Code Monkey home page Code Monkey logo

Comments (26)

changhr2013 avatar changhr2013 commented on June 9, 2024 5

感觉有必要写个跨语言说明了,要不然这个 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))
}

输出示例:

// 私钥
edec1100fbc83411ed1112bab763df275f91ad3140aa19ae5cc717012454fefc
// 公钥
0416c9fdfabe11ca0efe5aae03cdb46b96e39e14095e926e5f021889f79abd04631791d2dc1672bad412596d5f32a6977332f5c815bf6ca948c9f3f24999551b07
// golang 加密的密文
04f6f663b4ca467c1b0053ae6d22079ef3a9612253829eee84f32846067630aeeb95f19119a52b816ecf71ffdd9cdb68ca6fa2ab748a50acde6d9c93249288558645636ef1d77bbd32b419b87a7cd2337bb6362b6122746c0b313f461b373f7c61ea5a27b2dc2846ccd88f43
// golang 解密的明文
hello world

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);

输出示例:

// js 解密的明文
hello world
// js 加密的密文
17b8d0bde323c8b9bb593e0916e8f60ba2ac765fcc10ef1a88985c8a89e13bd9be256b8948761fbb8dbf531c99d62148f391f90cf1037e6d4cfb6934faed4172a37e5e4466b3a139330c9f9c5927216d2460733eedf6c2cd1ef54cf5d5e1f5b88e17c6e77a503c342d3cb6

使用 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))
}

输出示例:

hello world

@daLingZhong

from sm-crypto.

JuneAndGreen avatar JuneAndGreen commented on June 9, 2024 1

此库格式:公钥是 '04' + 128位 hex 串(x坐标 + y坐标);私钥是64位 hex 串,你可以对比一下。解密结果为空表示解密不出来。

from sm-crypto.

ypwlal avatar ypwlal commented on June 9, 2024 1

@ypwlal 当时用的是这个库 https://github.com/tjfoc/gmsm

我这边已经成功了,你看下我的情况对你有没有帮助。
一开始我用的gmsm的EncryptAsn1、DecryptAsn1方法,前后端对应不上;然后我debug出来后,使用gmsm的Encrypt和Decrypt方法,和sm-crypto(js加密的密文前补上04到后端解密)就完全可以对应上了。因为gmsm文档里的方法会对入参的明文/密文字节做marshal和unmarshal,跳过这一步就没问题了(要注意参数错误会panic)

from sm-crypto.

changhr2013 avatar changhr2013 commented on June 9, 2024 1

使用 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));
}

输出示例:

publicKey = 04d7124943876ff89a4bbe3d6f52f446a23868c760475c7993f30dc2fe3281b9a7866dc3644a175e435711ddde50918b46f4d2293a49aa9ffc77005b32f8bdb8dc
privateKey = 15ccdbb178f7f41c4acc7a74d1d35e6dbb3883d2e39559bf7bf74c0daac4d4d6
encryptHex = 04818a2a97c74c5a94d9ddf33707b215a0a0f86ec9e72b5ad1ee179cdb4527d5d4f853df4db3b2cf1904aa824c233bb5d53c388796801fc58f7542e8539c12b58cdada16e665ac796a0a047baddcfcd4fa22b083be334054179d2bca7d95ea6a0b3ef5fa32af3b01e9ebe4cf
hello world

使用 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);

输出示例:

// js 解密 java 的密文
hello world
// js 加密的密文
f32bb02ba91d9eb67b4f36ef567ca9beb461ab69058ed072a4046bf132046828c6589e170235ec708e004619a37c2aeaccafbc549b584232df2449d7221a4bc772662330a7d0564f4b1940f496f561e9d9eccba5f17e147154242edbb5d6c76e7044d531e7d19279715cac

使用 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));
}

输出示例:

hello world

@Montaro2017

from sm-crypto.

yhyzgn avatar yhyzgn commented on June 9, 2024

嗯嗯,我试了下,貌似并不是单纯的其中某64位

from sm-crypto.

antherds avatar antherds commented on June 9, 2024

已经提了pr,可以到我的仓库看看: https://github.com/antherd/sm-crypto
WX20210813-093905

from sm-crypto.

yhyzgn avatar yhyzgn commented on June 9, 2024

@antherd-admin 我Java端和Golang端已经对接完成,你的这个仓库也只是用java调作者的js方法呀。。

from sm-crypto.

pronebel avatar pronebel commented on June 9, 2024

java的公私钥,需要

