Common encryption methods in Java

1, Common encryption methods in Java
Base64 encryption algorithm (encoding method)
MD5 encryption (message digest algorithm, verifying information integrity)
Symmetric encryption algorithm
Asymmetric encryption algorithm
Digital signature algorithm
digital certificate
2, Classification
According to whether the encryption algorithm requires key s, there are two types:
Not based on key: Base64 algorithm, MD5
The key based ones are: symmetric encryption algorithm, asymmetric encryption algorithm, digital signature algorithm, digital certificate, HMAC, RC4 (symmetric encryption)
According to whether the encryption algorithm is reversible, it can be divided into two categories:
One way encryption algorithm (not decryptable): MD5, SHA, HMAC
Non single encryption algorithm (decryptable): BASE64, symmetric encryption algorithm, asymmetric encryption algorithm, digital signature algorithm, digital certificate
3, Algorithm Introduction
1. Symmetric encryption
Symmetric encryption is the fastest and simplest encryption method. Encryption and decryption use the same secret key. There are many kinds of symmetric encryption algorithms. Because of its high efficiency, it is widely used in the core of many encryption protocols.

Symmetric encryption usually uses a relatively small key, generally less than 256 bit s. Because the larger the key, the stronger the encryption, but the slower the encryption and decryption process. If you only use 1 bit to do this key, hackers can try to decrypt it with 0 first, otherwise they can use 1 solution; but if your key is 1 MB, hackers may never be able to decrypt it, but the process of encryption and decryption will take a long time. The size of the key should take into account both security and efficiency. It is a trade-off.

DES(Data Encryption Standard) and TripleDES are two implementations of symmetric encryption.

The basic algorithm of DES and TripleDES is the same, but TripleDES algorithm provides more key bits and higher encryption reliability.  
The key key used by DES is 8 bytes, and the initial vector IV is also 8 bytes.  
TripleDES uses a 24 byte key, and the initial vector IV is also 8 bytes.  
Both algorithms are based on 8 bytes as a block for encryption, one data block for encryption, one 8 bytes of plaintext encryption is also 8 bytes. If the plaintext length is not an integer multiple of 8 bytes, add a byte with a value of 0 to make up an integer multiple of 8 bytes. So the encrypted ciphertext length must be an integer multiple of 8 bytes

Here is an example:
 

import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.codec.binary.Base64;

public class DESDemo {
    // Algorithm name
    public static final String KEY_ALGORITHM = "DES";
    // Algorithm name / encryption mode / filling mode
    // DES has four working modes: ECB: electronic codebook mode, CBC: encrypted group link mode, CFB: encrypted feedback mode, OFB: output feedback mode
    public static final String CIPHER_ALGORITHM = "DES/ECB/NoPadding";

    /**
     *
     * Generate key key object
     *
     * @param KeyStr
     *            Key string
     * @return Key object
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws Exception
     */
    private static SecretKey keyGenerator(String keyStr) throws Exception {
        byte input[] = HexString2Bytes(keyStr);
        DESKeySpec desKey = new DESKeySpec(input);
        // Create a key factory, and use it to convert the DESKeySpec to
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey securekey = keyFactory.generateSecret(desKey);
        return securekey;
    }

    private static int parse(char c) {
        if (c >= 'a')
            return (c - 'a' + 10) & 0x0f;
        if (c >= 'A')
            return (c - 'A' + 10) & 0x0f;
        return (c - '0') & 0x0f;
    }

    // Conversion from hexadecimal string to byte array
    public static byte[] HexString2Bytes(String hexstr) {
        byte[] b = new byte[hexstr.length() / 2];
        int j = 0;
        for (int i = 0; i < b.length; i++) {
            char c0 = hexstr.charAt(j++);
            char c1 = hexstr.charAt(j++);
            b[i] = (byte) ((parse(c0) << 4) | parse(c1));
        }
        return b;
    }

