注册

达梦8使用国密SM4加解密和java中的使用问题

三儿 2024/02/28 1002 3 已解决

为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。
【DM版本】:dm8
【操作系统】:linux
【CPU】: 4
【问题描述】*:

现象描述

使用Java编写的SM4加密方法得到的密文后,使用达梦内置的 OPENSSL_SM4_CBC 解密方式对数据进行解密。结果无法解密。

使用达梦内置的 OPENSSL_SM4_CBC 加密方式对数据进行加密,在java代码中却无法解密。

两者得到的密文不一致。

想要实现的效果

  1. 在java中加密的数据能在达梦中解密出明文
  2. 在达梦中加密的数据能在java中解密出明文

加密参数:

key : JstNsDmSm4Key113
vi :JstNsDmSm4Key112
明文数据:测试数据123456

达梦数据库加密解密结果,如下图:
1709124009238.png

java 代码运行结果,如下图:

1709124094924.png

### 使用的maven包,如下:

<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15to18</artifactId> <version>1.77</version> </dependency>

使用的jdk为:

jdk-17

java代码如下:

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)); } }

要实现想要实现的效果

  1. 在java中加密的数据能在达梦中解密出明文
  2. 在达梦中加密的数据能在java中解密出明文

如何才能做到两边加解密互通?

达梦内置 OPENSSL_SM4_CBC 的是不是做了什么特殊的逻辑处理?

我的代码应该怎么改才能实现想要的效果?

或者有什么其他方式能做到代码和数据库双方加解密互通吗?

回答 0
暂无回答
扫一扫
联系客服