SM2
SM2 是由中国国家密码管理局制定的椭圆曲线公钥密码算法,是中国商用密码标准的核心算法之一。dongle 支持标准和流式 SM2 加密,提供符合 GM/T 0003.4-2012 标准的加密和解密功能。
支持以下密文模式:
- C1C3C2:国密标准推荐格式(默认),密文结构为
0x04 || C1(64字节) || C3(32字节) || C2(密文数据) - C1C2C3:旧标准兼容格式,密文结构为
0x04 || C1(64字节) || C2(密文数据) || C3(32字节)
注意事项:
- 密文模式:加密和解密必须使用相同的密文模式(C1C3C2 或 C1C2C3)
- 数据安全:SM2 提供
256位安全强度,相当于RSA3072 位 - 互操作性:与
OpenSSL等库互操作时,需明确指定相同的密文顺序 - 私钥安全:私钥必须妥善保管,不能泄露
- 标准符合:完全符合 GM/T 0003.4-2012(加密算法)和 GM/T 0003.5-2012(曲线参数)
导入相关模块:
go
import (
"github.com/dromara/dongle"
"github.com/dromara/dongle/crypto/keypair"
)创建密钥对
go
kp := keypair.NewSm2KeyPair()
// 设置密文模式(可选,默认为 C1C3C2)
kp.SetMode(keypair.C1C3C2)生成密钥对
go
// 生成 SM2 密钥对(256 位椭圆曲线)
err := kp.GenKeyPair()
if err != nil {
panic(err)
}
// 获取 PEM 格式公钥
publicKey := kp.PublicKey
// 获取 PEM 格式私钥
privateKey := kp.PrivateKey从已有 PEM 格式密钥设置密钥对
go
// 设置 PEM 格式公钥
kp.PublicKey = []byte(`-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEVJKqUmu59VTLhqCiVBmKqRjL5MXy
RHKwFAI+qG2Hqy5Wf5cLRlIf7aSMKqwGvYpP6gVOqQpvBdDQhDqr8rqrYA==
-----END PUBLIC KEY-----`)
// 设置 PEM 格式私钥
kp.PrivateKey = []byte(`-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgKvp8GZUkqT8UH/Z5
u8mjNM0JIvqmFolR6LczGEZmSvmhRANCAARUkqpSa7n1VMuGoKJUGYqpGMvkxfJE
crAUAj6obYerLlZ/lwtGUh/tpIwqrAa9ik/qBU6pCm8F0NCEOqvyuqtg
-----END PRIVATE KEY-----`)从已有 DER 格式密钥设置密钥对
go
// 设置 Base64 编码的 DER 格式公钥
kp.SetPublicKey([]byte("MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEVJKqUmu59VTLhqCiVBmKqRjL5MXyRHKwFAI+qG2Hqy5Wf5cLRlIf7aSMKqwGvYpP6gVOqQpvBdDQhDqr8rqrYA=="))
// 设置 Base64 编码的 DER 格式私钥
kp.SetPrivateKey([]byte("MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgKvp8GZUkqT8UH/Z5u8mjNM0JIvqmFolR6LczGEZmSvmhRANCAARUkqpSa7n1VMuGoKJUGYqpGMvkxfJEcrAUAj6obYerLlZ/lwtGUh/tpIwqrAa9ik/qBU6pCm8F0NCEOqvyuqtg"))将 DER 格式密钥格式化成 PEM 格式
go
// 将 base64 编码的 DER 格式公钥格式化为 PEM 格式
publicKey, err := kp.FormatPublicKey([]byte("MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEVJKqUmu59VTLhqCiVBmKqRjL5MXyRHKwFAI+qG2Hqy5Wf5cLRlIf7aSMKqwGvYpP6gVOqQpvBdDQhDqr8rqrYA=="))
// 将 base64 编码的 DER 格式私钥格式化为 PEM 格式
privateKey, err := kp.FormatPrivateKey([]byte("MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgKvp8GZUkqT8UH/Z5u8mjNM0JIvqmFolR6LczGEZmSvmhRANCAARUkqpSa7n1VMuGoKJUGYqpGMvkxfJEcrAUAj6obYerLlZ/lwtGUh/tpIwqrAa9ik/qBU6pCm8F0NCEOqvyuqtg"))将 PEM 格式密钥压缩成 DER 格式
go
// 将 PEM 格式公钥压缩成经过 base64 编码的 DER 格式(去掉 PEM 格式公钥的头尾和换行符)
publicKey, err := kp.CompressPublicKey([]byte(`-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEVJKqUmu59VTLhqCiVBmKqRjL5MXy
RHKwFAI+qG2Hqy5Wf5cLRlIf7aSMKqwGvYpP6gVOqQpvBdDQhDqr8rqrYA==
-----END PUBLIC KEY-----`))
// 将 PEM 格式私钥压缩成经过 base64 编码的 DER 格式(去掉 PEM 格式私钥的头尾和换行符)
privateKey, err := kp.CompressPrivateKey([]byte(`-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgKvp8GZUkqT8UH/Z5
u8mjNM0JIvqmFolR6LczGEZmSvmhRANCAARUkqpSa7n1VMuGoKJUGYqpGMvkxfJE
crAUAj6obYerLlZ/lwtGUh/tpIwqrAa9ik/qBU6pCm8F0NCEOqvyuqtg
-----END PRIVATE KEY-----`))公钥加密
输入数据
// 设置 DER 格式公钥 kp.SetPublicKey([]byte("MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEVJKqUmu59VTLhqCiVBmKqRjL5MXyRHKwFAI+qG2Hqy5Wf5cLRlIf7aSMKqwGvYpP6gVOqQpvBdDQhDqr8rqrYA==")) // 设置 PEM 格式公钥 kp.PublicKey = []byte(-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEVJKqUmu59VTLhqCiVBmKqRjL5MXy RHKwFAI+qG2Hqy5Wf5cLRlIf7aSMKqwGvYpP6gVOqQpvBdDQhDqr8rqrYA== -----END PUBLIC KEY-----)
go
// 输入字符串
encrypter := dongle.Encrypt.FromString("hello world").BySm2(kp)
// 输入字节切片
encrypter := dongle.Encrypt.FromBytes([]byte("hello world")).BySm2(kp)
// 输入文件流
file, _ := os.Open("test.txt")
encrypter := dongle.Encrypt.FromFile(file).BySm2(kp)
// 检查加密错误
if encrypter.Error != nil {
fmt.Printf("加密错误: %v\n", encrypter.Error)
return
}输出数据
go
// 输出 Hex 编码字符串
hexString := encrypter.ToHexString() // 例如:047fae94fd1a8b880d8d5454dd8df30c40...
// 输出 Hex 编码字节切片
hexBytes := encrypter.ToHexBytes() // 例如:[]byte("047fae94fd1a8b880d8d5454dd8df30c40...")
// 输出 Base64 编码字符串
base64String := encrypter.ToBase64String() // 例如:BH+ulP0ai4gNjVRU3Y3zDEA=...
// 输出 Base64 编码字节切片
base64Bytes := encrypter.ToBase64Bytes() // 例如:[]byte("BH+ulP0ai4gNjVRU3Y3zDEA=...")
// 输出未编码原始字符串
rawString := encrypter.ToRawString()
// 输出未编码原始字节切片
rawBytes := encrypter.ToRawBytes()私钥解密
输入数据
go
// 设置 DER 格式私钥
kp.SetPrivateKey([]byte("MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgKvp8GZUkqT8UH/Z5u8mjNM0JIvqmFolR6LczGEZmSvmhRANCAARUkqpSa7n1VMuGoKJUGYqpGMvkxfJEcrAUAj6obYerLlZ/lwtGUh/tpIwqrAa9ik/qBU6pCm8F0NCEOqvyuqtg"))
// 设置 PEM 格式私钥
kp.PrivateKey = []byte(`-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgKvp8GZUkqT8UH/Z5
u8mjNM0JIvqmFolR6LczGEZmSvmhRANCAARUkqpSa7n1VMuGoKJUGYqpGMvkxfJE
crAUAj6obYerLlZ/lwtGUh/tpIwqrAa9ik/qBU6pCm8F0NCEOqvyuqtg
-----END PRIVATE KEY-----`)
// 输入 Hex 编码字符串
decrypter := dongle.Decrypt.FromHexString(hexString).BySm2(kp)
// 输入 Hex 编码字节切片
decrypter := dongle.Decrypt.FromHexBytes(hexBytes).BySm2(kp)
// 输入 Hex 编码文件流
file, _ := os.Open("encrypted.hex")
decrypter := dongle.Decrypt.FromHexFile(file).BySm2(kp)
// 输入 Base64 编码字符串
decrypter := dongle.Decrypt.FromBase64String(base64String).BySm2(kp)
// 输入 Base64 编码字节切片
decrypter := dongle.Decrypt.FromBase64Bytes(base64Bytes).BySm2(kp)
// 输入 Base64 编码文件流
file, _ := os.Open("encrypted.base64")
decrypter := dongle.Decrypt.FromBase64File(file).BySm2(kp)
// 输入原始字符串
decrypter := dongle.Decrypt.FromRawString(rawString).BySm2(kp)
// 输入原始字节切片
decrypter := dongle.Decrypt.FromRawBytes(rawBytes).BySm2(kp)
// 输入原始文件流
file, _ := os.Open("encrypted.bin")
decrypter := dongle.Decrypt.FromRawFile(file).BySm2(kp)
// 检查解密错误
if decrypter.Error != nil {
fmt.Printf("解密错误: %v\n", decrypter.Error)
return
}输出数据
go
// 输出解密后的字符串
decrypter.ToString() // hello world
// 输出解密后的字节切片
decrypter.ToBytes() // []byte("hello world")