    /**
     * Encrypt data
     *
     * @param data
     *            Data to be encrypted
     * @param key
     *            secret key
     * @return Encrypted data
     */
    public static String encrypt(String data, String key) throws Exception {
        Key deskey = keyGenerator(key);
        // Instantiate the Cipher object, which is used to complete the actual encryption operation
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        SecureRandom random = new SecureRandom();
        // Initialize Cipher object, set to encryption mode
        cipher.init(Cipher.ENCRYPT_MODE, deskey, random);
        byte[] results = cipher.doFinal(data.getBytes());
        // This part is to test the website online with encryption and decryption( http://tripledes.online-domain-tools.com/ )Check the hex result of
        for (int i = 0; i < results.length; i++) {
            System.out.print(results[i] + " ");
        }
        System.out.println();
        // Perform encryption operations. The encrypted results are usually transmitted in Base64 code
        return Base64.encodeBase64String(results);
    }

    /**
     * Decrypt data
     *
     * @param data
     *            Data to be decrypted
     * @param key
     *            secret key
     * @return Decrypted data
     */
    public static String decrypt(String data, String key) throws Exception {
        Key deskey = keyGenerator(key);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        // Initialize Cipher object, set to decryption mode
        cipher.init(Cipher.DECRYPT_MODE, deskey);
        // Perform decryption operation
        return new String(cipher.doFinal(Base64.decodeBase64(data)));
    }

    public static void main(String[] args) throws Exception {
        String source = "helloittx";
        System.out.println("original text: " + source);
        String key = "A1B2C3D4E5F60708";
        String encryptData = encrypt(source, key);
        System.out.println("After encryption: " + encryptData);
        String decryptData = decrypt(encryptData, key);
        System.out.println("After decryption: " + decryptData);
    }
}

2. Asymmetric encryption
Asymmetric encryption provides a very secure method for data encryption and decryption. It uses a pair of keys, public key and private key. The private key can only be safeguarded by one party and cannot be disclosed, while the public key can be sent to anyone who requests it. Asymmetric encryption uses one of these keys to encrypt, while decryption requires another key. For example, if you ask the bank for the public key, and the bank sends the public key to you, and you encrypt the message with the public key, then only the holder of the private key, the bank, can decrypt your message. Different from symmetric encryption, the bank does not need to send the private key through the network, so the security is greatly improved.

At present, the most commonly used asymmetric encryption algorithm is RSA algorithm, which was invented by Rivest, Shamir and Adleman in 1978. They were all at MIT at that time. Take a look at the following example:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.RSAPublicKeySpec;

import javax.crypto.Cipher;

import com.lxh.rsatest.HexUtil;

import Decoder.BASE64Decoder;
import Decoder.BASE64Encoder;

public class RSAEncrypt {
    /** Specifies that the encryption algorithm is DESede */
    private static String ALGORITHM = "RSA";
    /** Specify the size of the key */
    private static int KEYSIZE = 1024;
    /** Specify public key to store files */
    private static String PUBLIC_KEY_FILE = "public.keystore";
    /** Specify private key to store file */
    private static String PRIVATE_KEY_FILE = "private.keystore";