String publicQ = HexUtil.encodeHexStr(sm2.getQ(false));//未压缩的
String privateD = HexUtil.encodeHexStr(sm2.getD());

取出 Q和D 才和 js端的公私钥对应的,
可以看看是不是类似的原因,我之前也遇到过

from sm-crypto.

antherds avatar antherds commented on June 9, 2024

@antherd-admin 我Java端和Golang端已经对接完成,你的这个仓库也只是用java调作者的js方法呀。。

没错,java直接调用js方法。保证前后端所有方法一致

from sm-crypto.

antherds avatar antherds commented on June 9, 2024

java的公私钥,需要

String publicQ = HexUtil.encodeHexStr(sm2.getQ(false));//未压缩的
String privateD = HexUtil.encodeHexStr(sm2.getD());

取出 Q和D 才和 js端的公私钥对应的,
可以看看是不是类似的原因,我之前也遇到过

因为前段js生成的公私钥是压缩的,所以用前段后端生成的公钥,获得的压缩Q加密的密文,用后端私钥是解不了的

from sm-crypto.

pronebel avatar pronebel commented on June 9, 2024

java的公私钥,需要

String publicQ = HexUtil.encodeHexStr(sm2.getQ(false));//未压缩的
String privateD = HexUtil.encodeHexStr(sm2.getD());

取出 Q和D 才和 js端的公私钥对应的,
可以看看是不是类似的原因,我之前也遇到过

cn.hutool.crypto.SmUtil;
我这里是用的这个hutool工具包里的方法,和本sm的js库之间对接下来没有问题。及时要注意这个Q,D的压缩密匙,还有 04的问题

from sm-crypto.

antherds avatar antherds commented on June 9, 2024

java的公私钥,需要
String publicQ = HexUtil.encodeHexStr(sm2.getQ(false));//未压缩的
String privateD = HexUtil.encodeHexStr(sm2.getD());
取出 Q和D 才和 js端的公私钥对应的,
可以看看是不是类似的原因,我之前也遇到过

cn.hutool.crypto.SmUtil;
我这里是用的这个hutool工具包里的方法,和本sm的js库之间对接下来没有问题。及时要注意这个Q,D的压缩密匙,还有 04的问题

前段加密,后端可以解密吗?可以就挺好,不过还是需要注意很多细节。。

from sm-crypto.

ypwlal avatar ypwlal commented on June 9, 2024

实际开发中遇到个问题,想请教下大佬们: 后端用Go语言生成的密钥对,前端用公钥能加密成功,在Go和Java上也能用对应的私钥解密成功,但前端无法解密

公钥:(取后130位)3059301306072a8648ce3d020106082a811ccf5501822d0342000410ee64f73e0acb2380bada2697e80a22b39968ac72833b7692968ff2c21bc88e8afcbdc1b89c3382089415cea907e61b02060194675a16c4d48c5e3a57c49388 私钥:308193020100301306072a8648ce3d020106082a811ccf5501822d047930770201010420ff54e3914a41191006633b5f08fcc5e42dbdf2c26c18d55dd9501f0d889c151ea00a06082a811ccf5501822da1440342000410ee64f73e0acb2380bada2697e80a22b39968ac72833b7692968ff2c21bc88e8afcbdc1b89c3382089415cea907e61b02060194675a16c4d48c5e3a57c49388

原文:你好啊 密文:(已添加 04 标识)044fd2407ae9b39d7e8080c15fa39ad392ce0ba26829345c6422c9fa1a8746ad4c5f42c3a1d6aaab0a8f16405afdcb3fb708c2a200b48ebd9b12adcaf686e4a060c6182903dd43e9b401afccc8504d9360d572a14d372dc7665fc2eb762f2e34c45cf50283c7c07b6e4d

Go和Java均能解密出原文,但是用sm-crypto解密后结果是空的。。

兄弟可以介绍下你用的golang哪个库么?
我的情况跟你相反,我用的go库(gmsm)生成的公私钥可以各自在go端加解密成功,在js端加解密成功,但是却没法做到前后互通,即在前端加密后端解密或者后端加密前端解密

from sm-crypto.

yhyzgn avatar yhyzgn commented on June 9, 2024

@ypwlal 当时用的是这个库 https://github.com/tjfoc/gmsm

from sm-crypto.

yhyzgn avatar yhyzgn commented on June 9, 2024

@ypwlal 多谢多谢!目前我这边已采用其他方案,抽空我也试试你的方法

from sm-crypto.

goodweather0 avatar goodweather0 commented on June 9, 2024

@ypwlal 情况说明很有帮助,按照你的描述成功了,多谢!

from sm-crypto.

changhr2013 avatar changhr2013 commented on June 9, 2024

实际开发中遇到个问题,想请教下大佬们: 后端用Go语言生成的密钥对,前端用公钥能加密成功,在Go和Java上也能用对应的私钥解密成功,但前端无法解密

公钥:(取后130位)3059301306072a8648ce3d020106082a811ccf5501822d0342000410ee64f73e0acb2380bada2697e80a22b39968ac72833b7692968ff2c21bc88e8afcbdc1b89c3382089415cea907e61b02060194675a16c4d48c5e3a57c49388 私钥:308193020100301306072a8648ce3d020106082a811ccf5501822d047930770201010420ff54e3914a41191006633b5f08fcc5e42dbdf2c26c18d55dd9501f0d889c151ea00a06082a811ccf5501822da1440342000410ee64f73e0acb2380bada2697e80a22b39968ac72833b7692968ff2c21bc88e8afcbdc1b89c3382089415cea907e61b02060194675a16c4d48c5e3a57c49388

原文:你好啊 密文:(已添加 04 标识)044fd2407ae9b39d7e8080c15fa39ad392ce0ba26829345c6422c9fa1a8746ad4c5f42c3a1d6aaab0a8f16405afdcb3fb708c2a200b48ebd9b12adcaf686e4a060c6182903dd43e9b401afccc8504d9360d572a14d372dc7665fc2eb762f2e34c45cf50283c7c07b6e4d

Go和Java均能解密出原文,但是用sm-crypto解密后结果是空的。。

公钥使用 DER 编码了,解析 DER 之后把 X 和 Y 还原回来即可,私钥使用的 PKCS#8 格式,也需要解析后还原出裸私钥。

from sm-crypto.

ZongweiBai avatar ZongweiBai commented on June 9, 2024

@ypwlal 多谢多谢!目前我这边已采用其他方案,抽空我也试试你的方法

请教一下你这边是怎么解决的,我目前遇到的问题和你类似,使用golang生成的公钥和私钥,golang和java能互相加解密,golang和js能互相加解密,java可以解密js的密文,唯一的问题是js无法解密java的密文。

from sm-crypto.

changhr2013 avatar changhr2013 commented on June 9, 2024

@ZongweiBai Java 加密出来的密文格式丢一个出来看看

from sm-crypto.

ZongweiBai avatar ZongweiBai commented on June 9, 2024

@ZongweiBai Java 加密出来的密文格式丢一个出来看看

我这边后端用的是gmhelper,生成的密文是,对应的加密格式是c1c3c2:

040B16C625F649F154D59B610DB390F30AADA21B50F1D88CB5BD7CEE1671AEF9225DEFF40FE9ECE4D39FDB811C9560C7BA557B6A95D77E53F1F2D15CF77066EA6011BD53F21066E99EAD0BB31DCB978A74D5878FD7F61953A6928A14E591120C9B81240D3E9AA67D716827DB095D

js对应的公钥和私钥分别是:

js公钥: 04721982C46CBF2A424456081944C58165543847119E629ECBC2B1C70400DF05A6661848019F13A1B2B370D60168A162A97D49FA2F2F56EF8F6BEC0035206BF440
js私钥: 4EA87F7B575ECE76D51CADB061CE3B4D7700BFC6231F5C844D7611F123D07879

from sm-crypto.

changhr2013 avatar changhr2013 commented on June 9, 2024

@ZongweiBai 去除密文前的 04 标识,然后密文换成小写即可:

const Sm2Crypto = require("sm-crypto").sm2;

let cipherText = "0b16c625f649f154d59b610db390f30aada21b50f1d88cb5bd7cee1671aef9225deff40fe9ece4d39fdb811c9560c7ba557b6a95d77e53f1f2d15cf77066ea6011bd53f21066e99ead0bb31dcb978a74d5878fd7f61953a6928a14e591120c9b81240d3e9aa67d716827db095d";

let privateKeyHex = "4EA87F7B575ECE76D51CADB061CE3B4D7700BFC6231F5C844D7611F123D07879";

let decryptText = Sm2Crypto.doDecrypt(cipherText, privateKeyHex, 1);

console.log(decryptText);
helloword!sm2

如果要追因的话,就是这个 js 库 在最后比较 c3 的时候,是用 === 比较的,但是库内部本身算出来的形式是小写的。😂

from sm-crypto.

ZongweiBai avatar ZongweiBai commented on June 9, 2024

@changhr2013 按照你的方法成功了,感谢。

目前sm2\sm3\sm4的golang\java\js三端都调试成功了,我这边用到的golang库和java库是:
https://github.com/Hyperledger-TWGC/ccs-gm
https://github.com/ZZMarquis/gmhelper

希望对大家有帮助

from sm-crypto.

daLingZhong avatar daLingZhong commented on June 9, 2024

@ypwlal 当时用的是这个库 https://github.com/tjfoc/gmsm

我这边已经成功了,你看下我的情况对你有没有帮助。 一开始我用的gmsm的EncryptAsn1、DecryptAsn1方法,前后端对应不上;然后我debug出来后,使用gmsm的Encrypt和Decrypt方法,和sm-crypto(js加密的密文前补上04到后端解密)就完全可以对应上了。因为gmsm文档里的方法会对入参的明文/密文字节做marshal和unmarshal,跳过这一步就没问题了(要注意参数错误会panic)

兄弟我按照你说的做了,但是还是出现了上述的情况,golang生成的公私钥两边都正常,但是前后端不能互通,前端加密后补上04也不行

from sm-crypto.

Montaro2017 avatar Montaro2017 commented on June 9, 2024

java的公私钥,需要

String publicQ = HexUtil.encodeHexStr(sm2.getQ(false));//未压缩的 String privateD = HexUtil.encodeHexStr(sm2.getD());

取出 Q和D 才和 js端的公私钥对应的, 可以看看是不是类似的原因,我之前也遇到过

我按你的代码拿到了公钥和私钥然后加密,前端解密不出来啊,是我的加密方式有问题吗?

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);

from sm-crypto.

Montaro2017 avatar Montaro2017 commented on June 9, 2024

使用 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));
}

输出示例:

publicKey = 04d7124943876ff89a4bbe3d6f52f446a23868c760475c7993f30dc2fe3281b9a7866dc3644a175e435711ddde50918b46f4d2293a49aa9ffc77005b32f8bdb8dc
privateKey = 15ccdbb178f7f41c4acc7a74d1d35e6dbb3883d2e39559bf7bf74c0daac4d4d6
encryptHex = 04818a2a97c74c5a94d9ddf33707b215a0a0f86ec9e72b5ad1ee179cdb4527d5d4f853df4db3b2cf1904aa824c233bb5d53c388796801fc58f7542e8539c12b58cdada16e665ac796a0a047baddcfcd4fa22b083be334054179d2bca7d95ea6a0b3ef5fa32af3b01e9ebe4cf
hello world

使用 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);

输出示例:

// js 解密 java 的密文
hello world
// js 加密的密文
f32bb02ba91d9eb67b4f36ef567ca9beb461ab69058ed072a4046bf132046828c6589e170235ec708e004619a37c2aeaccafbc549b584232df2449d7221a4bc772662330a7d0564f4b1940f496f561e9d9eccba5f17e147154242edbb5d6c76e7044d531e7d19279715cac

使用 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));
}

输出示例:

hello world

@Montaro2017

哇 感谢 我去试试

from sm-crypto.

dragon1102 avatar dragon1102 commented on June 9, 2024

感觉有必要写个跨语言说明了,要不然这个 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))
}

输出示例:

// 私钥
edec1100fbc83411ed1112bab763df275f91ad3140aa19ae5cc717012454fefc
// 公钥
0416c9fdfabe11ca0efe5aae03cdb46b96e39e14095e926e5f021889f79abd04631791d2dc1672bad412596d5f32a6977332f5c815bf6ca948c9f3f24999551b07
// golang 加密的密文
04f6f663b4ca467c1b0053ae6d22079ef3a9612253829eee84f32846067630aeeb95f19119a52b816ecf71ffdd9cdb68ca6fa2ab748a50acde6d9c93249288558645636ef1d77bbd32b419b87a7cd2337bb6362b6122746c0b313f461b373f7c61ea5a27b2dc2846ccd88f43
// golang 解密的明文
hello world

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);

输出示例:

// js 解密的明文
hello world
// js 加密的密文
17b8d0bde323c8b9bb593e0916e8f60ba2ac765fcc10ef1a88985c8a89e13bd9be256b8948761fbb8dbf531c99d62148f391f90cf1037e6d4cfb6934faed4172a37e5e4466b3a139330c9f9c5927216d2460733eedf6c2cd1ef54cf5d5e1f5b88e17c6e77a503c342d3cb6

使用 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))
}

输出示例:

hello world

@daLingZhong

实测加密通过,感谢

from sm-crypto.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.