Java Technology Stack
www.javastack.cn
Follow to read more quality articles
Encryption algorithms can generally be divided into: reversible encryption and irreversible encryption. Reversible encryption can further be divided into: symmetric encryption and asymmetric encryption.
1. Irreversible Encryption
Common irreversible encryption algorithms include MD5
, HMAC
, SHA1
, SHA-224
, SHA-256
, SHA-384
, and SHA-512
. Among them, SHA-224
, SHA-256
, SHA-384
, and SHA-512
can collectively be referred to as SHA2
encryption algorithms. The security of SHA
encryption algorithms is higher than that of MD5
, and SHA2
encryption algorithms are more secure than SHA1
. The number following SHA
indicates the length of the encrypted string, where SHA1
will generate a 160
-bit message digest by default.
The biggest characteristic of irreversible encryption algorithms is the key, but HMAC
requires a key【manual dog head】.
Since these encryptions are irreversible, a common scenario is user password encryption, where the verification process confirms identity by comparing two encrypted strings for equality. There are many websites claiming to crack MD5
passwords, and the principle is similar: they have a huge resource library containing many strings and their corresponding MD5
encrypted strings. If your password complexity is low, there is a high chance it can be verified.
1.1 MD5
MD5 Message-Digest Algorithm is a widely used cryptographic hash function that produces a 128-bit (16-byte) hash value, used to ensure the integrity of information during transmission.
The MD5
algorithm has the following characteristics:
1. Compression: Regardless of the length of the data, the calculated MD5
value length is the same.
2. Easy Computation: The MD5
value can be easily computed from the original data.
3. Resistance to Modification: Even if one byte is modified, the computed MD5
value will differ greatly.
4. Collision Resistance: Knowing the data and MD5
value, the probability of finding the same MD5
value from different original data is very low.
1public static String md5(String text) {
2 MessageDigest messageDigest = null;
3 try {
4 messageDigest = MessageDigest.getInstance("MD5");
5 } catch (NoSuchAlgorithmException e) {
6 e.printStackTrace();
7 }
8 byte[] bytes = messageDigest.digest(text.getBytes());
9 return Hex.encodeHexString(bytes);
10}
1.2 SHA Series
Secure Hash Algorithm (SHA) is a family of cryptographic hash functions, certified by FIPS as secure hashing algorithms. It can compute a fixed-length string (also known as a message digest) corresponding to a digital message, with a high probability that different messages correspond to different strings.
On August 17, 2005, at the end of the CRYPTO conference, Wang Xiaoyun, Yao Qizhi, and Yao Chufeng published a more efficient attack method on SHA-1 that can find collisions within the computational complexity of 2 to the power of 63.
This means that SHA-1
encryption algorithms have a possibility of collision, although it is very small.
1public static String sha256(String text) {
2 MessageDigest messageDigest = null;
3 try {
4 messageDigest = MessageDigest.getInstance("SHA-256");
5 } catch (NoSuchAlgorithmException e) {
6 e.printStackTrace();
7 }
8 byte[] bytes = messageDigest.digest(text.getBytes());
9 return Hex.encodeHexString(bytes);
10}
1.3 HMAC Series
HMAC stands for Hash-based Message Authentication Code, a method of message authentication based on hash functions and keys proposed by H. Krawezyk, M. Bellare, and R. Canetti in 1996, published as RFC2104 in 1997, and widely used in IPSec and other network protocols (such as SSL). It has become a de facto Internet security standard and can be bundled with any iterative hash function.
The HMAC algorithm is more like an encryption algorithm as it introduces a key, and its security no longer relies solely on the hash algorithm used.
1public static String hmacSha256(String text, SecretKeySpec sk) {
2 Mac mac = null;
3 try {
4 mac = Mac.getInstance("HmacSHA256");
5 } catch (NoSuchAlgorithmException e) {
6 e.printStackTrace();
7 }
8 try {
9 mac.init(sk);
10 } catch (InvalidKeyException e) {
11 e.printStackTrace();
12 }
13 byte[] rawHmac = mac.doFinal(text.getBytes());
14 return new String(Base64.encodeBase64(rawHmac));
15}
If you want to use irreversible encryption, it is recommended to use SHA256
, SHA384
, SHA512
, as well as HMAC-SHA256
, HMAC-SHA384
, and HMAC-SHA512
.
2. Symmetric Encryption Algorithms
Symmetric encryption algorithms are among the earliest algorithms, using the same key for both data encryption and decryption, which leads to difficulties in key management. Common symmetric encryption algorithms include DES
, 3DES
, AES128
, AES192
, and AES256
(the default installed JDK
does not support AES256
, requiring the installation of the corresponding jce
patch to upgrade jce1.7
, jce1.8
). The number following AES
indicates the key length. The security of symmetric encryption algorithms is relatively low, making them suitable for encryption and decryption in internal network environments.
2.1 DES
DES
is a typical algorithm in the field of symmetric encryption algorithms, with a default key length of 56
bits.
1// Encryption
2public static String encrypt(byte[] dataSource, String password) {
3 try {
4 SecureRandom random = new SecureRandom();
5 DESKeySpec desKeySpec = new DESKeySpec(password.getBytes());
6 // Create a key factory and convert DESKeySpec into
7 SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
8 SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
9 // The Cipher object actually performs the encryption operation
10 Cipher cipher = Cipher.getInstance("DES");
11 // Initialize the Cipher object with the key
12 cipher.init(Cipher.ENCRYPT_MODE, secretKey, random);
13 // Perform the encryption operation
14 return Base64.encodeBase64String(cipher.doFinal(dataSource));
15 } catch (Throwable e) {
16 e.printStackTrace();
17 }
18 return null;
19}
// Decryption
20public static String decrypt(String src, String password) throws Exception {
21 // DES algorithm requires a trusted random number source
22 SecureRandom random = new SecureRandom();
23 // Create a DESKeySpec object
24 DESKeySpec desKeySpec = new DESKeySpec(password.getBytes());
25 // Create a key factory
26 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
27 // Convert DESKeySpec into SecretKey object
28 SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
29 // The Cipher object actually performs the decryption operation
30 Cipher cipher = Cipher.getInstance("DES");
31 // Initialize the Cipher object with the key
32 cipher.init(Cipher.DECRYPT_MODE, secretKey, random);
33 // Begin the decryption operation
34 return new String(cipher.doFinal(Base64.decodeBase64(src)));
35}
2.2 3DES
3DES
(Triple DES) is an encryption algorithm transitioning from DES
to AES
, using three 56-bit keys to encrypt data three times. It is a more secure variant of DES
, designed through a combination of block methods. Compared to the original DES
, 3DES
is more secure, with a default key length of 168
bits, and can also choose 128
bits.
1public static String encryptThreeDESECB(String src, String key) {
2 try {
3 DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
4 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
5 SecretKey securekey = keyFactory.generateSecret(dks);
6
7 Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
8 cipher.init(Cipher.ENCRYPT_MODE, securekey);
9 byte[] b = cipher.doFinal(src.getBytes("UTF-8"));
10
11 String ss = new String(Base64.encodeBase64(b));
12 ss = ss.replaceAll("\+", "-");
13 ss = ss.replaceAll("/", "_");
14 return ss;
15 } catch(Exception ex) {
16 ex.printStackTrace();
17 return src;
18 }
19}
public static String decryptThreeDESECB(String src, String key) {
22 try {
23 src = src.replaceAll("-", "+");
24 src = src.replaceAll("_", "/");
25 byte[] bytesrc = Base64.decodeBase64(src.getBytes("UTF-8"));
26 // Decryption key
27 DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
28 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
29 SecretKey securekey = keyFactory.generateSecret(dks);
30
31 // Cipher object performs decryption
32 Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
33 cipher.init(Cipher.DECRYPT_MODE, securekey);
34 byte[] retByte = cipher.doFinal(bytesrc);
35
36 return new String(retByte, "UTF-8");
37 } catch(Exception ex) {
38 ex.printStackTrace();
39 return src;
40 }
41}
2.3 AES
AES
, the Advanced Encryption Standard, effectively resists all known attacks against DES
. The default key length is 128
bits, with options for 192
bits and 256
bits. Here, it’s worth mentioning that this bit refers to bits.
1private static final String defaultCharset = "UTF-8";
2private static final String KEY_AES = "AES";
3private static final String KEY_MD5 = "MD5";
4private static MessageDigest md5Digest;
5static {
6 try {
7 md5Digest = MessageDigest.getInstance(KEY_MD5);
8 } catch (NoSuchAlgorithmException e) {
9
10 }
11}
12/**
13 * Encryption
14 */
15public static String encrypt(String data, String key) {
16 return doAES(data, key, Cipher.ENCRYPT_MODE);
17}
18/**
19 * Decryption
20 */
21public static String decrypt(String data, String key) {
22 return doAES(data, key, Cipher.DECRYPT_MODE);
23}
24
25/**
26 * Encryption and Decryption
27 */
29private static String doAES(String data, String key, int mode) {
30 try {
31 boolean encrypt = mode == Cipher.ENCRYPT_MODE;
32 byte[] content;
33 if (encrypt) {
34 content = data.getBytes(defaultCharset);
35 } else {
36 content = Base64.decodeBase64(data.getBytes());
37 }
38 SecretKeySpec keySpec = new SecretKeySpec(md5Digest.digest(key.getBytes(defaultCharset)), KEY_AES);
39 Cipher cipher = Cipher.getInstance(KEY_AES); // Create a cipher
40 cipher.init(mode, keySpec); // Initialize
41 byte[] result = cipher.doFinal(content);
42 if (encrypt) {
43 return new String(Base64.encodeBase64(result));
44 } else {
45 return new String(result, defaultCharset);
46 }
47 } catch (Exception e) {
48 }
49 return null;
50}
Recommended symmetric encryption algorithms include: AES128
, AES192
, AES256
.
3. Asymmetric Encryption Algorithms
Asymmetric encryption algorithms use two keys, which are completely different but perfectly matched. Only the matching pair of public and private keys can complete the encryption and decryption process of plaintext. Common asymmetric encryptions include RSA
, SM2
, etc.
3.1 RSA
RSA
keys are at least 500 bits long, and it is generally recommended to use 1024 bits.
1// Asymmetric key algorithm
2public static final String KEY_ALGORITHM = "RSA";
3
4/**
5 * The default key length for DH algorithm is 1024
6 * Key length must be a multiple of 64, between 512 and 65536 bits
7 */
8private static final int KEY_SIZE = 1024;
9// Public Key
10private static final String PUBLIC_KEY = "RSAPublicKey";
11// Private Key
12private static final String PRIVATE_KEY = "RSAPrivateKey";
13/**
14 * Initialize key pair
15 *
16 * @return Map of party A's keys
17 */
18public static Map<String, Object> initKey() throws Exception {
19 // Instantiate key generator
20 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
21 // Initialize key generator
22 keyPairGenerator.initialize(KEY_SIZE);
23 // Generate key pair
24 KeyPair keyPair = keyPairGenerator.generateKeyPair();
25 // Party A's public key
26 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
27 // Party A's private key
28 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
29 // Store keys in map
30 Map<String, Object> keyMap = new HashMap<String, Object>();
31 keyMap.put(PUBLIC_KEY, publicKey);
32 keyMap.put(PRIVATE_KEY, privateKey);
33 return keyMap;
34}
35/**
36 * Encrypt with private key
37 *
38 * @param data Data to be encrypted
39 * @param key Key
40 * @return byte[] Encrypted data
41 */
42public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception {
43
44 // Get private key
45 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
46 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
47 // Generate private key
48 PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
49 // Data encryption
50 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
51 cipher.init(Cipher.ENCRYPT_MODE, privateKey);
52 return cipher.doFinal(data);
53}
54
55/**
56 * Encrypt with public key
57 *
58 * @param data Data to be encrypted
59 * @param key Key
60 * @return byte[] Encrypted data
61 */
62public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception {
63
64 // Instantiate key factory
65 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
66 // Initialize public key
67 // Key material conversion
68 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
69 // Generate public key
70 PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
71 // Data encryption
72 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
73 cipher.init(Cipher.ENCRYPT_MODE, pubKey);
74 return cipher.doFinal(data);
75}
76
77/**
78 * Decrypt with private key
79 *
80 * @param data Data to be decrypted
81 * @param key Key
82 * @return byte[] Decrypted data
83 */
84public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws Exception {
85 // Get private key
86 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
87 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
88 // Generate private key
89 PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
90 // Data decryption
91 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
92 cipher.init(Cipher.DECRYPT_MODE, privateKey);
93 return cipher.doFinal(data);
94}
95
96/**
97 * Decrypt with public key
98 *
99 * @param data Data to be decrypted
100 * @param key Key
101 * @return byte[] Decrypted data
102 */
103public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception {
104
105 // Instantiate key factory
106 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
107 // Initialize public key
108 // Key material conversion
109 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
110 // Generate public key
111 PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
112 // Data decryption
113 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
114 cipher.init(Cipher.DECRYPT_MODE, pubKey);
115 return cipher.doFinal(data);
116}
117
118/**
119 * Get private key
120 *
121 * @param keyMap Key map
122 * @return byte[] Private key
123 */
124public static byte[] getPrivateKey(Map<String, Object> keyMap) {
125 Key key = (Key) keyMap.get(PRIVATE_KEY);
126 return key.getEncoded();
127}
128
129/**
130 * Get public key
131 *
132 * @param keyMap Key map
133 * @return byte[] Public key
134 */
135public static byte[] getPublicKey(Map<String, Object> keyMap) throws Exception {
136 Key key = (Key) keyMap.get(PUBLIC_KEY);
137 return key.getEncoded();
138}
4. Encryption Salt
Encryption salt is a commonly heard concept; it is a random string used to concatenate with our encrypted string before encryption. Salting is mainly to enhance the security of the encrypted string. If there is a salted encrypted string, even if a hacker obtains this encrypted string through certain means, what they retrieve is not our original string, but a combination of the original string and the salt, which increases the string’s security.
Some algorithms mentioned in this article are sourced from the internet and can be copied for use directly.
Recommended encryption algorithms include:
-
Irreversible encryption:
SHA256
,SHA384
,SHA512
, as well asHMAC-SHA256
,HMAC-SHA384
,HMAC-SHA512
-
Symmetric encryption algorithms:
AES
,3DES
-
Asymmetric encryption algorithms:
RSA
Click “Read Original” to Access the Complete Interview Questions!