Must-Ask Interview Questions: Common Encryption Algorithms

Must-Ask Interview Questions: Common Encryption Algorithms

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 as HMAC-SHA256, HMAC-SHA384, HMAC-SHA512

  • Symmetric encryption algorithms: AES, 3DES

  • Asymmetric encryption algorithms: RSA

Recent Hot Articles:
1、Big News! The Latest Release of the “Java Development Manual (Songshan Edition)”
2、Break Your Cognition! Java Null Pointer Can Actually Be Played Like This
3、Review of 35 Apache Top Projects, I’m Impressed…
4、Spring Boot is Fierce, Releasing 3 Versions at Once!
5、How to Quickly Integrate Redis with Spring Boot?
6、Review of 6 Java Technologies That Have Been Phased Out, Once Flourished!
7、Spring Boot Redis Implementation of Distributed Lock, So Nice!
8、Spring Boot Has Ousted Maven and Embraced Gradle!
9、A New Colleague Doesn’t Know How to Use Lombok!
10、A Colleague Wrote a Hidden Bug, and I Troubleshot for 3 Days!
Scan to FollowJava Technology StackPublic Account for More Quality Content.

Must-Ask Interview Questions: Common Encryption Algorithms

Click “Read Original” to Access the Complete Interview Questions!

Leave a Comment