3

Golang-AES加密(CBC模式,PKCS7填充)

 1 year ago
source link: https://studygolang.com/articles/14251?fr=sidebar
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Golang-AES加密(CBC模式,PKCS7填充)

Night_Witcher · 2018-08-16 01:34:43 · 6390 次点击 · 预计阅读时间 3 分钟 · 大约8小时之前 开始浏览    
这是一个创建于 2018-08-16 01:34:43 的文章,其中的信息可能已经有所发展或是发生改变。

对称加密算法,即加密和解密使用一样的密钥的加解密算法。
分组密码(block cipher),是每次只能处理特定长度的一块(block)数据的一类加解密算法。
目前常见的对称加密算法DES、3DES、AES都是属于分组密码。

Golang没有像PHP那样提供一个现成的aes加密函数,不过标准库里有crypto,利用里面的aes等可以自己封装个加密函数,不过需要理解下整个加解密的过程和原理


AES加密详解

1. 参考文章golang 中AES加密详解

2. 这里使用的是AES加密中的CBC模式,块加密需要划分成整数长度相等个消息块不断加密(串行),分组长度是固定128位,但密钥的长度可以使用128位,192位或者256位(这里指的是bit),即密钥16,24,32长度对应AES-128, AES-192, AES-256。

3.初始向量要求随机,但不需要保密。


自己研究代码比较清晰,根据golang标准库AES实例代码,再参考网上的PKCS7填充,最后进行base64的编码(因为加密后有些字符不可见)。最后Encrypt和Dncrypt两个就是AES加解密(CBC模式,PKCS7填充)封装后的函数,密钥位数限定16,24,32(要注意的是密钥无论多少,blocksize都是固定16)

package encrypt

import (
   "bytes"
   "crypto/aes"
   "io"
   "crypto/rand"
   "crypto/cipher"
   "encoding/base64"
)

/*CBC加密 按照golang标准库的例子代码
不过里面没有填充的部分,所以补上
*/

//使用PKCS7进行填充,IOS也是7
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
   padding := blockSize - len(ciphertext) % blockSize
   padtext := bytes.Repeat([]byte{byte(padding)}, padding)
   return append(ciphertext, padtext...)
}

func PKCS7UnPadding(origData []byte) []byte {
   length := len(origData)
   unpadding := int(origData[length-1])
   return origData[:(length - unpadding)]
}

//aes加密,填充秘钥key的16位,24,32分别对应AES-128, AES-192, or AES-256.
func AesCBCEncrypt(rawData,key []byte) ([]byte, error) {
   block, err := aes.NewCipher(key)
   if err != nil {
       panic(err)
   }

   //填充原文
   blockSize := block.BlockSize()
   rawData = PKCS7Padding(rawData, blockSize)
   //初始向量IV必须是唯一,但不需要保密
   cipherText := make([]byte,blockSize+len(rawData))
   //block大小 16
   iv := cipherText[:blockSize]
   if _, err := io.ReadFull(rand.Reader,iv); err != nil {
       panic(err)
   }

   //block大小和初始向量大小一定要一致
   mode := cipher.NewCBCEncrypter(block,iv)
   mode.CryptBlocks(cipherText[blockSize:],rawData)

   return cipherText, nil
}

func AesCBCDncrypt(encryptData, key []byte) ([]byte,error) {
   block, err := aes.NewCipher(key)
   if err != nil {
       panic(err)
   }

   blockSize := block.BlockSize()

   if len(encryptData) < blockSize {
       panic("ciphertext too short")
   }
   iv := encryptData[:blockSize]
   encryptData = encryptData[blockSize:]

   // CBC mode always works in whole blocks.
   if len(encryptData)%blockSize != 0 {
       panic("ciphertext is not a multiple of the block size")
   }

   mode := cipher.NewCBCDecrypter(block, iv)

   // CryptBlocks can work in-place if the two arguments are the same.
   mode.CryptBlocks(encryptData, encryptData)
   //解填充
   encryptData = PKCS7UnPadding(encryptData)
   return encryptData,nil
}


func Encrypt(rawData,key []byte) (string,error) {
   data, err:= AesCBCEncrypt(rawData,key)
   if err != nil {
       return "",err
   }
   return base64.StdEncoding.EncodeToString(data),nil
}

func Dncrypt(rawData string,key []byte) (string,error) {
   data,err := base64.StdEncoding.DecodeString(rawData)
   if err != nil {
       return "",err
   }
   dnData,err := AesCBCDncrypt(data,key)
   if err != nil {
       return "",err
   }
   return string(dnData),nil
}

  1. golang 中AES加密详解

有疑问加站长微信联系(非本文作者)

280

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK