Skip to content

Instantly share code, notes, and snippets.

@playniuniu
Created July 5, 2020 11:43
Show Gist options
  • Select an option

  • Save playniuniu/5ad94c9a7bee9c132f95b446bdc892c2 to your computer and use it in GitHub Desktop.

Select an option

Save playniuniu/5ad94c9a7bee9c132f95b446bdc892c2 to your computer and use it in GitHub Desktop.
Python3 & Go AES/CBC/PKS7Padding
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)
}
}
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