    /**
     * Generate key pair
     */
    private static void generateKeyPair() throws Exception {
        /** RSA The algorithm requires a trusted random number source */
        SecureRandom sr = new SecureRandom();
        /** Create a KeyPairGenerator object for RSA algorithm */
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);
        /** Initialize the KeyPairGenerator object with the random data source above */
        kpg.initialize(KEYSIZE, sr);
        /** Generate key pair */
        KeyPair kp = kpg.generateKeyPair();
        /** Get public key */
        Key publicKey = kp.getPublic();
        /** Get private key */
        Key privateKey = kp.getPrivate();
        /** Write the generated key to the file with the object stream */
        ObjectOutputStream oos1 = new ObjectOutputStream(new FileOutputStream(PUBLIC_KEY_FILE));
        ObjectOutputStream oos2 = new ObjectOutputStream(new FileOutputStream(PRIVATE_KEY_FILE));
        oos1.writeObject(publicKey);
        oos2.writeObject(privateKey);
        /** Clear cache, close file output stream */
        oos1.close();
        oos2.close();
    }

    /**
     * Generate key pair string
     */
    private static void generateKeyPairString() throws Exception {
        /** RSA The algorithm requires a trusted random number source */
        SecureRandom sr = new SecureRandom();
        /** Create a KeyPairGenerator object for RSA algorithm */
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);
        /** Initialize the KeyPairGenerator object with the random data source above */
        kpg.initialize(KEYSIZE, sr);
        /** Generate key pair */
        KeyPair kp = kpg.generateKeyPair();
        /** Get public key */
        Key publicKey = kp.getPublic();
        /** Get private key */
        Key privateKey = kp.getPrivate();
        /** Write the generated key to a file with a string */

        String algorithm = publicKey.getAlgorithm(); // Acquisition algorithm
        KeyFactory keyFact = KeyFactory.getInstance(algorithm);
        BigInteger prime = null;
        BigInteger exponent = null;

        RSAPublicKeySpec keySpec = (RSAPublicKeySpec) keyFact.getKeySpec(publicKey, RSAPublicKeySpec.class);

        prime = keySpec.getModulus();
        exponent = keySpec.getPublicExponent();
        System.out.println("Public key modulus:" + HexUtil.bytes2Hex(prime.toByteArray()));
        System.out.println("Public key index:" + HexUtil.bytes2Hex(exponent.toByteArray()));

        System.out.println(privateKey.getAlgorithm());
        RSAPrivateCrtKeySpec privateKeySpec = (RSAPrivateCrtKeySpec) keyFact.getKeySpec(privateKey,
                RSAPrivateCrtKeySpec.class);
        BigInteger privateModulus = privateKeySpec.getModulus();
        BigInteger privateExponent = privateKeySpec.getPrivateExponent();

        System.out.println("Private key modulus:" + HexUtil.bytes2Hex(privateModulus.toByteArray()));
        System.out.println("Private key index:" + HexUtil.bytes2Hex(privateExponent.toByteArray()));

    }

    /**
     * Encryption method source: source data
     */
    public static String encrypt(String source) throws Exception {
        generateKeyPair();
        /** Read the public key object in the file */
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
        Key key = (Key) ois.readObject();
        ois.close();

        String algorithm = key.getAlgorithm(); // Acquisition algorithm
        KeyFactory keyFact = KeyFactory.getInstance(algorithm);
        BigInteger prime = null;
        BigInteger exponent = null;
        if ("RSA".equals(algorithm)) { // If it's RSA encryption
            RSAPublicKeySpec keySpec = (RSAPublicKeySpec) keyFact.getKeySpec(key, RSAPublicKeySpec.class);
            prime = keySpec.getModulus();
            exponent = keySpec.getPublicExponent();

//          System.out.println (public key modulus:+ HexUtil.bytes2Hex(prime.toByteArray()));
//          System.out.println (public key index:+ HexUtil.bytes2Hex(exponent.toByteArray()));

        }

        /** Get Cipher object to realize RSA encryption of source data */
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] b = source.getBytes();
        /** Perform encryption operation */
        byte[] b1 = cipher.doFinal(b);
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(b1);
    }

    /**
     * cryptograph: ciphertext
     */
    public static String decrypt(String cryptograph) throws Exception {
        /** Read the private key object in the file */
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
        Key key = (Key) ois.readObject();

        String algorithm = key.getAlgorithm(); // Acquisition algorithm
        KeyFactory keyFact = KeyFactory.getInstance(algorithm);
        RSAPrivateCrtKeySpec privateKeySpec = (RSAPrivateCrtKeySpec) keyFact.getKeySpec(key,
                RSAPrivateCrtKeySpec.class);
        BigInteger privateModulus = privateKeySpec.getModulus();
        BigInteger privateExponent = privateKeySpec.getPrivateExponent();

//      System.out.println (private key modulus:+ HexUtil.bytes2Hex(privateModulus.toByteArray()));
//      System.out.println (private key index:+ HexUtil.bytes2Hex(privateExponent.toByteArray()));

        /** Get Cipher object and RSA decrypt the encrypted data with public key */
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        BASE64Decoder decoder = new BASE64Decoder();

        byte[] b1 = decoder.decodeBuffer(cryptograph);
        /** Perform decryption operation */
        byte[] b = cipher.doFinal(b1);
        return new String(b);
    }

    public static void main(String[] args) throws Exception {
        generateKeyPair(); //Generate file form public key and private key
        //generateKeyPairString(); / / generate public key and private key in string form

        String source = "Asymmetric encryption RSA";// String to encrypt

        String cryptograph = encrypt(source);// Generated ciphertext
        String hexCrypt = HexUtil.bytes2Hex(cryptograph.getBytes(), false);
        System.out.println("Generated ciphertext--->" + hexCrypt);

        String target = decrypt(HexUtil.hex2String(hexCrypt));// Decrypt ciphertext
        System.out.println("Decrypt ciphertext--->" + target);

    }
}

