第一:场景介绍
甲方要求,数据在传输过程中要加密。
第二:选择加解密方式:
这里面Android 和服务端都是选择SM4
第三:实现方式
服务端采用SpringBoot,在pom.xml 文件下添加依赖
org.bouncycastle bcprov-jdk15on 1.64
在Android 端同样添加依赖,在module 下面build.gradle
implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.64'
服务端SM4工具类
package com.wansun.datahouse.visit.utils;import org.apache.tomcat.util.buf.HexUtils;import org.bouncycastle.jce.provider.BouncyCastleProvider;import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.KeyGenerator;import javax.crypto.NoSuchPaddingException;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;import java.security.InvalidAlgorithmParameterException;import java.security.InvalidKeyException;import java.security.Key;import java.security.NoSuchAlgorithmException;import java.security.NoSuchProviderException;import java.security.SecureRandom;import java.security.Security;public class Sm4Util { 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"; public static final int DEFAULT_KEY_SIZE = 128; static { // 加入 BC 实现 Security.addProvider(new BouncyCastleProvider()); } private static byte[] generateKey() throws NoSuchAlgorithmException, NoSuchProviderException { return generateKey(DEFAULT_KEY_SIZE); } private 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(); } 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 byte[] encryptEcbPadding(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); } private static byte[] decryptEcbPadding(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); } private static byte[] encryptEcbNoPadding(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); } private static byte[] decryptEcbNoPadding(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); } 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; } private static byte[] encryptCbcPadding(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); } private static byte[] decryptCbcPadding(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); } private static byte[] encryptCbcNoPadding(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); } private static byte[] decryptCbcNoPadding(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); } public static String generateKey_Hex() throws Exception { return HexUtils.toHexString(generateKey()); } public static String encryptCbcPaddingHex(String key, String iv, String data) throws Exception { String iv_hex = HexUtils.toHexString(iv.getBytes()); return HexUtils.toHexString(encryptCbcPadding(HexUtils.fromHexString(key), HexUtils.fromHexString(iv_hex), data.getBytes())); } public static String decryptCbcPaddingHex(String key, String iv, String cipherText) throws Exception { return new String(decryptCbcPadding(HexUtils.fromHexString(key), iv.getBytes(), HexUtils.fromHexString(cipherText))); } public static void main(String[] args) throws Exception { String data = "{\"test\":\"湖北利川深圳\"}"; String iv = "blade12345678910";// String hexKey = generateKey_Hex(); String hexKey = "20785fae41a54c65ab95d2db1abc7f9f"; System.out.println("hexKey===" + hexKey); String cipher = encryptCbcPaddingHex(hexKey, iv, data); System.out.println("cipher==" + cipher); String b = decryptCbcPaddingHex(hexKey, iv, cipher); System.out.println(b); }}
Android SM4 工具类,要把
BouncyCastleProvider.PROVIDER_NAME 贴换为 new BouncyCastleProvider() 不然报错
分别在拦截器里面调用 加解密方法。hexKey 可以自己生成。iv 自己定义16位
String hexKey = "20785fae41a54c65ab95d2db1abc7f9f"; String iv = "blade12345678910";
加密方法:
String encryptJson = Sm4Util.encryptCbcPaddingHex(hexKey, iv, String.valueOf(json));
解密方法:
String decryptJson = Sm4Util.decryptCbcPaddingHex(hexKey, iv, String.valueOf(data));
这里面就不展示拦截器里面的代码。
截图展示加解密后的效果。
来源地址:https://blog.csdn.net/beautifulYuan/article/details/129528518