实现Java的SM4对称加密算法

1. 简介

SM4是一种国内自主设计的对称加密算法,具有高效、安全的特点,广泛应用于各种加密场景。本文将介绍如何使用Java实现SM4对称加密算法。

2. 流程图

flowchart TD
    A[生成密钥] --> B[加密明文]
    B --> C[解密密文]

3. 生成密钥

在SM4算法中,密钥长度为128位(16字节),我们可以使用Java的随机数生成器生成一个随机的128位密钥。

import java.security.SecureRandom;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

public class SM4KeyGenerator {
    public static SecretKey generateKey() throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("SM4");
        SecureRandom secureRandom = new SecureRandom();
        keyGenerator.init(secureRandom);
        return keyGenerator.generateKey();
    }
}

4. 加密明文

在SM4算法中,明文需要先进行填充,然后使用密钥对其进行加密。以下是一个示例代码,演示了如何使用SM4算法加密明文。

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class SM4Encryption {
    public static byte[] encrypt(byte[] plaintext, SecretKey key) throws Exception {
        Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding");
        byte[] iv = generateRandomIV();
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
        byte[] encrypted = cipher.doFinal(plaintext);
        return iv + encrypted;
    }

    private static byte[] generateRandomIV() {
        // 生成一个随机的16字节IV
        byte[] iv = new byte[16];
        SecureRandom secureRandom = new SecureRandom();
        secureRandom.nextBytes(iv);
        return iv;
    }
}

5. 解密密文

在SM4算法中,密文需要解密,然后去除填充,得到原始的明文。以下是一个示例代码,演示了如何使用SM4算法解密密文。

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class SM4Decryption {
    public static byte[] decrypt(byte[] ciphertext, SecretKey key) throws Exception {
        Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding");
        byte[] iv = new byte[16];
        System.arraycopy(ciphertext, 0, iv, 0, 16);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
        byte[] decrypted = cipher.doFinal(ciphertext, 16, ciphertext.length - 16);
        return decrypted;
    }
}

6. 完整示例

下面是一个完整的示例代码,演示了如何生成密钥、加密明文、解密密文。

import javax.crypto.SecretKey;

public class SM4Demo {
    public static void main(String[] args) throws Exception {
        String plaintext = "Hello, World!";
        byte[] plaintextBytes = plaintext.getBytes("UTF-8");
        
        // 生成密钥
        SecretKey key = SM4KeyGenerator.generateKey();
        
        // 加密明文
        byte[] ciphertext = SM4Encryption.encrypt(plaintextBytes, key);

        // 解密密文
        byte[] decrypted = SM4Decryption.decrypt(ciphertext, key);
        String decryptedText = new String(decrypted, "UTF-8");
        
        System.out.println("明文: " + plaintext);
        System.out.println("密文: " + bytesToHex(ciphertext));
        System.out.println("解密结果: " + decryptedText);
    }
    
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }
}

7. 序列图

sequenceDiagram
    participant Developer
    participant Newbie

    Note left of Developer: 生成密钥
    Developer ->> Newbie: generateKey()
    Note left of Newbie: 生成密钥

    Note left of Developer: 加密明文
    Developer ->> Newbie: encrypt(plaintext, key)
    Note left of Newbie: 加密明文