Created
July 5, 2020 11:43
-
-
Save playniuniu/5ad94c9a7bee9c132f95b446bdc892c2 to your computer and use it in GitHub Desktop.
Python3 & Go AES/CBC/PKS7Padding
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "bytes" | |
| "crypto/aes" | |
| "crypto/cipher" | |
| "crypto/rand" | |
| "encoding/base64" | |
| "io" | |
| "log" | |
| ) | |
| //使用PKCS7进行填充 | |
| 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, 源码好像是写死16了 | |
| func AesCBCEncrypt(rawData, key []byte) ([]byte, error) { | |
| block, err := aes.NewCipher(key) | |
| if err != nil { | |
| return nil, err | |
| } | |
| //填充原文 | |
| blockSize := block.BlockSize() | |
| rawData = PKCS7Padding(rawData, blockSize) | |
| //初始向量IV必须是唯一,但不需要保密 | |
| cipherText := make([]byte, blockSize+len(rawData)) | |
| iv := cipherText[:blockSize] // 16 个 0 | |
| if _, err := io.ReadFull(rand.Reader, iv); err != nil { | |
| return nil, err | |
| } | |
| //block大小和初始向量大小一定要一致 | |
| mode := cipher.NewCBCEncrypter(block, iv) | |
| mode.CryptBlocks(cipherText[blockSize:], rawData) | |
| return cipherText, nil | |
| } | |
| func AesCBCDecrypt(encryptData, key []byte) ([]byte, error) { | |
| block, err := aes.NewCipher(key) | |
| if err != nil { | |
| return nil, 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 Decrypt(rawData string, key []byte) (string, error) { | |
| data, err := base64.StdEncoding.DecodeString(rawData) | |
| if err != nil { | |
| return "", err | |
| } | |
| dnData, err := AesCBCDecrypt(data, key) | |
| if err != nil { | |
| return "", err | |
| } | |
| return string(dnData), nil | |
| } | |
| func main() { | |
| rawData:= []byte("password123") | |
| key := []byte("1234567890123456") | |
| str, err := Encrypt(rawData, key) | |
| if err == nil { | |
| log.Printf("success: %s", str) | |
| } else { | |
| log.Fatalf("failed: %v", err) | |
| } | |
| encrytpData := "2LWYSMdnDJSym1TSN54ueo21bVAujtFK8+fMaqOBxFU=" | |
| str, err = Decrypt(encrytpData, key) | |
| if err == nil { | |
| log.Printf("success: %s", str) | |
| } else { | |
| log.Fatalf("failed: %v", err) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import base64 | |
| from Crypto.Cipher import AES | |
| def pkcs7padding(text): | |
| """ | |
| 明文使用PKCS7填充 | |
| 最终调用AES加密方法时,传入的是一个byte数组,要求是16的整数倍,因此需要对明文进行处理 | |
| """ | |
| bs = AES.block_size # 16 | |
| length = len(text) | |
| bytes_length = len(bytes(text, encoding='utf-8')) | |
| # tips:utf-8编码时,英文占1个byte,而中文占3个byte | |
| padding_size = length if (bytes_length == length) else bytes_length | |
| padding = bs - padding_size % bs | |
| # tips:chr(padding)看与其它语言的约定,有的会使用'\0' | |
| padding_text = chr(padding) * padding | |
| return text + padding_text | |
| def pkcs7unpadding(text): | |
| """ | |
| 处理使用PKCS7填充过的数据 | |
| :param text: 解密后的字符串 | |
| :return: | |
| """ | |
| length = len(text) | |
| unpadding = ord(text[length - 1]) | |
| return text[0:length - unpadding] | |
| def encrypt(key, content): | |
| """ | |
| AES加密 | |
| key,iv使用同一个 | |
| 模式cbc | |
| 填充pkcs7 | |
| :param key: 密钥 | |
| :param content: 加密内容 | |
| :return: | |
| """ | |
| key_bytes = bytes(key, encoding='utf-8') | |
| iv = b'\x00' * 16 | |
| cipher = AES.new(key_bytes, AES.MODE_CBC, iv) | |
| # 处理明文 | |
| content_padding = pkcs7padding(content) | |
| # 加密 | |
| encrypt_bytes = cipher.encrypt(iv + bytes(content_padding, encoding='utf-8')) | |
| # 重新编码 | |
| result = str(base64.b64encode(encrypt_bytes), encoding='utf-8') | |
| return result | |
| def decrypt(key, content): | |
| """ | |
| AES解密 | |
| 模式cbc | |
| 去填充pkcs7 | |
| """ | |
| # base64解码 | |
| encrypt_bytes = base64.b64decode(content) | |
| # key, iv | |
| key_bytes = bytes(key, encoding='utf-8') | |
| iv = encrypt_bytes[:16] | |
| # 解密 | |
| cipher = AES.new(key_bytes, AES.MODE_CBC, iv) | |
| decrypt_bytes = cipher.decrypt(encrypt_bytes[16:]) | |
| # 重新编码 | |
| result = str(decrypt_bytes, encoding='utf-8') | |
| # 去除填充内容 | |
| result = pkcs7unpadding(result) | |
| return result | |
| if __name__ == '__main__': | |
| aes_key = "1234567890123456" | |
| # 加密 | |
| raw_data = "password123" | |
| encrypt_data = encrypt(aes_key, raw_data) | |
| print(encrypt_data) | |
| # 解密 | |
| encrypt_data = "2LWYSMdnDJSym1TSN54ueo21bVAujtFK8+fMaqOBxFU=" | |
| decrypt_data = decrypt(aes_key, encrypt_data) | |
| print(decrypt_data) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment