天天看點

python 實作AES加密解密(對稱加密、ECB模式,配合base64)

什麼是對稱加密

什麼叫對稱加密呢,你可以這麼了解,一方通過密鑰将資訊加

密後,把密文傳給另一方,另一方通過這個相同的密鑰将密文

解密,轉換成可以了解的明文

什麼是非對稱加密

1. A要向B發送資訊,A和B都要産生一對用于加密和解密的公鑰和私鑰。

• 2. A的私鑰保密,A的公鑰告訴B;B的私鑰保密,B的公鑰告訴A。

• 3. A要給B發送資訊時,A用B的公鑰加密資訊,因為A知道B的公鑰。

• 4. A将這個消息發給B(已經用B的公鑰加密消息)。

• 5. B收到這個消息後,B用自己的私鑰解密A的消息,其他所有收到這個封包的人

都無法解密,因為隻有B才有B的私鑰。

• 6. 反過來,B向A發送消息也是一樣。

對稱加密和非對稱加密的對比:

對稱加密加密與解密使用的是同樣的密鑰,是以速度快,但由于需要将密鑰在網絡傳輸,是以

安全性不高。

• 非對稱加密使用了一對密鑰,公鑰與私鑰,是以安全性高,但加密與解密速度慢。

• 解決的辦法是将對稱加密的密鑰使用非對稱加密的公鑰進行加密,然後發送出去,接收方使用

私鑰進行解密得到對稱加密的密鑰,然後雙方可以使用對稱加密來進行溝通

什麼是AES:

AES 算法全稱是 Advanced Encryption Standard,是DES 算法的替代者,也是現在最流行的對稱加密算法之一。 

AES的加密流程:

1.把明文按照128bit拆分成若幹個明文塊。

2.按照選擇的填充方式來填充最後一個明文塊。

3.每一個明文塊利用AES加密器和密鑰,加密成密文塊。

4.拼接所有的密文塊,成為最終的密文結果。

AES加密三要素:

想要搞明白AES算法,首先要搞清楚三個基本概念。

秘鑰,填充,模式。

秘鑰:

對稱加密之是以對稱就是因為這類算法對明文的加密和解密使用的是同

一個密鑰。

AES支援三種長度的密鑰:128位,192位,256位

填充:

說到填充一定要說一下,AES 分組加密的特性,AES 加密并不是一股腦

将明文加密成密文的,而是把明文拆分成一個個獨立的明文塊,且每個

明文塊128bit。

假如一段明文長度是196bit,如果按每128bit一個明文塊來拆分的話,第

二個明文塊隻有64bit,不足128bit。這時候怎麼辦呢?就需要對明文塊

進行填充(Padding)。

填充的類型:(主要用到的有前三種)

• NoPadding

• PKCS7Padding

• ZeroPadding

• AnsiX923

• Iso10126

• Iso97971

模式:

AES的工作模式,展現在把明文塊加密成密文塊的處理過程中。AES

加密算法提供了五種不同的工作模式:

CBC、ECB、CTR、CFB、OFB

模式之間的主題思想是近似的,在處理細節上有一些差别。

ECB模式:

ECB模式(Electronic Codebook Book)是最簡單的工作模式,在該模

式下,每一個明文塊的加密都是完全獨立,互不幹涉的。

這樣的好處是什麼呢?

1.簡單

2.有利于并行計算

缺點同樣也很明顯:

相同的明文塊經過加密會變成相同的密文塊,是以安全性較差。

CBC模式:

CBC模式(Cipher Block Chaining)引入了一個新的概念:初始向量IV

(Initialization Vector)。

IV是做什麼用的呢?它的作用和MD5的“加鹽”有些類似,目的是防止同樣的明

文塊始終加密成同樣的密文塊。

CBC模式在每一個明文塊加密前會讓明文塊和一個值先做異或操作。

IV作為初始化變量,參與第一個明文塊的異或,後續的每一個明文塊和它 前一個

明文塊所加密出的密文塊相異或。

這樣相同的明文塊加密出的密文塊顯然是不一樣的。

CBC模式的好處是什麼呢?安全性更高

壞處也很明顯:

1.無法并行計算,性能上不如ECB

2.引入初始化向量IV,增加複雜度。

用JavaScript實作AES加密的腳本:

var CryptoJS = require("crypto-js");
var key ="ABC123456789";    //秘鑰
var iv = "1234567812345678";  //初始向量IV
function encrypt(text){
    return CryptoJS.AES.encrypt(text,CryptoJS.enc.Utf8.parse(key),{
        iv:CryptoJS.enc.Utf8.parse(iv),
        mode:CryptoJS.mode.CBC,  // CBC模式
        padding:CryptoJS.pad.Pkcs7 // 這裡選擇的填充類型為Pkcs7 ,還可能是ZeroPadding    NoPadding
    })
}
function decrypt(text){
    var result = CryptoJS.AES.decrypt(text,CryptoJS.enc.Utf8.parse(key),{
        iv:CryptoJS.enc.Utf8.parse(iv),
        mode:CryptoJS.mode.CBC,  //解密的模式必須和加密的模式相同,包括填充類型也需要相同。
        padding:CryptoJS.pad.Pkcs7
    })
    return result.toString(CryptoJS.enc.Utf8)
}
var text="測試AES加密";
var encoded=encrypt(text)
console.log(encoded.toString());
console.log(decrypt(encoded))
           

ECB模式下的,python代碼實作的例子

import base64
from Crypto.Cipher import AES

'''
采用AES對稱加密算法
'''
# str不是32的倍數那就補足為16的倍數
def add_to_32(value):
    while len(value) % 32 != 0:
        value += '\0'
    return str.encode(value)  # 傳回bytes

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

#加密方法
def encrypt_oracle(text):
    # 秘鑰
    key = 'VW1lMjAxMlRyaXAwMzA5AA=='
    # 待加密文本
    # 初始化加密器
    aes = AES.new(add_to_16(key), AES.MODE_ECB)
    #先進行aes加密
    encrypt_aes = aes.encrypt(add_to_16(text))
    #用base64轉成字元串形式
    encrypted_text = str(base64.encodebytes(encrypt_aes), encoding='utf-8')  # 執行加密并轉碼傳回bytes
    print(encrypted_text)
    return encrypted_text
#解密方法
def decrypt_oralce(text):
    # 秘鑰
    key = 'VW1lMjAxMlRyaXAwMzA5AA=='
    # 密文
    # 初始化加密器
    aes = AES.new(add_to_16(key), AES.MODE_ECB)
    #優先逆向解密base64成bytes
    base64_decrypted = base64.decodebytes(text.encode(encoding='utf-8'))
    #執行解密密并轉碼傳回str
    decrypted_text = str(aes.decrypt(base64_decrypted),encoding='utf-8').replace('\0','')
    print('decrypted_text',decrypted_text)
    return decrypted_text

if __name__ == '__main__':

    text = '''{'aaa': '111', 'bbb': '222'}'''
    entrypted_text = encrypt_oracle(text)

    decrypt_oralce(entrypted_text)
           

注意key是16位或者32位的,選擇對應的key加密函數。

參考:https://www.jianshu.com/p/717da8405002