-
Notifications
You must be signed in to change notification settings - Fork 267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
后端生成的密钥对,前端加密成功,但无法解密 #42
Comments
此库格式:公钥是 '04' + 128位 hex 串(x坐标 + y坐标);私钥是64位 hex 串,你可以对比一下。解密结果为空表示解密不出来。 |
嗯嗯,我试了下,貌似并不是单纯的其中某64位 |
已经提了pr,可以到我的仓库看看: https://github.com/antherd/sm-crypto |
@antherd-admin 我Java端和Golang端已经对接完成,你的这个仓库也只是用java调作者的js方法呀。。 |
java的公私钥,需要 String publicQ = HexUtil.encodeHexStr(sm2.getQ(false));//未压缩的 取出 Q和D 才和 js端的公私钥对应的, |
没错,java直接调用js方法。保证前后端所有方法一致 |
因为前段js生成的公私钥是压缩的,所以用前段后端生成的公钥,获得的压缩Q加密的密文,用后端私钥是解不了的 |
cn.hutool.crypto.SmUtil; |
前段加密,后端可以解密吗?可以就挺好,不过还是需要注意很多细节。。 |
兄弟可以介绍下你用的golang哪个库么? |
@ypwlal 当时用的是这个库 https://github.com/tjfoc/gmsm |
我这边已经成功了,你看下我的情况对你有没有帮助。 |
@ypwlal 多谢多谢!目前我这边已采用其他方案,抽空我也试试你的方法 |
@ypwlal 情况说明很有帮助,按照你的描述成功了,多谢! |
公钥使用 DER 编码了,解析 DER 之后把 X 和 Y 还原回来即可,私钥使用的 PKCS#8 格式,也需要解析后还原出裸私钥。 |
请教一下你这边是怎么解决的,我目前遇到的问题和你类似,使用golang生成的公钥和私钥,golang和java能互相加解密,golang和js能互相加解密,java可以解密js的密文,唯一的问题是js无法解密java的密文。 |
@ZongweiBai Java 加密出来的密文格式丢一个出来看看 |
我这边后端用的是gmhelper,生成的密文是,对应的加密格式是c1c3c2:
js对应的公钥和私钥分别是:
|
@ZongweiBai 去除密文前的 04 标识,然后密文换成小写即可: const Sm2Crypto = require("sm-crypto").sm2;
let cipherText = "0b16c625f649f154d59b610db390f30aada21b50f1d88cb5bd7cee1671aef9225deff40fe9ece4d39fdb811c9560c7ba557b6a95d77e53f1f2d15cf77066ea6011bd53f21066e99ead0bb31dcb978a74d5878fd7f61953a6928a14e591120c9b81240d3e9aa67d716827db095d";
let privateKeyHex = "4EA87F7B575ECE76D51CADB061CE3B4D7700BFC6231F5C844D7611F123D07879";
let decryptText = Sm2Crypto.doDecrypt(cipherText, privateKeyHex, 1);
console.log(decryptText);
如果要追因的话,就是这个 js 库 在最后比较 c3 的时候,是用 === 比较的,但是库内部本身算出来的形式是小写的。😂 |
@changhr2013 按照你的方法成功了,感谢。 目前sm2\sm3\sm4的golang\java\js三端都调试成功了,我这边用到的golang库和java库是: 希望对大家有帮助 |
兄弟我按照你说的做了,但是还是出现了上述的情况,golang生成的公私钥两边都正常,但是前后端不能互通,前端加密后补上04也不行 |
感觉有必要写个跨语言说明了,要不然这个 issue 无解 😂。 Golang 使用 gmsm 加/解密: func TestGmsm2Encrypt(t *testing.T) {
// 原文
dataBytes := []byte("hello world")
// 生成密钥对
sm2PriKey, err := sm2.GenerateKey(nil)
if err != nil {
return
}
// 私钥 hex
s := hex.EncodeToString(sm2PriKey.D.Bytes())
fmt.Println(s)
// 公钥 hex
sm2PubKey := sm2PriKey.PublicKey
s2 := "04" + hex.EncodeToString(sm2PubKey.X.Bytes()) + hex.EncodeToString(sm2PubKey.Y.Bytes())
fmt.Println(s2)
// 公钥加密
encrypt, err := sm2.Encrypt(&sm2PubKey, dataBytes, nil, sm2.C1C3C2)
if err != nil {
return
}
fmt.Println(hex.EncodeToString(encrypt))
// 私钥解密
decrypt, err := sm2.Decrypt(sm2PriKey, encrypt, sm2.C1C3C2)
if err != nil {
return
}
fmt.Println(string(decrypt))
} 输出示例:
js 使用 sm-crypto 解密 golang 密文: const Sm2Crypto = require("sm-crypto").sm2;
// golang 加密的密文,需要移除前面的 04 标识
let cipherText = "f6f663b4ca467c1b0053ae6d22079ef3a9612253829eee84f32846067630aeeb95f19119a52b816ecf71ffdd9cdb68ca6fa2ab748a50acde6d9c93249288558645636ef1d77bbd32b419b87a7cd2337bb6362b6122746c0b313f461b373f7c61ea5a27b2dc2846ccd88f43";
// 私钥
let privateKeyHex = "edec1100fbc83411ed1112bab763df275f91ad3140aa19ae5cc717012454fefc";
// 解密
let decryptText = Sm2Crypto.doDecrypt(cipherText, privateKeyHex, 1);
console.log(decryptText);
// 公钥
let publicKeyHex = "0416c9fdfabe11ca0efe5aae03cdb46b96e39e14095e926e5f021889f79abd04631791d2dc1672bad412596d5f32a6977332f5c815bf6ca948c9f3f24999551b07"
// 加密
let encryptText = Sm2Crypto.doEncrypt("hello world", publicKeyHex, 1);
console.log(encryptText); 输出示例:
使用 golang 解密 js 密文: func TestGmsm2Decrypt(t *testing.T) {
// js 加密的密文,需要添加 04 标识
cipherBytes, _ := hex.DecodeString("0417b8d0bde323c8b9bb593e0916e8f60ba2ac765fcc10ef1a88985c8a89e13bd9be256b8948761fbb8dbf531c99d62148f391f90cf1037e6d4cfb6934faed4172a37e5e4466b3a139330c9f9c5927216d2460733eedf6c2cd1ef54cf5d5e1f5b88e17c6e77a503c342d3cb6")
// 还原私钥结构体
X, _ := hex.DecodeString("16c9fdfabe11ca0efe5aae03cdb46b96e39e14095e926e5f021889f79abd0463")
Y, _ := hex.DecodeString("1791d2dc1672bad412596d5f32a6977332f5c815bf6ca948c9f3f24999551b07")
D, _ := hex.DecodeString("edec1100fbc83411ed1112bab763df275f91ad3140aa19ae5cc717012454fefc")
pubX := new(big.Int).SetBytes(X)
pubY := new(big.Int).SetBytes(Y)
priD := new(big.Int).SetBytes(D)
sm2PriKey := &sm2.PrivateKey{
PublicKey: sm2.PublicKey{
Curve: sm2.P256Sm2(),
X: pubX,
Y: pubY,
},
D: priD,
}
// 私钥解密
decrypt, err := sm2.Decrypt(sm2PriKey, cipherBytes, sm2.C1C3C2)
if err != nil {
return
}
fmt.Println(string(decrypt))
} 输出示例:
|
我按你的代码拿到了公钥和私钥然后加密,前端解密不出来啊,是我的加密方式有问题吗? SM2 sm2 = SmUtil.sm2();
String publicKey = HexUtil.encodeHexStr(sm2.getQ(false));
String privateKey = HexUtil.encodeHexStr(sm2.getD());
System.out.println("publicKey = " + publicKey);
System.out.println("privateKey = " + privateKey);
String encryptBcd = sm2.encryptBcd(data, KeyType.PublicKey);
System.out.println("encryptBcd = " + encryptBcd); |
使用 hutool 做 SM2 加解密: @Test
public void Sm2EncryptAndDecrypt() {
SM2 sm2 = SmUtil.sm2();
String publicKey = Hex.toHexString(sm2.getQ(false));
String privateKey = Hex.toHexString(sm2.getD());;
System.out.println("publicKey = " + publicKey);
System.out.println("privateKey = " + privateKey);
// 待加密的原文
String data = "hello world";
// 加密为 hex 格式
String encryptHex = sm2.encryptHex(data, KeyType.PublicKey);
System.out.println("encryptHex = " + encryptHex);
// 解密
byte[] decrypt = sm2.decrypt(Hex.decode(encryptHex));
System.out.println(new String(decrypt, StandardCharsets.UTF_8));
} 输出示例:
使用 js sm-crypto 解密 java 加密的密文: const Sm2Crypto = require("sm-crypto").sm2;
// 密文,需要移除前面的 04 标识
let cipherText = "818a2a97c74c5a94d9ddf33707b215a0a0f86ec9e72b5ad1ee179cdb4527d5d4f853df4db3b2cf1904aa824c233bb5d53c388796801fc58f7542e8539c12b58cdada16e665ac796a0a047baddcfcd4fa22b083be334054179d2bca7d95ea6a0b3ef5fa32af3b01e9ebe4cf";
// 私钥
let privateKeyHex = "15ccdbb178f7f41c4acc7a74d1d35e6dbb3883d2e39559bf7bf74c0daac4d4d6";
// 解密
let decryptText = Sm2Crypto.doDecrypt(cipherText, privateKeyHex, 1);
console.log(decryptText);
// 公钥
let publicKeyHex = "04d7124943876ff89a4bbe3d6f52f446a23868c760475c7993f30dc2fe3281b9a7866dc3644a175e435711ddde50918b46f4d2293a49aa9ffc77005b32f8bdb8dc"
// 加密
let encryptText = Sm2Crypto.doEncrypt("hello world", publicKeyHex, 1);
console.log(encryptText); 输出示例:
使用 hutool 解密 js 的密文: @Test
public void Sm2DecryptTest() {
// 还原 SM2 实例
byte[] privateKey = Hex.decode("15ccdbb178f7f41c4acc7a74d1d35e6dbb3883d2e39559bf7bf74c0daac4d4d6");
byte[] publicKey = Hex.decode("04d7124943876ff89a4bbe3d6f52f446a23868c760475c7993f30dc2fe3281b9a7866dc3644a175e435711ddde50918b46f4d2293a49aa9ffc77005b32f8bdb8dc");
SM2 sm2 = new SM2(privateKey, publicKey);
// js 密文前需要添加 04 标识
String jsEncryptHex = "04f32bb02ba91d9eb67b4f36ef567ca9beb461ab69058ed072a4046bf132046828c6589e170235ec708e004619a37c2aeaccafbc549b584232df2449d7221a4bc772662330a7d0564f4b1940f496f561e9d9eccba5f17e147154242edbb5d6c76e7044d531e7d19279715cac";
// 解密
byte[] decrypt = sm2.decrypt(Hex.decode(jsEncryptHex));
System.out.println(new String(decrypt, StandardCharsets.UTF_8));
} 输出示例:
|
哇 感谢 我去试试 |
实测加密通过,感谢 |
加密解密倒是可以了,签名和验签怎么不行啊
加密倒是可以了,但是前面和验签不对,这个应该怎么处理? |
@changhr2013 您好,如果java后台生成的公私钥不是获取的Q值,js中有解决办法吗?java那边不乐意改代码; |
一般 Java 默认生成私钥是 PKCS#8 格式的,公钥是 X.509 格式的,需要解编码。 可以参考 #109 的思路解编码即可。 最好还是沟通让后端改一下,后端现成的解析库,多一行代码的事。 裸公私钥存储和传输的成本也会低很多。 |
实际开发中遇到个问题,想请教下大佬们:
后端用Go语言生成的密钥对,前端用公钥能加密成功,在Go和Java上也能用对应的私钥解密成功,但前端无法解密
公钥:(取后130位)3059301306072a8648ce3d020106082a811ccf5501822d0342000410ee64f73e0acb2380bada2697e80a22b39968ac72833b7692968ff2c21bc88e8afcbdc1b89c3382089415cea907e61b02060194675a16c4d48c5e3a57c49388
私钥:308193020100301306072a8648ce3d020106082a811ccf5501822d047930770201010420ff54e3914a41191006633b5f08fcc5e42dbdf2c26c18d55dd9501f0d889c151ea00a06082a811ccf5501822da1440342000410ee64f73e0acb2380bada2697e80a22b39968ac72833b7692968ff2c21bc88e8afcbdc1b89c3382089415cea907e61b02060194675a16c4d48c5e3a57c49388
原文:你好啊
密文:(已添加 04 标识)044fd2407ae9b39d7e8080c15fa39ad392ce0ba26829345c6422c9fa1a8746ad4c5f42c3a1d6aaab0a8f16405afdcb3fb708c2a200b48ebd9b12adcaf686e4a060c6182903dd43e9b401afccc8504d9360d572a14d372dc7665fc2eb762f2e34c45cf50283c7c07b6e4d
Go和Java均能解密出原文,但是用sm-crypto解密后结果是空的。。
The text was updated successfully, but these errors were encountered: