求助,关于 golang 国密私钥问题

2022-05-09 11:15:07 +08:00
 chenall

测试.sm2 密码: 123456

MIIDSQIBATBHBgoqgRzPVQYBBAIBBgcqgRzPVQFoBDDkLvKllj9ZWhaKU6MSnxBBV5yaF3tEcOk1
vQniWyVzyaQA4F3j/YvDJwEoE8gOF/swggL5BgoqgRzPVQYBBAIBBIIC6TCCAuUwggKJoAMCAQIC
BRBAmQgJMAwGCCqBHM9VAYN1BQAwXDELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFu
Y2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEbMBkGA1UEAwwSQ0ZDQSBURVNUIFNNMiBPQ0Ex
MB4XDTIwMTExOTA4MzExOFoXDTI1MTExOTA4MzExOFowgYkxCzAJBgNVBAYTAkNOMRcwFQYDVQQK
DA5DRkNBIFRFU1QgT0NBMTENMAsGA1UECwwEUFNCQzEZMBcGA1UECwwQT3JnYW5pemF0aW9uYWwt
MjE3MDUGA1UEAwwuMDUxQOmCruWCqOe6v+S4iuaUtuWNleWVhuaIt0BONTEwMTEzMDAwMTg4NzhA
MTBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABJVRC63OKfcL4H324rDOdb4SSlbAjoJDXnK0qmwX
Z59FWmiSqt3ipreljKew4QynjTgR/yfp9yjNgNU8G5pkYdujggEGMIIBAjAfBgNVHSMEGDAWgBRr
/hjaj0I6prhtsy6Igzo0osEw4TAMBgNVHRMBAf8EAjAAMEgGA1UdIARBMD8wPQYIYIEchu8qAQEw
MTAvBggrBgEFBQcCARYjaHR0cDovL3d3dy5jZmNhLmNvbS5jbi91cy91cy0xNC5odG0wOQYDVR0f
BDIwMDAuoCygKoYoaHR0cDovL3VjcmwuY2ZjYS5jb20uY24vU00yL2NybDE0MzU2LmNybDAOBgNV
HQ8BAf8EBAMCBsAwHQYDVR0OBBYEFPiGPZT0oTuRXvkyGoOgviNEWnc1MB0GA1UdJQQWMBQGCCsG
AQUFBwMCBggrBgEFBQcDBDAMBggqgRzPVQGDdQUAA0gAMEUCIQCJDSsVPfhr+gnDASMj5Syt+hxs
amHygPecjCLbcdFQQgIgSXC4musF5Fnj/CpNTqvk9+56FuINkATGS8xRh7kzKBE=

有没有对国密比较了解的,请问一下如何通过 golang 从这个 sm2 文件提取私钥?

或者 gmssl/openssl 有办法直接提取吗?

3697 次点击
所在节点    Go 编程语言
12 条回复
hxndg
2022-05-09 12:04:40 +08:00
这个看起来就是 pem 文件掐头去尾,应该可以直接用 openssl 看的
mengyx
2022-05-09 12:20:32 +08:00
这个是 SM2 的证书吧,不包含私钥
chenall
2022-05-09 13:42:12 +08:00
@hxndg
不知要用什么命令?
我有试了像下面的命令不行
gmssl x509 -in test.sm2 -passin pass:123456

@mengyx

java 的读取代码如下,可以读取到公钥和私钥.

```
import cfca.sadk.util.KeyUtil;

public class HelloWorld {
public static void main(String[] args) {
PrivateKey priKey = KeyUtil.getPrivateKeyFromSM2("test.sm2", "123456");
System.out.println(priKey.toString());
System.out.println(args.length);
}
}
```
mengyx
2022-05-09 13:53:39 +08:00
刚才看漏了,我重新看了一下:感觉是 PKCS#12 格式,用 SM4 加密了私钥,稍后我确认下
Pinattsu
2022-05-09 14:35:17 +08:00
提取用户证书:

openssl pkcs12 -in 1.p12 -clcerts -nokeys -out cert.pem //pem 格式
openssl pkcs12 -in 1.p12 -clcerts -nokeys -out cert.crt //crt 格式

提取公钥

openssl pkcs12 -in 1.p12 -clcerts -out public_key.pem //pem 格式
openssl pkcs12 -in 1.p12 -clcerts -out cert.crt //crt 格式

提取私钥:

openssl pkcs12 -in 1.p12 -nodes -out private_key.pem
Pinattsu
2022-05-09 14:38:29 +08:00
golang 可以试试这个 https://github.com/tjfoc/gmsm
我用过这个库解析 p12 文件
chenall
2022-05-09 15:20:55 +08:00
@Pinattsu

试了,会报错 wrong tag.

用 gmsl 提示

tags don't match (16 vs {class:0 tag:6 length:10 isCompound:false})
mengyx
2022-05-09 15:33:04 +08:00
@chenall #3 反编译看了一下你提到的 SDK ,感觉这个 key/iv 派生方式,不是标准的 PKCS#12 ,可能是自定义的

既然有 SDK 能够转换为标准格式,你就先转换导出成 PEM/DER ,再在 Go 里面读取好了
mengyx
2022-05-09 15:35:04 +08:00
@mengyx #8 抱歉 图贴重复了……
chenall
2022-05-09 17:05:48 +08:00
@mengyx @Pinattsu @hxndg

感谢各位的回复,目前好像只能先用 sdk 转换提取再使用了.

另外我刚有找到了这篇文章.

https://www.thunes.com/2021/12/29/digital-signature-usage-of-chinese-cryptography-standards/

太概就是 asn.1 第一段 的那 48 个字节就是 经过 sm4 加密的 私钥.

我有空再研究一下,应该可以通过 sm4 来解密.
mengyx
2022-05-09 17:36:50 +08:00
@chenall #10 看代码是
1. 先将 password 和 \0x00\0x00\0x00\0x00 拼接,然后用 SM3 散列得到 32byte
2. 取前 16B 作为 IV ,后 16B 作为 Key ,使用 SM4(CBC, PKCS7 Padding), 解密得到私钥
chenall
2022-05-09 19:00:28 +08:00
@mengyx

感谢,测试了一下确实可以, sm3 散列是 password 和 \0x00\0x00\0x00\0x01 拼接的( #8 图的内容).

先用 asn.1 解析得到 密文,然后解密就可以得到私钥了.

sm4data, _ := hex.DecodeString("E42EF2A5963F595A168A53A3129F1041579C9A177B4470E935BD09E25B2573C9A400E05DE3FD8BC327012813C80E17FB")
sm3Hash := sm3.Sm3Sum([]byte{'1', '2', '3', '4', '5', '6', 0, 0, 0, 1})
_ = sm4.SetIV(sm3Hash[:16])
out, e := sm4.Sm4Cbc(sm3Hash[16:], sm4data, false)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/851692

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX