国密sm2加密

  |  

SM2(国密算法),加密模式 C1C3C2

SM2 为非对称加密,基于 ECC。该算法已公开。由于该算法基于 ECC,故其签名速度与秘钥生成速度都快于 RSA。ECC 256 位(SM2 采用的就是 ECC 256 位的一种)安全强度比 RSA 2048 位高,但运算速度快于 RSA。
旧标准的加密排序 C1C2C3 新标准 C1C3C2,C1 为 65 字节第 1 字节为压缩标识,这里固定为 0x04,后面 64 字节为 xy 分量各 32 字节。C3 为 32 字节。C2 长度与原文一致。

公钥:049cbf6df92258b385b82844d29039183d98e205726bcecd71b40ded26e717d3ccb9132685432eaafbcb58683c3d303a1e79137447231f8db33226b24893fcd429

私钥:6c4a9b2d44704400552b4b90c39c5bca3e5c0ac1b91324e3d0579eebf24830bd

java

  1. 添加包
1
2
3
4
5
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.70</version>
</dependency>
  1. java 加密
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package crypto;

import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;
import org.junit.jupiter.api.Test;

/**
* @author klover
* @description SM2
* @date 2023/4/25 12:16
*/
public class SM2 {
@Test
void test() throws InvalidCipherTextException {
// 加密代码示例
final String SPEC_NAME = "sm2p256v1";
final X9ECParameters x9ECParameters = GMNamedCurves.getByName(SPEC_NAME);
final ECDomainParameters ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());

// 公钥数据
String encodedPub = "049cbf6df92258b385b82844d29039183d98e205726bcecd71b40ded26e717d3ccb9132685432eaafbcb58683c3d303a1e79137447231f8db33226b24893fcd429";
String data = "6220012345670001"; // 待加密数据

byte[] pointBytes = Hex.decode(encodedPub);
ECPoint q = x9ECParameters.getCurve().decodePoint(pointBytes);
ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(q, ecDomainParameters);
// 采用 C1 || C3 || C2 的模式
SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
// 自定义固定签名
// SecureRandom secureRandom = new SecureRandom(encodedPub.getBytes(StandardCharsets.UTF_8));
// SecureRandom random = CryptoServicesRegistrar.getSecureRandom(secureRandom);
// sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, random));
// 动态
sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters));
byte[] dataBytes = data.getBytes();
byte[] cipherBytes = sm2Engine.processBlock(dataBytes, 0, dataBytes.length);
String encryptedData = new String(Base64.encode(cipherBytes));
System.out.println(encryptedData);
// 加密结果示例: BB5SdLKsA2dqJTeXUFpRf9M6htKBrfYOTlaVUFHp340wXQ6quFU3fT9PSw8Hf6s1QyqMizJYjnvl/Jsqn91Zr6KXXhZUdeRctUBtvkUOFB6QYeHLa+dk5mQTOhG0cJGaOWd3tNF/3pM7w0lk3snC6X0=
}
}

node

  1. 添加包

gmsm-sm2js

  1. 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import * as SM2 from "gmsm-sm2js";

/**
* 加密方式 SM2 sm2p256v1
* @publicKey 加密公钥
* @msg 原文
*/
export const sm2p256v1Encrypt = (publicKey: string, msg: string) => {
const encrypt = SM2.encrypt(publicKey, msg);

return Buffer.from(encrypt, "hex").toString("base64");
};

/**
* 解密方式 SM2 sm2p256v1
* @publicKey 解密私钥
* @msg 密文
*/
export const sm2p256v1Decrypt = (privateKey: string, msg: string) => {
const decrypt = SM2.decrypt(privateKey, Buffer.from(msg, "base64"));

return Buffer.from(decrypt, "hex").toString("utf8");
};
  1. 测试
1
2
3
4
5
6
7
8
9
10
11
12
const privateKey =
"6c4a9b2d44704400552b4b90c39c5bca3e5c0ac1b91324e3d0579eebf24830bd";
const publicKey =
"049cbf6df92258b385b82844d29039183d98e205726bcecd71b40ded26e717d3ccb9132685432eaafbcb58683c3d303a1e79137447231f8db33226b24893fcd429";

const msgString = "6220012345670001";

const encryptData = sm2p256v1Encrypt(publicKey, msgString);

console.log(encryptData);

console.log(sm2p256v1Decrypt(privateKey, encryptData));

node 解密 java 加密的值

1
2
3
4
5
6
console.log(
sm2p256v1Decrypt(
privateKey,
"BB5SdLKsA2dqJTeXUFpRf9M6htKBrfYOTlaVUFHp340wXQ6quFU3fT9PSw8Hf6s1QyqMizJYjnvl/Jsqn91Zr6KXXhZUdeRctUBtvkUOFB6QYeHLa+dk5mQTOhG0cJGaOWd3tNF/3pM7w0lk3snC6X0="
)
);
文章目录
  1. 1. SM2(国密算法),加密模式 C1C3C2
    1. 1.1. java
    2. 1.2. node
    3. 1.3. node 解密 java 加密的值