当前位置:   article > 正文

国密SM4——golang的实现_golang sm4

golang sm4

SM4算法是我国商用密码标准,其前身是SMS4算法。SM4算法是一个分组加密算法,分组长度和密钥长度均128bit。SM4算法使用32轮的非线性迭代结构。SM4在最后一轮非线性迭代之后加上了一个反序变换,因此SM4中只要解密密钥是加密密钥的逆序,它的解密算法与加密算法就可以保持一致。SM4的主体运算是非平衡Feistel网络。

整体逻辑结构如图所示,经过32轮变换把明文变换为密文。

SM4算法类似于国际密码算法AES。

代码示例: 

1. CBC分组模式(Cipher Block Chaining ,密码分组链模式)

  1. package main
  2. import (
  3. "bytes"
  4. "crypto/cipher"
  5. "encoding/base64"
  6. "fmt"
  7. "github.com/tjfoc/gmsm/sm4"
  8. "log"
  9. )
  10. func main() {
  11. SM4()
  12. }
  13. func SM4() {
  14. // 128比特密钥
  15. key := []byte("1234567890abcdef")
  16. // 128比特iv
  17. iv := make([]byte, sm4.BlockSize)
  18. data := []byte("hello 国密SM4")
  19. fmt.Println("SM4加密密文是:", string(data))
  20. ciphertxt, err := sm4Encrypt(key, iv, data)
  21. if err != nil {
  22. log.Fatal(err)
  23. }
  24. fmt.Printf("SM4加密结果: %x\n", ciphertxt)
  25. fmt.Println("SM4加密结果:\n", base64.StdEncoding.EncodeToString(ciphertxt))
  26. res, err := sm4Decrypt(key, iv, ciphertxt)
  27. if err != nil {
  28. log.Fatal(err)
  29. }
  30. fmt.Println("SM4解密密文是:", string(res))
  31. }
  32. func sm4Encrypt(key, iv, plainText []byte) ([]byte, error) {
  33. block, err := sm4.NewCipher(key)
  34. if err != nil {
  35. return nil, err
  36. }
  37. blockSize := block.BlockSize()
  38. origData := pkcs5Padding(plainText, blockSize)
  39. blockMode := cipher.NewCBCEncrypter(block, iv)
  40. cryted := make([]byte, len(origData))
  41. blockMode.CryptBlocks(cryted, origData)
  42. return cryted, nil
  43. }
  44. func sm4Decrypt(key, iv, cipherText []byte) ([]byte, error) {
  45. block, err := sm4.NewCipher(key)
  46. if err != nil {
  47. return nil, err
  48. }
  49. blockMode := cipher.NewCBCDecrypter(block, iv)
  50. origData := make([]byte, len(cipherText))
  51. blockMode.CryptBlocks(origData, cipherText)
  52. origData = pkcs5UnPadding(origData)
  53. return origData, nil
  54. }
  55. // pkcs5填充
  56. func pkcs5Padding(src []byte, blockSize int) []byte {
  57. padding := blockSize - len(src)%blockSize
  58. padtext := bytes.Repeat([]byte{byte(padding)}, padding)
  59. return append(src, padtext...)
  60. }
  61. func pkcs5UnPadding(src []byte) []byte {
  62. length := len(src)
  63. if length == 0 {
  64. return nil
  65. }
  66. unpadding := int(src[length-1])
  67. return src[:(length - unpadding)]
  68. }

2.CFB分组模式(Cipher FeedBack ,密码反馈模式):

  1. package main
  2. import (
  3. "crypto/cipher"
  4. "crypto/rand"
  5. "fmt"
  6. "github.com/tjfoc/gmsm/sm4"
  7. "io"
  8. )
  9. func main() {
  10. key := []byte("1234567890abcdef")
  11. iv, encrypt, err := Sm4EncryptCfb([]byte("hello 江洲"), key)
  12. fmt.Printf("iv:%X,encrpyt:%X,err:%v\n", iv, encrypt, err)
  13. plainData, err := Sm4DecryptCfb(encrypt, key, iv)
  14. fmt.Printf("解密数据:%s,err:%v", plainData, err)
  15. }
  16. // Sm4EncryptCfb sm4加密,CFB模式
  17. //goland:noinspection GoNameStartsWithPackageName
  18. func Sm4EncryptCfb(plainData, key []byte) (iv, encryptData []byte, err error) {
  19. block, err := sm4.NewCipher(key)
  20. if err != nil {
  21. return nil, nil, err
  22. }
  23. encryptData = make([]byte, len(plainData))
  24. iv = make([]byte, sm4.BlockSize)
  25. fmt.Println("iv:", iv)
  26. if _, err = io.ReadFull(rand.Reader, iv); err != nil {
  27. return nil, nil, err
  28. }
  29. mode := cipher.NewCFBEncrypter(block, iv)
  30. mode.XORKeyStream(encryptData, plainData)
  31. fmt.Println("iv", iv)
  32. return
  33. }
  34. // Sm4DecryptCfb sm4解密,CFB模式
  35. //goland:noinspection GoNameStartsWithPackageName
  36. func Sm4DecryptCfb(encryptData, key, iv []byte) (plainData []byte, err error) {
  37. block, err := sm4.NewCipher(key)
  38. if err != nil {
  39. return nil, err
  40. }
  41. plainData = make([]byte, len(encryptData))
  42. mode := cipher.NewCFBDecrypter(block, iv)
  43. mode.XORKeyStream(plainData, encryptData)
  44. return
  45. }

3.OFB分组模式(Output FeedBack,输出反馈模式)

  1. package main
  2. import (
  3. "crypto/cipher"
  4. "crypto/rand"
  5. "fmt"
  6. "github.com/tjfoc/gmsm/sm4"
  7. "io"
  8. )
  9. func main() {
  10. key := []byte("1234567890abcdef")
  11. iv, encryptData, err := Sm4EncryptOfb([]byte("hello 江洲"), key)
  12. fmt.Printf("iv:%X,encrpyt:%X,err:%v\n", iv, encryptData, err)
  13. plainData, err := Sm4DecryptOfb(encryptData, key, iv)
  14. fmt.Println("加密的数据为:", string(plainData))
  15. }
  16. // Sm4EncryptOfb sm4加密,OFB模式
  17. //goland:noinspection GoNameStartsWithPackageName
  18. func Sm4EncryptOfb(plainData, key []byte) (iv, encryptData []byte, err error) {
  19. block, err := sm4.NewCipher(key)
  20. if err != nil {
  21. return nil, nil, err
  22. }
  23. encryptData = make([]byte, len(plainData))
  24. iv = make([]byte, sm4.BlockSize)
  25. if _, err = io.ReadFull(rand.Reader, iv); err != nil {
  26. return nil, nil, err
  27. }
  28. mode := cipher.NewOFB(block, iv)
  29. mode.XORKeyStream(encryptData, plainData)
  30. return
  31. }
  32. // Sm4DecryptOfb sm4解密,OFB模式
  33. //goland:noinspection GoNameStartsWithPackageName
  34. func Sm4DecryptOfb(encryptData, key, iv []byte) (plainData []byte, err error) {
  35. block, err := sm4.NewCipher(key)
  36. if err != nil {
  37. return nil, err
  38. }
  39. plainData = make([]byte, len(encryptData))
  40. mode := cipher.NewOFB(block, iv)
  41. mode.XORKeyStream(plainData, encryptData)
  42. return
  43. }

以上代码中,SM4用到的库为:github.com/tjfoc/gmsm

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

闽ICP备14008679号