一、程序逻辑

加密-上传

浏览器发起A用户的上传请求

服务端生成会话密钥Ks,用A用户的公钥Ka进行SM2加密为密钥Ks’,发给浏览器

浏览器收到加密后的会话 密钥Ks’,用A用户的私钥Ka’进行SM2解密得到会话密钥Ks

浏览器使用会话密钥Ks,对上传文件进行SM4加密得到密文M’,发给服务端

服务端保存密文M’以及会话密钥Ks

二、技术实现

2.1 密钥传输部分(步骤1-3)

SM2证书解析

首先测试浏览器端加密狗ocx插件,可以使用ocx获取证书。

加密狗ocx测试页

经厂家确认,证书格式为X.509。将证书直接写在服务端代码内,尝试解析证书并获取公钥Ka。代码如下:

// 证书

String cert64 = "MIIBvzCCAWa…F2yvFQ==";

// base64解码

byte[] certBytes = Base64.getDecoder().decode(cert64);

InputStream inStream = new ByteArrayInputStream(certBytes);

CertificateFactory cf = CertificateFactory.getInstance("X.509");

// x509解析

X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream);

// 打印证书到期时间

System.out.println(cert.getNotAfter());

运行后报错:

Caused by: java.io.IOException: Unknown named curve: 1.2.156.10197.1.301

at sun.security.ec.ECParameters.engineInit(ECParameters.java:143)

at java.security.AlgorithmParameters.init(AlgorithmParameters.java:293)

at sun.security.x509.AlgorithmId.decodeParams(AlgorithmId.java:132)

at sun.security.x509.AlgorithmId.(AlgorithmId.java:114)

at sun.security.x509.AlgorithmId.parse(AlgorithmId.java:372)

at sun.security.x509.X509Key.parse(X509Key.java:168)

at sun.security.x509.CertificateX509Key.(CertificateX509Key.java:75)

at sun.security.x509.X509CertInfo.parse(X509CertInfo.java:667)

at sun.security.x509.X509CertInfo.(X509CertInfo.java:167)

