当前位置:   article > 正文

国密SM2——golang的实现_golang sm2

golang sm2

SM2是国家密码管理局于2010年12月17日发布的椭圆曲线公钥密码算法。

由于SM2是基于椭圆曲线的公钥加密算法,与RSA一样都是非对称密码算法。

由于 RSA 算法和 ECC 算法这一明显不同,使得 ECC 算法的单位安全强度高于 RSA算 法。

也就是说,要达到同样的安全强度,ECC 算法所需的密钥长度远比 RSA 算法低

代码示例:

  1. package main
  2. import (
  3. "crypto/rand"
  4. "encoding/base64"
  5. "encoding/hex"
  6. "fmt"
  7. "github.com/tjfoc/gmsm/sm2"
  8. "github.com/tjfoc/gmsm/x509"
  9. "os"
  10. )
  11. type GMCrypt struct {
  12. PublicFile string
  13. PrivateFile string
  14. }
  15. var (
  16. path = "./"
  17. privateFile = "private.pem" //私钥文件
  18. publicFile = "public.pem" //公钥文件
  19. data = "hello 国密"
  20. )
  21. func main() {
  22. //秘钥生成
  23. GenerateSM2Key()
  24. crypt := GMCrypt{
  25. PublicFile: path + publicFile,
  26. PrivateFile: path + privateFile,
  27. }
  28. //加密
  29. encryptText, _ := crypt.Encrypt(data)
  30. //解密
  31. decryptText, err := crypt.Decrypt(encryptText)
  32. fmt.Println(err)
  33. fmt.Println(decryptText)
  34. //签名
  35. msg := []byte("hello 国密")
  36. sig, key, err := CreateSm2Sig(msg)
  37. fmt.Printf("签名结果:%x, 公钥:%v, err:%v\n", sig, key, err)
  38. //验证签名
  39. verSm2Sig := VerSm2Sig(key, msg, sig)
  40. fmt.Println("验证结果为:", verSm2Sig)
  41. }
  42. //生成公钥、私钥
  43. func GenerateSM2Key() {
  44. //1. 秘钥产生
  45. priKey, err := sm2.GenerateKey(rand.Reader)
  46. if err != nil {
  47. fmt.Println("秘钥产生失败:", err)
  48. os.Exit(1)
  49. }
  50. pubKey := &priKey.PublicKey
  51. //生成文件 保存私钥
  52. //x509编码
  53. pemPrivKey, err := x509.WritePrivateKeyToPem(priKey, nil)
  54. privateFile, err := os.Create(path + privateFile)
  55. defer privateFile.Close()
  56. privateFile.Write(pemPrivKey)
  57. pemPublicKey, err := x509.WritePublicKeyToPem(pubKey)
  58. publicFile, err := os.Create(path + publicFile)
  59. defer publicFile.Close()
  60. publicFile.Write(pemPublicKey)
  61. }
  62. func readPemCxt(path string) ([]byte, error) {
  63. file, err := os.Open(path)
  64. if err != nil {
  65. return []byte{}, err
  66. }
  67. defer file.Close()
  68. fileInfo, err := file.Stat()
  69. if err != nil {
  70. return []byte{}, err
  71. }
  72. buf := make([]byte, fileInfo.Size())
  73. _, err = file.Read(buf)
  74. if err != nil {
  75. return []byte{}, err
  76. }
  77. return buf, err
  78. }
  79. //数据加密
  80. func (s *GMCrypt) Encrypt(data string) (string, error) {
  81. pub, err := readPemCxt(s.PublicFile)
  82. if err != nil {
  83. return "", err
  84. }
  85. //read public key
  86. publicKeyFromPem, err := x509.ReadPublicKeyFromPem(pub)
  87. if err != nil {
  88. fmt.Println(err)
  89. return "", err
  90. }
  91. ciphertxt, err := publicKeyFromPem.EncryptAsn1([]byte(data), rand.Reader)
  92. if err != nil {
  93. return "", err
  94. }
  95. return base64.StdEncoding.EncodeToString(ciphertxt), nil
  96. }
  97. //数据解密
  98. func (s *GMCrypt) Decrypt(data string) (string, error) {
  99. pri, err := readPemCxt(s.PrivateFile)
  100. if err != nil {
  101. return "", err
  102. }
  103. privateKeyFromPem, err := x509.ReadPrivateKeyFromPem(pri, nil)
  104. if err != nil {
  105. return "", err
  106. }
  107. ciphertxt, err := base64.StdEncoding.DecodeString(data)
  108. if err != nil {
  109. return "", err
  110. }
  111. plaintxt, err := privateKeyFromPem.DecryptAsn1(ciphertxt)
  112. if err != nil {
  113. return "", err
  114. }
  115. return string(plaintxt), nil
  116. }
  117. /*
  118. 使用私钥创建签名
  119. */
  120. func CreateSm2Sig(msg []byte) ([]byte, *sm2.PublicKey, error) {
  121. //读取密钥对
  122. pri, err := readPemCxt(path + privateFile)
  123. privateKey, _ := x509.ReadPrivateKeyFromPem(pri, nil)
  124. c := sm2.P256Sm2() //椭圆曲线
  125. priv := new(sm2.PrivateKey)
  126. priv.PublicKey.Curve = c
  127. priv.D = privateKey.D
  128. priv.PublicKey.X = privateKey.X
  129. priv.PublicKey.Y = privateKey.Y
  130. sign, err := priv.Sign(rand.Reader, msg, nil) //sm2签名
  131. if err != nil {
  132. return nil, nil, err
  133. }
  134. return sign, &priv.PublicKey, err
  135. }
  136. /*
  137. 验证签名是否正常
  138. */
  139. func VerSm2Sig(pub *sm2.PublicKey, msg []byte, sign []byte) bool {
  140. isok := pub.Verify(msg, sign)
  141. if !isok {
  142. return false
  143. }
  144. return true
  145. }

以上代码中,SM2用到的库为:

github.com/tjfoc/gmsm
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/483330
推荐阅读
相关标签
  

闽ICP备14008679号