关于SM2软件加密与硬件加密的问题

SM2国密算法在中国的密码学领域中使用得非常广泛,它是一种基于椭圆曲线公钥密码的算法。日常开发工作中,涉及到SM2算法的加密和解密时,如果一方使用软件实现,而另一方使用硬件实现,可能会遇到一些联调过程中的问题。在SM2的加密和解密过程中,涉及到对ASN.1格式的编码和解码。

当软件加密和硬件加密进行联调时,可能会遇到以下问题:

1.编码/解码不一致:软件和硬件可能采用不同的ASN.1编码规则或者库来处理ASN.1格式的数据。这可能导致加密后的数据在软件端和硬件端之间无法正确解析。

2.数据填充和对齐问题:ASN.1编码的数据可能需要特定的填充或对齐方式。软件和硬件在这方面的处理方式如果不一致,也可能导致问题。

为了解决这些问题,可以采取以下措施:

1.明确接口定义:确保软件和硬件之间的接口定义清晰、一致,并遵循相关的标准和规范。如果可能的话,尽量使软件和硬件使用相同的ASN.1库,以确保编码和解码的一致性。

2.与硬件厂商沟通:如果问题确实出在硬件端,及时与硬件厂商沟通,寻求技术支持和解决方案。

案例:软件加密(主流开源库bouncycastle)和硬件加密接口对接,运行过程中偶现解密失败问题。接口上送的sm2加密值为硬件加密机加密后的asn1字节数组,应用程序需要将asn1转换原始数据进行解密,偶现错误发生在转换过程中。

ASN.1(Abstract Syntax Notation One)是一种接口定义语言,用于描述数据结构,被广泛用于密码学标准中。在SM2加密算法中,asn1的数据格式是这样的:

复制代码
/**
 * 加密数据的ASN.1 数据结构如下:
 * CipherData ::= SEQUENCE {
 * xcoordinate INTEGER,(32)
 * ycoordinate INTEGER,(32)
 * hash OCTET STRING,(32)
 * cigherText OCTET STRING (对应明文字节长度)
 * }
 * <p>
 * C1C3C2格式对应:
 * c1 = xcoordinate + ycoordinate
 * c3 = hash;
 * c2 = cigherText;
 * <p>
 * 格式解析如下:
 * 30 + totalLen  + xTag + xlen + x  + yTag + ylen +y + c3Tag + c3len + c3 + c2Tag + c2len + c2;
 */

将asn1字节写入文件,使用asn1工具打开可以看到完整结构:

asn1字节解析:

0x30:sequence

0x79:总长度totalLen

0x02:x类型标签xTag

0x20:x的长度xlen

0x00~0x92:x的内容

依此类推。。。

x分量: 包含标记+长度+内容,0x02表示整数

y分量:包含标记+长度+内容

摘要:包含标记+长度+内容,0x04表示String

密文:包含标记+长度+内容

应用程序中处理asn1数据转原始数据:

XML 复制代码
        <!--引入开源库 -->        
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.70</version>
        </dependency>
java 复制代码
    //此方法将asn1格式数据转换为原始数据进行解密 
    private static byte[] changeAsn1ToC1C3C2(byte[] asn1) {
        try {
            ASN1InputStream aIn = new ASN1InputStream(asn1);
            ASN1Sequence seq = (ASN1Sequence) aIn.readObject();
            BigInteger x = ASN1Integer.getInstance(seq.getObjectAt(0)).getValue();
            BigInteger y = ASN1Integer.getInstance(seq.getObjectAt(1)).getValue();
            byte[] c3 = ASN1OctetString.getInstance(seq.getObjectAt(2)).getOctets();
            byte[] c2 = ASN1OctetString.getInstance(seq.getObjectAt(3)).getOctets();

            ECPoint c1Point = GMNamedCurves.getByName("sm2p256v1").getCurve().createPoint(x, y);
            byte[] c1 = c1Point.getEncoded(false);
            return ArrayUtil.addAll(c1, c3, c2);
        } catch (Exception ex) {
            return null;
        }
    }

错误发生位置:

ASN1Sequence seq = (ASN1Sequence) aIn.readObject();

debug进入方法,如果出现无法debug情况,将bouncycastle库下载到本地调试。

bouncycastle库最终异常的位置:ASN1Integer#isMalformed

方案一:屏蔽bc关于大整数的校验,设置系统参数org.bouncycastle.asn1.allow_unsafe_integer为true

java 复制代码
    private static byte[] changeAsn1ToC1C3C2(byte[] asn1) {
        try {
            //x,y分量补位问题导致的规范性校验不通过,该配置绕过校验逻辑
            System.setProperty("org.bouncycastle.asn1.allow_unsafe_integer", "true");
            ASN1InputStream aIn = new ASN1InputStream(asn1);
            ASN1Sequence seq = (ASN1Sequence) aIn.readObject();
            BigInteger x = ASN1Integer.getInstance(seq.getObjectAt(0)).getValue();
            BigInteger y = ASN1Integer.getInstance(seq.getObjectAt(1)).getValue();
            byte[] c3 = ASN1OctetString.getInstance(seq.getObjectAt(2)).getOctets();
            byte[] c2 = ASN1OctetString.getInstance(seq.getObjectAt(3)).getOctets();

            ECPoint c1Point = GMNamedCurves.getByName("sm2p256v1").getCurve().createPoint(x, y);
            byte[] c1 = c1Point.getEncoded(false);
            return ArrayUtil.addAll(c1, c3, c2);
        } catch (Exception ex) {
            return null;
        }
    }

方案二:厂商提供asn1转原始数据方法替换bc库(推荐)

方案三:自行解析

复制代码
asn1格式解析如下(16进制表示):x、y、c3、c2为内容
30 + totalLen  + xTag + xlen + x  + yTag + ylen +y + c3Tag + c3len + c3 + c2Tag + c2len + c2;

原始数据格式(c1c3c2模式):

04+x+y+c3+c2

参考:

网联回执报文签名验证和敏感信息解密报错:failed to construct sequence from byte\[\]: corrupted stream detected 国密SM2-CSDN博客

https://blog.51cto.com/u_16099268/8806443

关于SM2算法 ASN.1编码 踩过的坑 - 加密_sm2私钥asn.1序列化-CSDN博客

asn.1ber编解码系统与设计asn.1编码规则详解(全面最经典) - 豆丁网

相关推荐
zander25817 分钟前
138. 随机链表的复制
数据结构·算法·链表
过期动态24 分钟前
【LeetCode 热题 100】找到字符串中所有字母异位词
java·数据结构·算法·leetcode·职场和发展·rabbitmq
来一碗刘肉面33 分钟前
栈在递归中的应用
数据结构·算法
8K超高清44 分钟前
博冠获中国电影电视技术学会科技进步奖
人工智能·科技·算法·安全·接口隔离原则·智能硬件
微石科技1 小时前
长期慢病如何做好居家管理?宁波微石科技星梦云康改善周期数据零散短板
大数据·科技·物联网·算法
微露清风1 小时前
快速排序算法学习记录
学习·算法·排序算法
梓䈑7 小时前
【算法题攻略】BFS 解决FloodFill 算法、最短路问题、多源BFS 和 拓扑排序
c++·算法·宽度优先
Adios7949 小时前
设置交集大小至少为2
数据结构·算法·leetcode