I heard that wechat search “Java fish” will change strong oh!

This article is in Java Server, which contains my complete series of Java articles, can be read for study or interview

(I) Encryption algorithm

Information encryption is now almost all projects need to use technology, identity authentication, single sign-on, information communication, payment and other scenarios often need to use encryption algorithm, the so-called encryption algorithm, is the original plaintext through a series of algorithm operations into ciphertext. Next, we will introduce some commonly used encryption algorithms at present. This period does not involve the bottom layer of the algorithm, but mainly introduces the application and shows the code.

If you just want to understand how it works, you can skip the code, which you can use directly.

(2) MD5 algorithm

To be precise, MD5 is not an encryption algorithm, but a digest algorithm. MD5 can output a string of 128bits in plaintext, which cannot be converted to plaintext. Some MD5 decryption websites on the Internet only save the CORRESPONDING MD5 strings of some strings, and find out the original text through the MD5 strings that have been recorded.

In several projects I’ve worked on, I’ve often seen MD5 used for encryption. For example, for password encryption, after a password is generated, MD5 is used to generate a 128-bit string and save it in the database. After the user enters the password, MD5 string is generated first and then compared in the database. Therefore, we cannot retrieve the original password when retrieving it, because the plaintext password is not saved at all.

public class MD5 {
    /** * generate MD5 *@param str
     * @return* /
    public String encode(String str) {
        byte[] result = null;
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(str.getBytes("UTF-8"));
            result = md.digest();

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return parseByte2HexStr(result);
    }

    /** * convert binary to hexadecimal **@param buf
     * @return* /
    private String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        MD5 md5=new MD5();
        String content = "The test the test"; System.out.println(md5.encode(content)); }}Copy the code

(3) SHA1 algorithm

SHA1 is a similar message digest algorithm to MD5, but it is more secure than MD5.

public class SHA1 {
    public String encode(String str) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(str.getBytes("utf-8"));
            byte[] digest = md.digest();
            return byteToHexString(digest);

        } catch (Exception e) {
            e.printStackTrace();
            return null; }}public static String byteToHexString(byte[] bytes) {
        return String.valueOf(Hex.encodeHex(bytes));
    }
    public static void main(String[] args) {
        SHA1 sha1 = new SHA1();
        String content = "The test the test"; System.out.println(sha1.encode(content)); }}Copy the code

(4) AES algorithm

AES is a common symmetric encryption algorithm. Symmetric encryption means that encryption with a key can be decrypted using the key. A state-owned enterprise I have contacted is using AES to realize integrated login internally. The third-party system provides an interface for receiving user information. The STATE-OWNED enterprise encrypts the user information through the AES and sends the user information to the third-party system through this interface. The third-party system performs login operations by itself. It is important to note that the key is very important. If the key is lost, information may be leaked.

public class AES {
    /** * converts the incoming plaintext to ciphertext *@param str
     * @param pwd
     * @return* /
    public String encode(String str,String pwd) {
        byte[] result = null;
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(pwd.getBytes());
            kgen.init(128, random);
            SecretKey secretKey = kgen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");

            // Create a password
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] byteContent = str.getBytes();
            result = cipher.doFinal(byteContent);

        } catch (Exception e) {
            return null;
        }

        return parseByte2HexStr(result);
    }

    /** * Converts the passed ciphertext to plain text *@param str
     * @param pwd
     * @return* /
    public String decode(String str,String pwd) {
        byte[] result = null;
        byte[] content = parseHexStr2Byte(str);
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(pwd.getBytes());
            kgen.init(128, random);
            SecretKey secretKey = kgen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");

            // Create a password
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key);
            result = cipher.doFinal(content);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        return new String(result);
    }

    /** * convert binary to hexadecimal **@param buf
     * @return* /
    private String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /** * convert hexadecimal to binary **@param hexStr
     * @return* /
    private byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1) {
            return null;
        }
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }
    
    public static void main(String[] args) {
        AES aes = new AES();
        String content = "Test encryption";
        // AES key length should be 16 bits (not required)
        String pwd = "javayznbjavayznb";

        / / encryption
        System.out.println("Before encryption:" + content);
      String encodeResultStr = aes.encode(content,pwd);
      System.out.println("After encryption:" + encodeResultStr);
      / / decryption
      String decodeResultStr = aes.decode(encodeResultStr,pwd);
      System.out.println("After decryption:"+ decodeResultStr); }}Copy the code

(5) DES

DES is also a symmetric encryption algorithm, but it is less secure, efficient, and flexible than AES. However, IT can ensure security. DES also requires encryption and decryption using keys, so keys are very important:

public class DES {
    /** * converts the incoming plaintext to ciphertext *@param str
     * @param pwd
     * @return* /
    public String encode(String str,String pwd) {
        byte[] result = null;
        try {
            DESKeySpec keySpec = new DESKeySpec(pwd.getBytes());
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey key = keyFactory.generateSecret(keySpec);

            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] byteContent = str.getBytes();
            result = cipher.doFinal(byteContent);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        return parseByte2HexStr(result);
    }

    /** * Converts the passed ciphertext to plain text *@param str
     * @param pwd
     * @return* /
    public String decode(String str,String pwd) {
        byte[] result = null;
        byte[] content = parseHexStr2Byte(str);
        try {
            DESKeySpec keySpec = new DESKeySpec(pwd.getBytes());
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey key = keyFactory.generateSecret(keySpec);

            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key);
            result = cipher.doFinal(content);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        return new String(result);
    }

    /** * convert binary to hexadecimal **@param buf
     * @return* /
    private String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /** * convert hexadecimal to binary **@param hexStr
     * @return* /
    private byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1) {
            return null;
        }
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    public static void main(String[] args) {
        DES des = new DES();
        String content = "The test the test";
        // The key length of DES must be 8 bits (if the key length is less than 8 bits, an error will be reported. After 8 bits, the encryption result will not be affected)
        String pwd = "javayznb";
        / / encryption
        System.out.println("Before encryption:" + content);
        String encodeResultStr = des.encode(content,pwd);
        System.out.println("After encryption:" + encodeResultStr);
        / / decryption
        String decodeResultStr = des.decode(encodeResultStr,pwd);
        System.out.println("After decryption:"+ decodeResultStr); }}Copy the code

(6) of the RSA

RSA is the most influential public key encryption algorithm and can be used for encryption and signature checking. The encryption method used when paying treasure pays docking is RSA. In RSA, there is a pair of keys called public key and private key. The private key is stored by an individual, and the public key may be held by multiple people.

The main application scenarios of RSA are encryption and check, not to mention encryption. Check means that messages are signed using private keys so that messages cannot be tampered with or forged.

Encryption mode: User B sends encrypted data to user A

1. A generates A public key and A private key. The private key is reserved and the public key can be obtained by anyone.

2. B gets the public key and encrypts the data using the public key

3. User A receives the ciphertext and decrypts it using the private key.

1. User A generates A public key and A private key. The private key is kept by user A, and the public key can be obtained by anyone.

2. User A uses the private key to sign the message and sends the signed message to user B.

3. B checks the public key. If true is returned, it indicates that the message was sent from A and has not been tampered with.

public class TestRSA {

    /** * The maximum encrypted plaintext size of RSA */
    private static final int MAX_ENCRYPT_BLOCK = 117;

    /** * Maximum size of RSA ciphertext */
    private static final int MAX_DECRYPT_BLOCK = 128;

    /** * get the key pair **@returnThe key to * /
    public static KeyPair getKeyPair(a) throws Exception {
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
        generator.initialize(1024);
        return generator.generateKeyPair();
    }

    /** * get the private key **@paramPrivateKey privateKey character string *@return* /
    public static PrivateKey getPrivateKey(String privateKey) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
        return keyFactory.generatePrivate(keySpec);
    }

    /** * Get public key **@paramPublicKey publicKey character string *@return* /
    public static PublicKey getPublicKey(String publicKey) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
        return keyFactory.generatePublic(keySpec);
    }

    /** * RSA encryption **@paramData Indicates the data to be encrypted@paramPublicKey public key *@return* /
    public static String encrypt(String data, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        int inputLen = data.getBytes().length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        // Encrypt data in segments
        while (inputLen - offset > 0) {
            if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        // Get the encrypted content encoded using Base64 and converted to a string using UTF-8 standards
        // An encrypted string
        return new String(Base64.encodeBase64String(encryptedData));
    }

    /** * RSA decryption **@paramData Data to be decrypted *@paramPrivateKey private key *@return* /
    public static String decrypt(String data, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] dataBytes = Base64.decodeBase64(data);
        int inputLen = dataBytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        // decrypt data in segments
        while (inputLen - offset > 0) {
            if (inputLen - offset > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        // The decrypted content
        return new String(decryptedData, "UTF-8");
    }

    /** ** signature **@paramData Data to be signed *@paramPrivateKey private key *@returnSignature * /
    public static String sign(String data, PrivateKey privateKey) throws Exception {
        byte[] keyBytes = privateKey.getEncoded();
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey key = keyFactory.generatePrivate(keySpec);
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initSign(key);
        signature.update(data.getBytes());
        return new String(Base64.encodeBase64(signature.sign()));
    }

    /** * check the signature **@paramSrcData The original string *@paramPublicKey public key *@paramSign the signature *@returnCheck whether the visa is approved */
    public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
        byte[] keyBytes = publicKey.getEncoded();
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey key = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(key);
        signature.update(srcData.getBytes());
        return signature.verify(Base64.decodeBase64(sign.getBytes()));
    }

    public static void main(String[] args) {
        try {
            // Generate a key pair
            KeyPair keyPair = getKeyPair();
            String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
            String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
            System.out.println("The private key." + privateKey);
            System.out.println("Public." + publicKey);
            / / RSA encryption
            String data = "Text content to be encrypted";
            String encryptData = encrypt(data, getPublicKey(publicKey));
            System.out.println("Encrypted content :" + encryptData);
            / / RSA decryption
            String decryptData = decrypt(encryptData, getPrivateKey(privateKey));
            System.out.println("Decrypted content :" + decryptData);
            / / RSA signature
            String sign = sign(data, getPrivateKey(privateKey));
            System.out.println("Signed:"+sign);
            / / RSA attestation
            boolean result = verify(data, getPublicKey(publicKey), sign);
            System.out.print("Inspection Result :" + result);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.print("Encryption and decryption exception"); }}}Copy the code

(7) Summary

Encryption is an issue that comes up both at work and in an interview and must be mastered. Do not require encryption code written by hand, but to know what each encryption algorithm is doing, is what kind of effect.