Although asymmetric encryption is very secure, it is very slow compared with symmetric encryption, so we still need to use symmetric encryption to send messages, but the key used by symmetric encryption can be sent out by asymmetric encryption.  
(1) Symmetric encryption and decryption use the same key, so the speed is fast, but because the key needs to be transmitted in the network, so the security is not high.  
(2) Asymmetric encryption uses a pair of keys, public key and private key, so the security is high, but the speed of encryption and decryption is slow.  
(3) The solution is to use asymmetric encryption public key to encrypt the symmetric encryption key, and then send it out.
 

3.Base64 encoding
What is the use of Base 64 Encoding? For example, you use the Simple Mail Transfer Protocol to send mail. Because this protocol is text-based, if the message contains a picture, we know that the storage format of the picture is binary data, not text format. We must encode the binary data into text format, and Base 64 Encoding is useful.

public void testJDKBase64(){
    String encoderStr = java.util.Base64.getEncoder().encodeToString(s.getBytes());
    System.out.println("encode :"+encoderStr);

    String decodeStr = new String(java.util.Base64.getDecoder().decode(encoderStr));
    System.out.println("decodeStr :"+decodeStr);
}

public void testCodecBase64(){
    String encoderStr = org.apache.commons.codec.binary.Base64.encodeBase64String(s.getBytes());
    System.out.println("encode :"+encoderStr);

    String decodeStr = new String(org.apache.commons.codec.binary.Base64.decodeBase64(encoderStr));
    System.out.println("decodeStr :"+decodeStr);
}

 

4.MD5 encryption
Message Digest Algorithm MD5 is a hash function widely used in the field of computer security to provide message integrity protection. The file number of the algorithm is RFC 1321 (R.Rivest,MIT Laboratory for Computer Science and RSA Data Security Inc. April 1992)

The full name of MD5 is message digest algorithm 5 (information digest algorithm). It was developed by Ronald L. Rivest of MIT Laboratory for Computer Science and RSA Data Security Inc. in the early 1990s and developed by MD2, MD3 and MD4.

MD5 is used to ensure complete and consistent information transmission. It is one of the hash algorithms widely used in computer, and MD5 is widely used in mainstream programming languages. The basic principle of hash algorithm is to calculate data (such as Chinese characters) as another fixed length value. The predecessor of MD5 is MD2, MD3 and MD4.

The function of MD5 is to "compress" large capacity information into a confidential format (that is, to transform a byte string of any length into a hexadecimal digit string of a certain length) before signing the private key with digital signature software.
 

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Java MD5 tool class of message digest algorithm, in fact, the implementation of other digest algorithms is similar
 */
