package minsecurity.crypto; import org.bouncycastle.jce.provider.BouncyCastleProvider; import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.security.*; /* * @Author: hongyu guo * @Description: sm4算法 * @Version: 1.0.0 * @Date: 16:26 2021/03/04 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ public class SM4 { static { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); } public static final String ALGORITHM_NAME = "SM4"; public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding"; public static final String ALGORITHM_NAME_ECB_NOPADDING = "SM4/ECB/NoPadding"; public static final String ALGORITHM_NAME_CBC_PADDING = "SM4/CBC/PKCS5Padding"; public static final String ALGORITHM_NAME_CBC_NOPADDING = "SM4/CBC/NoPadding"; /** * SM4算法目前只支持128位(即密钥16字节) */ public static final int DEFAULT_KEY_SIZE = 128; public static byte[] generateKey() throws NoSuchAlgorithmException, NoSuchProviderException { return generateKey(DEFAULT_KEY_SIZE); } public static byte[] generateKey(int keySize) throws NoSuchAlgorithmException, NoSuchProviderException { KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME); kg.init(keySize, new SecureRandom()); return kg.generateKey().getEncoded(); } public static byte[] encrypt_ECB_Padding(byte[] key, byte[] data) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { Cipher cipher = generateECBCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key); return cipher.doFinal(data); } public static byte[] decrypt_ECB_Padding(byte[] key, byte[] cipherText) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException { Cipher cipher = generateECBCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key); return cipher.doFinal(cipherText); } public static byte[] encrypt_ECB_NoPadding(byte[] key, byte[] data) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { Cipher cipher = generateECBCipher(ALGORITHM_NAME_ECB_NOPADDING, Cipher.ENCRYPT_MODE, key); return cipher.doFinal(data); } public static byte[] decrypt_ECB_NoPadding(byte[] key, byte[] cipherText) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException { Cipher cipher = generateECBCipher(ALGORITHM_NAME_ECB_NOPADDING, Cipher.DECRYPT_MODE, key); return cipher.doFinal(cipherText); } public static byte[] encrypt_CBC_Padding(byte[] key, byte[] iv, byte[] data) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException { Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.ENCRYPT_MODE, key, iv); return cipher.doFinal(data); } public static byte[] decrypt_CBC_Padding(byte[] key, byte[] iv, byte[] cipherText) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException { Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.DECRYPT_MODE, key, iv); return cipher.doFinal(cipherText); } public static byte[] encrypt_CBC_NoPadding(byte[] key, byte[] iv, byte[] data) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException { Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_NOPADDING, Cipher.ENCRYPT_MODE, key, iv); return cipher.doFinal(data); } public static byte[] decrypt_CBC_NoPadding(byte[] key, byte[] iv, byte[] cipherText) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException { Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_NOPADDING, Cipher.DECRYPT_MODE, key, iv); return cipher.doFinal(cipherText); } private static Cipher generateECBCipher(String algorithmName, int mode, byte[] key) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException { Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME); Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME); cipher.init(mode, sm4Key); return cipher; } private static Cipher generateCBCCipher(String algorithmName, int mode, byte[] key, byte[] iv) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException { Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME); Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); cipher.init(mode, sm4Key, ivParameterSpec); return cipher; } }