上网搜索得知:国密证书使用了自有的椭圆曲线,所以无法使用JDK自带的java.security解析证书(http://www.jonllen.com/jonllen/work/162.aspx)。经过调研,需要引入BouncyCastle,BC库支持国密算法。参考这篇文章(https://blog.csdn.net/jinhill/article/details/9996117)修改代码,在pom.xml增加BC库依赖:

org.bouncycastle

bcprov-jdk15on

1.61

修改测试代码为:

// 引入BC库

Security.addProvider(new BouncyCastleProvider());

// 使用BC解析X.509证书

CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");

经测试,可以正常读取证书内容。

// 测试会话密钥

String ks = "666666";

byte[] data = ks.getBytes();

// 获取A的公钥Ka

BCECPublicKey publicKey = (BCECPublicKey) cert.getPublicKey();

// 加密引擎

SM2Engine sm2Engine = new SM2Engine();

// 加密参数

X9ECParameters sm2p256v1 = GMNamedCurves.getByName("sm2p256v1");

ECDomainParameters parameters = new ECDomainParameters(sm2p256v1.getCurve(), sm2p256v1.getG(), sm2p256v1.getN());

// 引擎初始化

sm2Engine.init(true, new ParametersWithRandom(new ECPublicKeyParameters(publicKey.getQ(), parameters), new SecureRandom()));

// 加密

byte[] encrypt = sm2Engine.processBlock(data, 0, data.length);

// base64编码

String encrypt64 = Base64.getEncoder().encodeToString(encrypt);

System.out.println(encrypt64);

可以生成加密后的密文,但尝试使用ocx插件进行解密时,解密失败。

解密失败

参考这篇文章所述,考虑密文组织顺序,旧标准:C1+C2+C3,新标准C1+C3+C2。增加密文结果调整函数,调整密文组织顺序。

/**

* 安全芯片SM2加密处理的密文顺序是 C1+C3+C2 而BC库加密出来的顺序是C1+C2+C3

* 此方法在加密后调用,将结果转化为 C1+C3+C2

*/

static byte[] changeC123toC132(byte[] src) {

//sm2p256v1的这个固定65。可看GMNamedCurves、ECCurve代码。

final int c1len = (sm2p256v1.getCurve().getFieldSize() + 7) / 8 * 2 + 1;

//new SM3Digest().getDigestSize();

final int c3len = 32;

byte[] dst = new byte[src.length];

System.arraycopy(src, 0, dst, 0, c1len); //c1

System.arraycopy(src, src.length - c3len, dst, c1len, c3len); //c3

System.arraycopy(src, c1len, dst, c1len + c3len, src.length - c1len - c3len); //c2

return dst;

}

再次尝试使用ocx插件进行解密,仍失败。比对ocx通过加密狗生成的密文与代码生成的密文,发现ocx的比代码生成的密文短一个字节。上网搜索问题原因,终于找到这篇(https://my.oschina.net/547217475/blog/2252583)。通过debug,发现加密后密文的第一个字节的确是04。

加密后数据

增加一个函数,去除密文的第一个字节。

/**

* 安全芯片在C1数据最前面没有04,而BC库加密出来的数据前面有04

* 去除BC加密后C1数据的第一个字节

*/

static byte[] removeFirstByte(byte[] src) {

byte[] dst = new byte[src.length - 1];

System.arraycopy(src, 1, dst, 0, dst.length);

return dst;

}

经测试,ocx可以正确解密获得服务器端生成的会话密钥ks。

java 数字信封_使用加密狗的国密算法实现B/S架构数字信封相关推荐

  1. java祖冲之加密算法_对称加密和非对称加密

    一  非对称加密 非对称加密和解密花费的时间长 非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey),一般使用公钥进行加密,使用私钥进行解密. 常见的非对称加密 ...

  2. 基于Java的(SM2_SM3_SM4)国密算法, 加密解密工具类及测试demo

    编写本文的同时借鉴了多位同学写的demo, 最后发现这位同学写的最详细, 放上该作者的链接, 原版链接: https://download.csdn.net/download/ererfei/9474 ...

  3. 堡垒机应用发布服务器是干嘛的_支持Web UI数据库审计和敏感数据国密算法加密,JumpServer堡垒机v2.5.0发布丨Release Notes...

    11月18日,JumpServer开源堡垒机正式发布v2.5.0版本.该版本的新增功能包括:支持Web UI数据库审计(X-Pack增强包内).支持敏感数据国密算法加密.新增克隆创建.新增高危命令告警 ...

  4. ec java sm2证书_国密算法SM2证书制作

    前段时间将系统的RSA算法全部升级为SM2国密算法,密码机和UKey硬件设备大都同时支持RSA和SM2算法,只是应用系统的加解密签名验证需要修改,这个更改底层调用的加密动态库来,原来RSA用的对称加密 ...

  5. java sm3国密算法加密、验证工具类

    java sm3国密算法加密.验证工具类 说明 maven依赖 完整代码 测试 说明 由于本人并不专于算法和密码学,所以如果发现工具类存在问题或者可优化地方,欢迎评论处提出. 工具类也可以直接使用封装 ...

  6. 国密算法java源码_国密算法SM2证书制作

    前段时间将系统的RSA算法全部升级为SM2国密算法,密码机和UKey硬件设备大都同时支持RSA和SM2算法,只是应用系统的加解密签名验证需要修改,这个更改底层调用的加密动态库来,原来RSA用的对称加密 ...

  7. mysql国密算法_【国密SM2算法】通过公钥证书获取JAVA对象

    网上关于国密算法的资料较单一,大部分代码都是写的怎么通过java代码生成公私钥串. 实际项目中对方已经给了他们的公钥证书,这里记录如何通过代码解析获得Ecpoint对象并输出 关键代码 String ...

  8. SpringBoot中_JAVA利用国密算法_实现内容的加密_解密--SpringCloud工作笔记180

    首先来看一下什么是国密算法: 国密即国家密码局认定的国产密码算法,即商用密码. 国密主要有SM1,SM2,SM3,SM4.密钥长度和分组长度均为128位. 1.SM1 为对称加密.其加密强度与AES( ...

  9. java实现国密算法

    java实现国密算法 一.国秘算法SM4 1.1 引入依赖 1.2 使用对称密码算法SM4加解密 二.SM3是哈希算法 2.1 案例 三.SM2算法(公钥私钥是字节类型) 3.1 SM2签名和验签 3 ...

最新文章

  1. python发送邮件和附件
  2. 程序员加入新团队必问的20道问题
  3. python中的seth函数_Python入门——turtle库的使用
  4. 样本距离计算、向量范数、矩阵范数
  5. 河北地质大学硕士专业介绍:计算机类
  6. 网络通信协议-TCP/IP模型实战
  7. CVPR 2022 | 旷视研究院入选论文亮点解读
  8. Algorithm:贪心策略之区间选点问题
  9. [转] 接触C# 反射 2
  10. ios xcode如何在控制台打印frame
  11. Vue小说阅读器(仿追书神器)
  12. opencv无法打开摄像头
  13. 点线形系列1-计算两点之间的距离
  14. 打开单片机世界的大门——上位机控制下位机实例详解
  15. Vivado使用技巧(17):创建IBIS模型
  16. Jupyter-02-numpy:数组的维度
  17. 笔记本键盘部分按键失灵?
  18. step计算机语言,STEP7的三种基本编程语言LAD、FBD及STL 该如何抉择?
  19. 【Minio】新一代自建文件系统——Minio
  20. 快手短视频运营实操技巧

热门文章

  1. switch-case注意点
  2. 深入浅出PyTorch中的nn.CrossEntropyLoss
  3. 关于windows错误恢复怎么解决
  4. 编译原理------语法分析器C/C++代码实现
  5. 假如让我回到高考结束的那个暑假,我会这么做...
  6. 做了一个漂亮的项目,啧啧
  7. 中国存储“军团”补位美光,存储芯片的垄断格局要崩了
  8. BorlandC汉字库 HZK像素字模
  9. 【精品】互联网常见的十八种营销方式
  10. 鼻孔插灯,智商上升,风靡硅谷,3万就成