public class MD5Util {
    /**
     * md5 digest encryption is performed on text. This algorithm is consistent with md5 digest generated by MySQL and JavaScript
     * @param plainText
     * @return The letters in the return value are lowercase
     */
    public static String md5(String plainText) {
        if (null == plainText) {
            plainText = "";
        }
        String MD5Str = "";
        try {
            // JDK 6 supports the following six message digest algorithms, which are case insensitive
            // md5,sha(sha-1),md2,sha-256,sha-384,sha-512
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(plainText.getBytes());
            byte b[] = md.digest();

            int i;

            StringBuilder builder = new StringBuilder(32);
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0)
                    i += 256;
                if (i < 16)
                    builder.append("0");
                builder.append(Integer.toHexString(i));
            }
            MD5Str = builder.toString();
            // LogUtil.println("result: " + buf.toString());// 32-bit encryption
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return MD5Str;
    }
    // A short version test
    public static void main(String[] args) {
        String m1 = md5("1");
        String m2 = md5(m1);
        /* Output as
         * m1=c4ca4238a0b923820dcc509a6f75849b
         * m2=28c8edde3d61a0411511d3b1866f0636
         */
        System.out.println("m1="+m1);
        System.out.println("m2="+m2);
    }
}

Usually we do not use MD5 encryption directly. Usually, the byte array generated by MD5 is handed over to Base64 for encryption to get the corresponding string.

5. Digital signature algorithm
Signature: security and anti repudiation
Digital signature: message digest algorithm with key (public key, private key)
Function:
1. Verify data integrity
2. Certification data source
3. Anti denial

Digital signature follows: private key signature, public key verification
Common digital signature algorithms: RSA, DSA, ECDSA

RSA introduction:

Is a classic algorithm, is the most widely used digital signature algorithm.

The key implementation of RSA digital signature algorithm is the same as that of RSA encryption algorithm. The name of the algorithm is called RSA. Key generation and conversion are the same.

RSA digital signature algorithm mainly includes MD and SHA.

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import org.apache.commons.codec.binary.Hex;

public class RSATest {
    public static final String src = "hello world";

    public static void main(String[] args) {
        jdkRSA();

    }

    /**
     * Using java jdk to implement rsa signature and signature verification
     */
    public static void jdkRSA() {
        try {
            // 1. Initialize key
            KeyPairGenerator keyPairGenerator = KeyPairGenerator
                    .getInstance("RSA");
            //Set the length of KEY
            keyPairGenerator.initialize(512);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            //Get public key
            RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
            //Get private key
            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();

            // 2. Sign
            //Sign with private key
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
                    rsaPrivateKey.getEncoded());
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            //Construct a privateKey
            PrivateKey privateKey = keyFactory
                    .generatePrivate(pkcs8EncodedKeySpec);
            //Declare signed objects
            Signature signature = Signature.getInstance("MD5withRSA");
            signature.initSign(privateKey);
            signature.update(src.getBytes());
            //Sign
            byte[] result = signature.sign();
            System.out.println("jdk rsa sign:" + Hex.encodeHexString(result));

            // 3. Verify signature
            //Verify signature with public key
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
                    rsaPublicKey.getEncoded());
            keyFactory = KeyFactory.getInstance("RSA");
            //Construct a publicKey
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            //Declare signing object
            signature = Signature.getInstance("MD5withRSA");
            signature.initVerify(publicKey);
            signature.update(src.getBytes());
            //Verify signature
            boolean bool = signature.verify(result);
            System.out.println("jdk rsa verify:" + bool);
        } catch (Exception e) {
            System.out.println(e.toString());
        }

    }

}

4, Application scenario

  1. Base64 application scenario: picture transcoding (applied to mail, img label, http encryption)
  2. MD5 application scenario: password encryption, imei encryption, file verification
  3. Asymmetric encryption: e-commerce order payment, bank related business

Tags: Java encoding Apache codec

Posted on Sun, 21 Jun 2020 23:47:32 -0400 by cwheel3915