Open CherryRum opened 2 months ago
@CherryRum 你要自己实现么,哈哈
看看有啥问题 哈哈,明确下文档
public KeyInfo generate() {
KeyPair keyPair = SecureUtil.generateKeyPair("SM2");
// 获取公钥和私钥
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
KeyInfo keyInfo = new KeyInfo();
keyInfo.setPublicKeyStr(Base64.getEncoder().encodeToString(publicKey.getEncoded()));
keyInfo.setPrivateKeyStr(Base64.getEncoder().encodeToString(privateKey.getEncoded()));
return keyInfo;
}
最近在对接国密,想咨询下hutool生成的国密密钥对的私钥算法标识符是使用的1.2.840.10045.2.1
ANSI X9.62 国际标准吗?
在使用openssl如下命令生成的国密密钥对的私钥算法标识符是使用的1.2.156.10197.1.301
中国国家商用密码标准。因为也是第一次接触,客户要求使用国密,我理解这两种都是ECC(椭圆曲线密码学)的实现,请教下用哪一种更符合所谓国密的规范呢?
openssl ecparam -genkey -name SM2 -out "sm2PrivateKey.pem"
@cxhello 密钥格式的问题。
Hutool中使用密钥支持:
私钥:支持D值、PKCS#8、PKCS#1 公钥:支持Q值、X.509、PKCS#1
密钥标识符使用的是:1.2.156.10197.1.301
见:
@looly 您说的密钥格式的问题,是指的我使用openssl命令不对是吗?
@cxhello 我意思是国密的Oid是固定的,只是密钥存储的格式不同。
如果在使用中有问题,可以附上测试的密钥,我这边回复。
证书解析网址:https://lapo.it/asn1js
压缩包里面有公私钥和证书,我使用证书解析网址解析出来看到OID使用的是1.2.840.10045.2.1
,parameters是1.2.156.10197.1.301
,导致我们在前端使用js解密有问题,所以想请教下。😂
@cxhello Java生成的密钥确实不是Asni格式,是pkcs8和x509。
现在Hutool只能保证js生成的密钥可以用,但是Java生成的密钥没法在js中使用。
好的,我自己再研究下。
@cxhello 看下这个cxhello 你的意思是想直接在两方用ans.1编码的吗
您的问题是一个历史遗留问题 您解析证书时看到的OID 1.2.840.10045.2.1(是因为该证书使用了OpenSSL 1.x版本的实现。在OpenSSL 1.x版本中,SM2算法的公钥被错误地标识为标准的EC公钥(OID: 1.2.840.10045.2.1),而不是国密标准中定义的SM2算法的OID(1.2.156.10197.1.301)sm2p256v1。这导致了与国密标准的不一致。
建议您使用OpenSSL 3.x版本。OpenSSL 3.x版本中,SM2公钥密码算法已经使用了正确的OID 1.2.156.10197.1.301(参见《GB/T 33560-2017 信息安全技术 密码应用标识规范》附录A)。虽然这一更改可能导致一些后向兼容性问题,但这是为了遵循最新的国密标准,并解决之前版本存在的标准落后于实践的问题。
您解析证书时看到的OID 1.2.840.10045.2.1(是因为该证书使用了OpenSSL 1.x版本的实现。在OpenSSL 1.x版本中,SM2算法的公钥被错误地标识为标准的EC公钥(OID: 1.2.840.10045.2.1),而不是国密标准中定义的SM2算法的OID(1.2.156.10197.1.301)sm2p256v1。这导致了与国密标准的不一致。
@CherryRum 其实我想表达的是 我使用的hutool-5.7.22版本,生成的公私钥OID也是:1.2.840.10045.2.1,是需要更新版本吗?😂
那我建议您先升级版本吧,这个虽然不错,但是不符合现有的文档定义的曲线,虽然说这俩oid的椭圆曲线是一样的(没记错的话)
@CherryRum 我们需要给客户演示的时候在他们的环境使用openss命令生成,所以如果客户的环境上使用openssl 1.x 其实没什么问题。我刚刚测试了,可以正常加解密了。
感谢大佬说的这个历史遗留问题。还有个问题想问下,hutool升级到5.8.29 OID就是1.2.156.10197.1.301了吗?
我是在我电脑上使用openssl生成公私钥发现这个问题的,我电脑上openssl版本是3.2.0。所以前端在使用私钥解密的时候报错了,前端用的应该也恰好是以前的库。😂
确实没注意,我想新版本要做下更新了。
这其实是个算法的归类问题,取决于 SM2 是应该属于 EC 算法的一条曲线,还是应该与 EC 并列的算法。
我觉得业界一直是认为 SM2 就是一条特殊的 EC 曲线,所以一开始大家都是按照 EC 的标准去走的,包括 《GM/T 0015-2012 基于SM2密码算法的数字证书格式规范》 在附录中给出的示例,也是使用 1.2.840.10045.2.1
作为算法 Oid 的。
OpenSSL 团队在升级 3.0 时,也解释了他们最初这样做的原因,他们团队内部当时认为应该将 SM2 算法视为一种独立的算法,所以他们参考了《GM/T 0006-2012 密码应用标识规范》给出的 Oid 来标识 SM2 算法。
这造成了很大的混乱,我觉得既然 GM/T 0015
已经给出了明确的参考示例,那么正如 OpenSSL 开发人员在 Issue 中说的:『如果有一个标准规定应该以特定的方式进行编码,那么我们就不能以不同的方式进行编码』。
PS: 不过我觉得这个事情大概率还是 0015 制定者的锅,因为在 GM/T 0015
标准的附录表格中是这样描述的:
可以明确看到 algorithm
部分给的值是 1.2.156.10197.1.301
,parameters
部分标记的是:『当使用 SM2 密码算法时,为 SM2 密码算法曲线的 OID』。
但是到下面附录的示例又变成了上面贴图的那样,大家实现的时候即使有疑问,也肯定会优先去符合标准示例。
这特么找谁说理去。
再提一嘴,目前所有的国密基础设施都是按照示例走的,所以在实际编码中,使用 1.2.840.10045.2.1
才是正解,会避免 N 多兼容性问题。
@changhr2013
我公司 arm kylin v10 的服务器上 openssl 版本是 1.1.1f,生成的国密公私钥OID就是1.2.156.10197.1.301
,可是坑了我一把。😂
@changhr2013
我公司 arm kylin v10 的服务器上 openssl 版本是 1.1.1f,生成的国密公私钥OID就是
1.2.156.10197.1.301
,可是坑了我一把。😂
这个算是个bug,升级到openssl最新版本就能解决。 相关issue在这里,有过不少讨论 https://github.com/openssl/openssl/issues/20973
@changhr2013 我公司 arm kylin v10 的服务器上 openssl 版本是 1.1.1f,生成的国密公私钥OID就是
1.2.156.10197.1.301
,可是坑了我一把。😂这个算是个bug,升级到openssl最新版本就能解决。 相关issue在这里,有过不少讨论 openssl/openssl#20973
也不算是bug吧,上面我引用了很多,其中就有这个,只是标准太模糊了
参考文档
GMT 0009-2012.pdf GMT 0009-2023.pdf