上下文:博主最近在做python代码迁移go代码的工作,其中涉及到AES加解密一块的逻辑,然后发现GO版和Python版输出总是不一致的问题。在仔细阅读Python源码后,发现AES加解密存在多种的模式概念(说白了,就是AES加密的几种不同的策略),我也没去细看,感兴趣的朋友,请自行查阅。
来看看典型的Python代码处理:
import base64
from Crypto.Cipher import AES
def pkcs7pad(text):
pad = 16 - len(text) % 16
return text + pad * chr(pad)
cipher = AES.new("你的secret key")
data = cipher.encrypt(pkcs7pad("要加密的字符串"))
base64.b64encode(data)
代码很简洁,阅读源码后,大有学问。上述方式,默认使用的AES ECB模式进行加密的。但是Go源码默认只支持CBC/CFB两种模式,并未提供ECB模式。作者如是描述道:We left ECB out intentionally: it's insecure, and if needed it's trivial to implement. 具体细节可访问:Go Issues 如果是这样的话,就尴尬了,肿么办。issues的回复中,看到这么一段描述:ECB is essentially "no mode" and while it isn't supported in a named fashion, crypto/cipher.Block.Encrypt and Decrypt implement it on a block by block basis. 瞬间又复活了,马上开始调整Go代码,最终实现和上述Python代码同secret、同加密字符串下拿到相同的结果输出。代码如下:
import (
"fmt"
"bytes"
"crypto/aes"
"encoding/base64"
)
func pkcs7pad(text string) string {
pad := 16 - len(text)%16
var buffer bytes.Buffer
for i := 0; i < pad; i++ {
buffer.WriteString(string(pad))
}
text = text + buffer.String()
return text
}
func main() {
block, _ := aes.NewCipher("你的secret key")
var plaintext = pkcs7pad("要加密的字符串")
bs := block.BlockSize()
if len(plaintext) % bs != 0 {
panic("Need a multiple of the blocksize")
}
cipherText := make([]byte, len(plaintext))
targetText := make([]byte, 0)
for len(plaintext) > 0 {
block.Encrypt(cipherText, []byte(plaintext))
plaintext = plaintext[bs:]
targetText = append(targetText, cipherText[:bs] ...)
cipherText = cipherText[bs:]
}
b64 := base64.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
fmt.Println(b64.EncodeToString(targetText))
}