[加解密]js/python/golang 相容AES(CBC/ECB)加解密(2)--CBC模式
阿新 • • 發佈:2019-02-13
CBC模式用起來差別不大,就是多了一個iv
還是先來js的
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <script src="rollups/aes.js"></script> <script src="components/pad-zeropadding.js"></script> <body> <script> var key = CryptoJS.enc.Utf8.parse("beijingtiananmen"); var plaintText = 'www.baidu.com'; // 明文 //var plaintText = 'www.baidu.com'; // 明文 var iv=key; //16位字串 var encryptedData = CryptoJS.AES.encrypt(plaintText, key, { iv: CryptoJS.enc.Utf8.parse(iv), mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 //padding: CryptoJS.pad.ZeroPadding }); console.log("加密前:"+plaintText); console.log("加密後:"+encryptedData); //Pkcs7: WoCzvm6eZiM4/bx5o/CzGw== //ZeroPadding : cUYmaJktt7P+dqv+Ijds9g== encryptedData = encryptedData.ciphertext.toString(); var encryptedHexStr = CryptoJS.enc.Hex.parse(encryptedData); console.log("解密前hex:"+encryptedHexStr); var encryptedBase64Str = CryptoJS.enc.Base64.stringify(encryptedHexStr); console.log("解密前:"+encryptedBase64Str); var decryptedData = CryptoJS.AES.decrypt(encryptedBase64Str, key, { iv: CryptoJS.enc.Utf8.parse(iv), mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); var decryptedStr = decryptedData.toString(CryptoJS.enc.Utf8); console.log("解密後:"+decryptedStr); </script> </body> </html>
再來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)