Artistic ~SM4 implementation of Java encryption and decryption

Keywords: Java security

Concept introduction of domestic SM4 encryption and decryption algorithm

SMS4 algorithm is an encryption algorithm used in WAPI wireless network standard widely used in China. It is a 32 round iterative packet encryption algorithm with unbalanced Feistel structure. Its key length and packet length are 128. The algorithm used in the encryption and decryption process of SMS4 algorithm is exactly the same. The only difference is that the decryption key of the algorithm is obtained by reverse transformation of its encryption key.
SMS4 block encryption algorithm is a block encryption algorithm used in China's wireless standard. In 2012, it has been determined as the national cryptographic industry standard by the State Administration of Commercial Cryptography. The standard number is GM/T 0002-2012 and is renamed SM4 algorithm. It is used as the national cryptographic industry standard together with SM2 elliptic curve public key cryptography algorithm and SM3 cryptographic hash algorithm, It plays an extremely important role in China's password industry.
The packet length of SMS4 algorithm is 128bit, and the key length is also 128bit. The encryption and decryption algorithms adopt 32 rounds of unbalanced Feistel iterative structure, which first appears in the key expansion algorithm of block cipher LOKI. SMS4 adds a reverse order transformation after 32 rounds of nonlinear iteration, so that the decryption algorithm can be consistent with the encryption algorithm only if the decryption key is in the reverse order of the encryption key. The structure of SMS4 encryption and decryption algorithm is exactly the same, except that when using round key, the decryption key is in the reverse order of the encryption key.
S-box is a component of block cipher constructed by nonlinear transformation. It is mainly designed to realize the characteristics and design of confusion in the process of block cipher. At the beginning of the design, the S-box in SMS4 algorithm is completely carried out according to the design standards of European and American block ciphers. Its method is the affine function inverse mapping composite method which can well resist the difference attack.

SM4 encryption algorithm application scenario

SM4 is often used for data transmission encryption of government systems. For example, this algorithm can be used when we transmit parameters from the front end to the background. Encrypt the parameter data, then decrypt the encrypted data in the background and store it in the database to ensure that the data will not be leaked during data transmission.

SM4Utils

public class Sm4Utils {

    private static final String ENCODING = "UTF-8";
    public static final String ALGORIGTHM_NAME = "SM4";
    public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS7Padding";
    public static final int DEFAULT_KEY_SIZE = 128;

    public Sm4Utils() {
    }

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     *  @Description:Generate ecb code
     */
    private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throws Exception {
        Cipher cipher = Cipher.getInstance(algorithmName,BouncyCastleProvider.PROVIDER_NAME);
        Key sm4Key = new SecretKeySpec(key, ALGORIGTHM_NAME);
        cipher.init(mode, sm4Key);
        return cipher;
    }

    /**
     *  @Description:Automatic key generation
     */
    public static byte[] generateKey() throws Exception {
        return generateKey(DEFAULT_KEY_SIZE);
    }

    public static byte[] generateKey(int keySize) throws Exception {
        KeyGenerator kg = KeyGenerator.getInstance(ALGORIGTHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
        kg.init(keySize, new SecureRandom());
        return kg.generateKey().getEncoded();
    }


    /**
     *  @Description:encryption
     */
    public static String encryptEcb(String hexKey, String paramStr, String charset) throws Exception {
        String cipherText = "";
        if (null != paramStr && !"".equals(paramStr)) {
            byte[] keyData = ByteUtils.fromHexString(hexKey);
            charset = charset.trim();
            if (charset.length() <= 0) {
                charset = ENCODING;
            }
            byte[] srcData = paramStr.getBytes(charset);
            byte[] cipherArray = encrypt_Ecb_Padding(keyData, srcData);
            cipherText = ByteUtils.toHexString(cipherArray);
        }
        return cipherText;
    }

    /**
     *  @Description:Encryption mode ecb
     */
    public static byte[] encrypt_Ecb_Padding(byte[] key, byte[] data) throws Exception {
        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);
        byte[] bs = cipher.doFinal(data);
        return bs;
    }

    /**
     *  @Description:sm4 decrypt
     */
    public static String decryptEcb(String hexKey, String cipherText, String charset) throws Exception {
        String decryptStr = "";
        byte[] keyData = ByteUtils.fromHexString(hexKey);
        byte[] cipherData = ByteUtils.fromHexString(cipherText);
        byte[] srcData = decrypt_Ecb_Padding(keyData, cipherData);
        charset = charset.trim();
        if (charset.length() <= 0) {
            charset = ENCODING;
        }
        decryptStr = new String(srcData, charset);
        return decryptStr;
    }

    /**
     *  @Description:decrypt
     */
    public static byte[] decrypt_Ecb_Padding(byte[] key, byte[] cipherText) throws Exception {
        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(cipherText);
    }

    /**
     *  @Description:password verifiers 
     */
    public static boolean verifyEcb(String hexKey,String cipherText,String paramStr) throws Exception {
        boolean flag = false;
        byte[] keyData = ByteUtils.fromHexString(hexKey);
        byte[] cipherData = ByteUtils.fromHexString(cipherText);
        byte[] decryptData = decrypt_Ecb_Padding(keyData,cipherData);
        byte[] srcData = paramStr.getBytes(ENCODING);
        flag = Arrays.equals(decryptData,srcData);
        return flag;
    }

    /**
     *  @Description:Test class
    */
    public static void main(String[] args) {
        try {
            String json = "{\"name\":\"color\",\"sex\":\"man\"}";
            // Custom 32-bit hex key
            String key = "cc9368581322479ebf3e79348a2757d9";
            String cipher = Sm4Utils.encryptEcb(key, json,ENCODING);
            System.out.println(cipher);
            System.out.println(Sm4Utils.verifyEcb(key, cipher, json));
            json = Sm4Utils.decryptEcb(key, cipher,ENCODING);
            System.out.println(json);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

Posted by Graphi on Thu, 02 Dec 2021 18:47:41 -0800