[加解密]js/python/golang 兼容AES(CBC/ECB)加解密(2)--CBC模式

CBC模式用起来差别不大,就是多了一个iv

还是先来js的

  
  
  
      
    Title  
  
  
  
  
  
  
  
  

再来go的

package main

import (
	"bytes"
	"crypto/cipher"
	"crypto/aes"
	"encoding/base64"
	"fmt"
)

func main() {
	testAes()
}

func testAes() {
	// AES-128。key长度:16, 24, 32 bytes 对应 AES-128, AES-192, AES-256
	key := []byte("beijingtiananmen")
	result, err := AesEncrypt([]byte("www.baidu.com"), key)
	if err != nil {
		panic(err)
	}
	fmt.Println(base64.StdEncoding.EncodeToString(result))    //zero UR5c4C1iW5mIdxrv5rxo4w==,pkcs jE7BUAKWpdJWb2ulcFWd/g==  和pthon,js相同 
	origData, err := AesDecrypt(result, key)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(origData))
}

func AesEncrypt(origData, key []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	//origData = PKCS5Padding(origData, blockSize)
	 origData = ZeroPadding(origData, block.BlockSize())
	blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])  //iv=key
	crypted := make([]byte, len(origData))
	// 根据CryptBlocks方法的说明,如下方式初始化crypted也可以
	// crypted := origData
	blockMode.CryptBlocks(crypted, origData)
	return crypted, nil
}

func AesDecrypt(crypted, key []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
	origData := make([]byte, len(crypted))
	// origData := crypted
	blockMode.CryptBlocks(origData, crypted)
	origData = PKCS5UnPadding(origData)
	// origData = ZeroUnPadding(origData)
	return origData, nil
}

func ZeroPadding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{0}, padding)
	return append(ciphertext, padtext...)
}

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

func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

func PKCS5UnPadding(origData []byte) []byte {
	length := len(origData)
	// 去掉最后一个字节 unpadding 次
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}

python的

#coding=utf-8
#AES AES/CBC/PKCS5|Zero

import base64
from Crypto.Cipher import AES

def ByteToHex( bins ):
    """
    Convert a byte string to it's hex string representation e.g. for output.
    """
    return ''.join( [ "%02X" % x for x in bins ] ).strip()


'''
采用AES对称加密算法
'''
# str不是16的倍数那就补足为16的倍数. ZeroPadding

'''
    在PKCS5Padding中,明确定义Block的大小是8位
    而在PKCS7Padding定义中,对于块的大小是不确定的,可以在1-255之间

    PKCS #7 填充字符串由一个字节序列组成,每个字节填充该字节序列的长度。
    假定块长度为 8,数据长度为 9,
    数据: FF FF FF FF FF FF FF FF FF
    PKCS7 填充: FF FF FF FF FF FF FF FF FF 01 01 01 01 01 01 01   ?应该是填充01
    
    python3:填充bytes(这个说法不对,AES的参数是字符串,不是byte)
    length = 16 - (len(data) % 16)
    data += bytes([length])*length

 
    python2:填充字符串
    length = 16 - (len(data) % 16)
    data += chr(length)*length

    
    pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
    unpad = lambda s : s[0:-ord(s[-1])]

'''
def add_to_16(value):
    while len(value) % 16 != 0:
        value += '\0'
    return str.encode(value)  # 返回bytes

    
def ZeroPadding(value,bs):
    while len(value) % bs != 0:
        value += '\0'
    return str.encode(value)  # 返回bytes

#对于python,不需要zerounpadding?  去掉尾部的\0
    
def PKCS7Padding(value,bs):
    pad = lambda s: s + (bs - len(s) % bs) * chr(bs - len(s) % bs)#PKS7 
    return str.encode(pad(value)) # 返回bytes
    
def PKCS7UnPadding(value):
    #value = value[:-value[-1]]
    unpad = lambda s : s[0:-ord(s[-1])]  #获得数据的长度,截取
    return unpad(value)

#加密方法
def encrypt_oracle():
    # 秘钥
    #key = '123456'
    key = 'beijingtiananmen'
    # 待加密文本
    #text = 'abc123def456'
    text = 'www.baidu.com'
    iv=add_to_16(key)   #多了个iv
    # 初始化加密器
    aes = AES.new(add_to_16(key), AES.MODE_CBC,iv)
    bs = AES.block_size
    pad2 = lambda s: s + (bs - len(s) % bs) * chr(bs - len(s) % bs)#PKS7 
    
    #先进行aes加密
    #encrypt_aes = aes.encrypt(add_to_16(text))
    #Zeropadding
    #encrypt_aes = aes.encrypt(add_to_16(text))
    #Pkcs7 padding
    encrypt_aes = aes.encrypt(str.encode(pad2(text)))
    #转为hex
    print(ByteToHex(encrypt_aes))    #转为字符串 71462668992DB7B3FE76ABFE22376CF6
    #用base64转成字符串形式
    encrypted_text = str(base64.encodebytes(encrypt_aes), encoding='utf-8')  # 执行加密并转码返回bytes
    print(encrypted_text)   #zeropadding:   UR5c4C1iW5mIdxrv5rxo4w==     Pkcs7/Pkcs7: jE7BUAKWpdJWb2ulcFWd/g==
    #和js的 结果相同 http://tool.chacuo.net/cryptaes
    return encrypted_text
    
#解密方法
def decrypt_oralce(text):
    # 秘钥
    #key = '123456'
    key = 'beijingtiananmen'
    # 密文
    #text = 'qR/TQk4INsWeXdMSbCDDdA=='
    #text = 'cUYmaJktt7P+dqv+Ijds9g=='
    # 初始化加密器
    aes = AES.new(add_to_16(key), AES.MODE_CBC,add_to_16(key))
    #优先逆向解密base64成bytes
    base64_decrypted = base64.decodebytes(text.encode(encoding='utf-8'))
    #
    decrypted_text = str(aes.decrypt(base64_decrypted),encoding='utf-8') # 执行解密密并转码返回str
    unpad = lambda s : s[0:-ord(s[-1])]
    #PADDING = '\0'
    #print decrypted_text.rstrip(PADDING)  #zeropadding只见诶去掉结尾\0
    print(unpad(decrypted_text))

if __name__ == '__main__':
    en=encrypt_oracle()
    decrypt_oralce(en)



你可能感兴趣的:(python,go,javascript)