为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。
【DM版本】:dm8
【操作系统】:linux
【CPU】: 4
【问题描述】*:
使用Java编写的SM4加密方法得到的密文后,使用达梦内置的 OPENSSL_SM4_CBC 解密方式对数据进行解密。结果无法解密。
使用达梦内置的 OPENSSL_SM4_CBC 加密方式对数据进行加密,在java代码中却无法解密。
两者得到的密文不一致。
key : JstNsDmSm4Key113
vi :JstNsDmSm4Key112
明文数据:测试数据123456
达梦数据库加密解密结果,如下图:
### 使用的maven包,如下:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.77</version>
</dependency>
jdk-17
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Security;
public class SM4Util {
private static final String ALGORITHM_NAME = "SM4";
private static final String ALGORITHM_NAME_PADDING = "SM4/CBC/PKCS5Padding";
// private static final int IV_SIZE = 16;
// private static final byte[] DEFAULT_IV = new byte[IV_SIZE];
private static final byte[] DEFAULT_IV = "JstNsDmSm4Key112".getBytes();
private static final String DEFAULT_KEY = "JstNsDmSm4Key113";
static {
// 添加 BouncyCastle 加密提供程序
Security.addProvider(new BouncyCastleProvider());
}
/**
* 生成 SM4 密钥
*
* @param keyBytes 密钥原始字节数组
* @return SecretKey 密钥对象
* @throws Exception
*/
public static SecretKey generateKey(byte[] keyBytes) throws Exception {
return new SecretKeySpec(keyBytes, ALGORITHM_NAME);
}
/**
* 加密方法
*
* @param key 密钥对象
* @param data 待加密数据
* @return byte[] 加密数据
* @throws Exception
*/
public static byte[] encryptCBC(SecretKey key, byte[] data) throws Exception {
return process(key, data, Cipher.ENCRYPT_MODE);
}
/**
* 解密方法
*
* @param key 密钥对象
* @param data 待解密数据
* @return byte[] 解密数据
* @throws Exception
*/
public static byte[] decryptCBC(SecretKey key, byte[] data) throws Exception {
return process(key, data, Cipher.DECRYPT_MODE);
}
private static byte[] process(SecretKey key, byte[] data, int mode) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_PADDING);
byte[] iv = DEFAULT_IV;
IvParameterSpec ivParam = new IvParameterSpec(iv);
cipher.init(mode, key, ivParam);
return cipher.doFinal(data);
}
public static String encryptCBC(String key,String data) throws Exception {
SecretKeySpec skey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM_NAME);
byte[] bytes = SM4Util.encryptCBC(skey, data.getBytes());
byte[] encode = Hex.encode(bytes);
return new String(encode);
}
public static String decryptCBC(String key,String data) throws Exception {
SecretKeySpec skey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM_NAME);
byte[] decode = Hex.decode(data.getBytes());
byte[] bytes = SM4Util.decryptCBC(skey,decode );
return new String(bytes);
}
public static String encryptCBCUseDefaultKey(String data) throws Exception {
SecretKey skey = generateKey(DEFAULT_KEY.getBytes(StandardCharsets.UTF_8));
byte[] bytes = SM4Util.encryptCBC(skey, data.getBytes());
byte[] encode = Hex.encode(bytes);
return new String(encode).toUpperCase();
}
public static String decryptCBCUseDefaultKey(String data) throws Exception {
SecretKey skey = generateKey(DEFAULT_KEY.getBytes(StandardCharsets.UTF_8));
byte[] decode = Hex.decode(data.getBytes());
byte[] bytes = SM4Util.decryptCBC(skey,decode );
return new String(bytes);
}
public static void main(String[] args) throws Exception {
String dataString = "测试数据123456";
String str = encryptCBCUseDefaultKey(dataString);
System.out.println("加密结果:"+str);
System.out.println("解密结果:"+decryptCBCUseDefaultKey(str));
}
}
要实现想要实现的效果
如何才能做到两边加解密互通?
达梦内置 OPENSSL_SM4_CBC 的是不是做了什么特殊的逻辑处理?
我的代码应该怎么改才能实现想要的效果?
或者有什么其他方式能做到代码和数据库双方加解密互通吗?
可以在java中通过调用sql的形式加解密。
加密:java中调用执行 select sf_encrypt_char('测试数据123456',5202,'JstNsDmSm4Key113',null)
解密:java中调用执行 select sf_decrypt_to_char(sf_encrypt_char('测试数据123456',5202,'JstNsDmSm4Key113','JstNsDmSm4Key112'),5202,'JstNsDmSm4Key113','JstNsDmSm4Key112')