赞
踩
SM4算法是我国商用密码标准,其前身是SMS4算法。SM4算法是一个分组加密算法,分组长度和密钥长度均128bit。SM4算法使用32轮的非线性迭代结构。SM4在最后一轮非线性迭代之后加上了一个反序变换,因此SM4中只要解密密钥是加密密钥的逆序,它的解密算法与加密算法就可以保持一致。SM4的主体运算是非平衡Feistel网络。
整体逻辑结构如图所示,经过32轮变换把明文变换为密文。
SM4算法类似于国际密码算法AES。
代码示例:
1. CBC分组模式(Cipher Block Chaining ,密码分组链模式)
- package main
-
- import (
- "bytes"
- "crypto/cipher"
- "encoding/base64"
- "fmt"
- "github.com/tjfoc/gmsm/sm4"
- "log"
- )
-
- func main() {
- SM4()
- }
- func SM4() {
- // 128比特密钥
- key := []byte("1234567890abcdef")
- // 128比特iv
- iv := make([]byte, sm4.BlockSize)
- data := []byte("hello 国密SM4")
- fmt.Println("SM4加密密文是:", string(data))
- ciphertxt, err := sm4Encrypt(key, iv, data)
- if err != nil {
- log.Fatal(err)
- }
- fmt.Printf("SM4加密结果: %x\n", ciphertxt)
- fmt.Println("SM4加密结果:\n", base64.StdEncoding.EncodeToString(ciphertxt))
-
- res, err := sm4Decrypt(key, iv, ciphertxt)
- if err != nil {
- log.Fatal(err)
- }
- fmt.Println("SM4解密密文是:", string(res))
- }
- func sm4Encrypt(key, iv, plainText []byte) ([]byte, error) {
- block, err := sm4.NewCipher(key)
- if err != nil {
- return nil, err
- }
- blockSize := block.BlockSize()
- origData := pkcs5Padding(plainText, blockSize)
- blockMode := cipher.NewCBCEncrypter(block, iv)
- cryted := make([]byte, len(origData))
- blockMode.CryptBlocks(cryted, origData)
- return cryted, nil
- }
-
- func sm4Decrypt(key, iv, cipherText []byte) ([]byte, error) {
- block, err := sm4.NewCipher(key)
- if err != nil {
- return nil, err
- }
- blockMode := cipher.NewCBCDecrypter(block, iv)
- origData := make([]byte, len(cipherText))
- blockMode.CryptBlocks(origData, cipherText)
- origData = pkcs5UnPadding(origData)
- return origData, nil
- }
-
- // pkcs5填充
- func pkcs5Padding(src []byte, blockSize int) []byte {
- padding := blockSize - len(src)%blockSize
- padtext := bytes.Repeat([]byte{byte(padding)}, padding)
- return append(src, padtext...)
- }
-
- func pkcs5UnPadding(src []byte) []byte {
- length := len(src)
- if length == 0 {
- return nil
- }
- unpadding := int(src[length-1])
- return src[:(length - unpadding)]
- }
2.CFB分组模式(Cipher FeedBack ,密码反馈模式):
- package main
-
- import (
- "crypto/cipher"
- "crypto/rand"
- "fmt"
- "github.com/tjfoc/gmsm/sm4"
- "io"
- )
-
- func main() {
- key := []byte("1234567890abcdef")
- iv, encrypt, err := Sm4EncryptCfb([]byte("hello 江洲"), key)
- fmt.Printf("iv:%X,encrpyt:%X,err:%v\n", iv, encrypt, err)
- plainData, err := Sm4DecryptCfb(encrypt, key, iv)
- fmt.Printf("解密数据:%s,err:%v", plainData, err)
-
- }
-
- // Sm4EncryptCfb sm4加密,CFB模式
- //goland:noinspection GoNameStartsWithPackageName
- func Sm4EncryptCfb(plainData, key []byte) (iv, encryptData []byte, err error) {
- block, err := sm4.NewCipher(key)
- if err != nil {
- return nil, nil, err
- }
- encryptData = make([]byte, len(plainData))
- iv = make([]byte, sm4.BlockSize)
- fmt.Println("iv:", iv)
- if _, err = io.ReadFull(rand.Reader, iv); err != nil {
- return nil, nil, err
- }
- mode := cipher.NewCFBEncrypter(block, iv)
- mode.XORKeyStream(encryptData, plainData)
- fmt.Println("iv", iv)
- return
- }
-
- // Sm4DecryptCfb sm4解密,CFB模式
- //goland:noinspection GoNameStartsWithPackageName
- func Sm4DecryptCfb(encryptData, key, iv []byte) (plainData []byte, err error) {
- block, err := sm4.NewCipher(key)
- if err != nil {
- return nil, err
- }
- plainData = make([]byte, len(encryptData))
- mode := cipher.NewCFBDecrypter(block, iv)
- mode.XORKeyStream(plainData, encryptData)
- return
- }
3.OFB分组模式(Output FeedBack,输出反馈模式)
- package main
-
- import (
- "crypto/cipher"
- "crypto/rand"
- "fmt"
- "github.com/tjfoc/gmsm/sm4"
- "io"
- )
-
- func main() {
- key := []byte("1234567890abcdef")
- iv, encryptData, err := Sm4EncryptOfb([]byte("hello 江洲"), key)
- fmt.Printf("iv:%X,encrpyt:%X,err:%v\n", iv, encryptData, err)
- plainData, err := Sm4DecryptOfb(encryptData, key, iv)
- fmt.Println("加密的数据为:", string(plainData))
- }
-
- // Sm4EncryptOfb sm4加密,OFB模式
- //goland:noinspection GoNameStartsWithPackageName
- func Sm4EncryptOfb(plainData, key []byte) (iv, encryptData []byte, err error) {
- block, err := sm4.NewCipher(key)
- if err != nil {
- return nil, nil, err
- }
- encryptData = make([]byte, len(plainData))
- iv = make([]byte, sm4.BlockSize)
- if _, err = io.ReadFull(rand.Reader, iv); err != nil {
- return nil, nil, err
- }
- mode := cipher.NewOFB(block, iv)
- mode.XORKeyStream(encryptData, plainData)
- return
- }
-
- // Sm4DecryptOfb sm4解密,OFB模式
- //goland:noinspection GoNameStartsWithPackageName
- func Sm4DecryptOfb(encryptData, key, iv []byte) (plainData []byte, err error) {
- block, err := sm4.NewCipher(key)
- if err != nil {
- return nil, err
- }
- plainData = make([]byte, len(encryptData))
- mode := cipher.NewOFB(block, iv)
- mode.XORKeyStream(plainData, encryptData)
- return
- }
以上代码中,SM4用到的库为:github.com/tjfoc/gmsm
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。