赞
踩
SM2是国家密码管理局于2010年12月17日发布的椭圆曲线公钥密码算法。
由于SM2是基于椭圆曲线的公钥加密算法,与RSA一样都是非对称密码算法。
由于 RSA 算法和 ECC 算法这一明显不同,使得 ECC 算法的单位安全强度高于 RSA算 法。
也就是说,要达到同样的安全强度,ECC 算法所需的密钥长度远比 RSA 算法低。
代码示例:
- package main
-
- import (
- "crypto/rand"
- "encoding/base64"
- "encoding/hex"
- "fmt"
- "github.com/tjfoc/gmsm/sm2"
- "github.com/tjfoc/gmsm/x509"
- "os"
- )
-
- type GMCrypt struct {
- PublicFile string
- PrivateFile string
- }
-
- var (
- path = "./"
- privateFile = "private.pem" //私钥文件
- publicFile = "public.pem" //公钥文件
- data = "hello 国密"
- )
-
- func main() {
- //秘钥生成
- GenerateSM2Key()
- crypt := GMCrypt{
- PublicFile: path + publicFile,
- PrivateFile: path + privateFile,
- }
- //加密
- encryptText, _ := crypt.Encrypt(data)
- //解密
- decryptText, err := crypt.Decrypt(encryptText)
- fmt.Println(err)
- fmt.Println(decryptText)
-
- //签名
- msg := []byte("hello 国密")
- sig, key, err := CreateSm2Sig(msg)
- fmt.Printf("签名结果:%x, 公钥:%v, err:%v\n", sig, key, err)
- //验证签名
- verSm2Sig := VerSm2Sig(key, msg, sig)
- fmt.Println("验证结果为:", verSm2Sig)
- }
-
- //生成公钥、私钥
- func GenerateSM2Key() {
- //1. 秘钥产生
- priKey, err := sm2.GenerateKey(rand.Reader)
- if err != nil {
- fmt.Println("秘钥产生失败:", err)
- os.Exit(1)
- }
- pubKey := &priKey.PublicKey
- //生成文件 保存私钥
- //x509编码
- pemPrivKey, err := x509.WritePrivateKeyToPem(priKey, nil)
- privateFile, err := os.Create(path + privateFile)
- defer privateFile.Close()
- privateFile.Write(pemPrivKey)
-
- pemPublicKey, err := x509.WritePublicKeyToPem(pubKey)
- publicFile, err := os.Create(path + publicFile)
- defer publicFile.Close()
- publicFile.Write(pemPublicKey)
-
- }
- func readPemCxt(path string) ([]byte, error) {
- file, err := os.Open(path)
- if err != nil {
- return []byte{}, err
- }
- defer file.Close()
- fileInfo, err := file.Stat()
- if err != nil {
- return []byte{}, err
- }
- buf := make([]byte, fileInfo.Size())
- _, err = file.Read(buf)
- if err != nil {
- return []byte{}, err
- }
- return buf, err
- }
- //数据加密
- func (s *GMCrypt) Encrypt(data string) (string, error) {
- pub, err := readPemCxt(s.PublicFile)
- if err != nil {
- return "", err
- }
- //read public key
- publicKeyFromPem, err := x509.ReadPublicKeyFromPem(pub)
- if err != nil {
- fmt.Println(err)
- return "", err
- }
- ciphertxt, err := publicKeyFromPem.EncryptAsn1([]byte(data), rand.Reader)
- if err != nil {
- return "", err
- }
- return base64.StdEncoding.EncodeToString(ciphertxt), nil
- }
- //数据解密
- func (s *GMCrypt) Decrypt(data string) (string, error) {
- pri, err := readPemCxt(s.PrivateFile)
- if err != nil {
- return "", err
- }
-
- privateKeyFromPem, err := x509.ReadPrivateKeyFromPem(pri, nil)
- if err != nil {
- return "", err
- }
-
- ciphertxt, err := base64.StdEncoding.DecodeString(data)
- if err != nil {
- return "", err
- }
- plaintxt, err := privateKeyFromPem.DecryptAsn1(ciphertxt)
- if err != nil {
- return "", err
- }
- return string(plaintxt), nil
- }
-
- /*
- 使用私钥创建签名
- */
- func CreateSm2Sig(msg []byte) ([]byte, *sm2.PublicKey, error) {
- //读取密钥对
- pri, err := readPemCxt(path + privateFile)
- privateKey, _ := x509.ReadPrivateKeyFromPem(pri, nil)
- c := sm2.P256Sm2() //椭圆曲线
- priv := new(sm2.PrivateKey)
- priv.PublicKey.Curve = c
- priv.D = privateKey.D
- priv.PublicKey.X = privateKey.X
- priv.PublicKey.Y = privateKey.Y
-
- sign, err := priv.Sign(rand.Reader, msg, nil) //sm2签名
- if err != nil {
- return nil, nil, err
- }
- return sign, &priv.PublicKey, err
- }
-
- /*
- 验证签名是否正常
- */
- func VerSm2Sig(pub *sm2.PublicKey, msg []byte, sign []byte) bool {
- isok := pub.Verify(msg, sign)
- if !isok {
- return false
- }
- return true
- }
以上代码中,SM2用到的库为:
github.com/tjfoc/gmsm
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。