1. 程式人生 > >python 加密與解密

python 加密與解密

 

加密演算法分類

對稱加密演算法:

對稱加密採用了對稱密碼編碼技術,它的特點是檔案加密和解密使用相同的金鑰

傳送方和接收方需要持有同一把金鑰,傳送訊息和接收訊息均使用該金鑰。

相對於非對稱加密,對稱加密具有更高的加解密速度,但雙方都需要事先知道金鑰,金鑰在傳輸過程中可能會被竊取,因此安全性沒有非對稱加密高。

常見的對稱加密演算法:DES,AES,3DES等等

非對稱加密演算法:

檔案加密需要公開金鑰(publickey)和私有金鑰(privatekey)。

接收方在傳送訊息前需要事先生成公鑰和私鑰,然後將公鑰傳送給傳送方。傳送放收到公鑰後,將待發送資料用公鑰加密,傳送給接收方。接收到收到資料後,用私鑰解密。

在這個過程中,公鑰負責加密,私鑰負責解密,資料在傳輸過程中即使被截獲,攻擊者由於沒有私鑰,因此也無法破解。

非對稱加密演算法的加解密速度低於對稱加密演算法,但是安全性更高

非對稱加密演算法:RSA、DSA、ECC等演算法

訊息摘要演算法:

訊息摘要演算法可以驗證資訊是否被篡改。

在資料傳送前,首先使用訊息摘要演算法生成該資料的簽名,然後簽名和資料一同傳送給接收者。

接收者收到資料後,對收到的資料採用訊息摘要演算法獲得簽名,最後比較簽名是否一致,以此來判斷資料在傳輸過程中是否發生修改。

 

加密庫

為了在 Linux 上安裝它,你可以使用以下pip 命令:

pip3 install 
-i https://pypi.douban.com/simple pycryptodome 在Windows 系統上安裝則稍有不同: pip3 install -i https://pypi.douban.com/simple pycryptodomex

 

DES加密

全稱為Data EncryptionStandard,即資料加密標準,是一種使用金鑰加密的塊演算法

入口引數有三個:Key、Data、Mode

Key為7個位元組共56位,是DES演算法的工作金鑰;

Data為8個位元組64位,是要被加密或被解密的資料;

Mode為DES的工作方式,有兩種:加密或解密

3DES(即Triple DES)是DES向AES過渡的加密演算法,

使用兩個金鑰,執行三次DES演算法,

加密的過程是加密-解密-加密

解密的過程是解密-加密-解密

#coding=utf-8
from Cryptodome.Cipher import DES

key = b'abcdefgh'  # 金鑰 8位或16位,必須為bytes


def pad(text):
    """
    # 加密函式,如果text不是8的倍數【加密文字text必須為8的倍數!】,那就補足為8的倍數
    :param text: 
    :return: 
    """
    while len(text) % 8 != 0:
        text += ' '
    return text


des = DES.new(key, DES.MODE_ECB)  # 建立一個DES例項
text = 'Python rocks!'
padded_text = pad(text)
encrypted_text = des.encrypt(padded_text.encode('utf-8'))  # 加密
print(encrypted_text)
# rstrip(' ')返回從字串末尾刪除所有字串的字串(預設空白字元)的副本
plain_text = des.decrypt(encrypted_text).decode().rstrip(' ')  # 解密
print(plain_text)

輸出

b'>\xfc\x1f\x16x\x87\xb2\x93\x0e\xfcH\x02\xd59VQ'
Python rocks!

 

AES加密

高階加密標準(英語:Advanced EncryptionStandard,縮寫:AES),這個標準用來替代原先的DES

AES的區塊長度固定為128 位元,金鑰長度則可以是128,192或256位元(16、24和32位元組)

大致步驟如下:

1、金鑰擴充套件(KeyExpansion),

2、初始輪(Initial Round),

3、重複輪(Rounds),每一輪又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey,

4、最終輪(Final Round),最終輪沒有MixColumns。

普通方式

#coding=utf-8
from Cryptodome.Cipher import AES
from binascii import b2a_hex, a2b_hex
#祕鑰,此處需要將字串轉為位元組
key = 'abcdefgh'
#加密內容需要長達16位字元,所以進行空格拼接
def pad(text):
    while len(text) % 16 != 0:
        text += ' '
    return text
#加密祕鑰需要長達16位字元,所以進行空格拼接
def pad_key(key):
    while len(key) % 16 != 0:
        key += ' '
    return key
#進行加密演算法,模式ECB模式,把疊加完16位的祕鑰傳進來
aes = AES.new(pad_key(key).encode(), AES.MODE_ECB)
#加密內容,此處需要將字串轉為位元組
text = 'hello'
#進行內容拼接16位字元後傳入加密類中,結果為位元組型別
encrypted_text = aes.encrypt(pad(text).encode())
encrypted_text_hex = b2a_hex(encrypted_text)
print(encrypted_text_hex)


# #此處是為了驗證是否能將位元組轉為字串後,進行解密成功
# #實際上a 就是 encrypted_text ,也就是加密後的內容
# #用aes物件進行解密,將位元組型別轉為str型別,錯誤編碼忽略不計
de = str(aes.decrypt(a2b_hex(encrypted_text_hex)), encoding='utf-8',errors="ignore")
# #獲取str從0開始到文字內容的字串長度。
print(de[:len(text)])

輸出:

b'c9f9f942485373f113dc07443ca8f2bf'
hello

 

面向物件方式

#coding=utf-8
from Cryptodome.Cipher import AES
from binascii import b2a_hex, a2b_hex

AES_LENGTH = 16

class prpcrypt():
    def __init__(self, key):
        self.key = key
        self.mode = AES.MODE_ECB
        self.cryptor = AES.new(self.pad_key(self.key).encode(), self.mode)

    # 加密函式,如果text不是16的倍數【加密文字text必須為16的倍數!】,那就補足為16的倍數
    # 加密內容需要長達16位字元,所以進行空格拼接
    def pad(self,text):
        while len(text) % AES_LENGTH != 0:
            text += ' '
        return text

    # 加密金鑰需要長達16位字元,所以進行空格拼接
    def pad_key(self,key):
        while len(key) % AES_LENGTH != 0:
            key += ' '
        return key

    def encrypt(self, text):

        # 這裡金鑰key 長度必須為16(AES-128)、24(AES-192)、或32(AES-256)Bytes 長度.目前AES-128足夠用
        # 加密的字元需要轉換為bytes
        # print(self.pad(text))
        self.ciphertext = self.cryptor.encrypt(self.pad(text).encode())
        # 因為AES加密時候得到的字串不一定是ascii字符集的,輸出到終端或者儲存時候可能存在問題
        # 所以這裡統一把加密後的字串轉化為16進位制字串
        return b2a_hex(self.ciphertext)

        # 解密後,去掉補足的空格用strip() 去掉

    def decrypt(self, text):
        plain_text = self.cryptor.decrypt(a2b_hex(text)).decode()
        return plain_text.rstrip(' ')


if __name__ == '__main__':
    pc = prpcrypt('abcdef')  # 初始化金鑰
    e = pc.encrypt("0123456789ABCDEF")
    d = pc.decrypt(e)
    print(e, d)
    e = pc.encrypt("00000000000000000000000000")
    d = pc.decrypt(e)
    print(e, d)

輸出:

b'011704c9ca48ae83fe63c9b245a48cde' 0123456789ABCDEF
b'efabdcfe552e429226b1d0a88e7fa19cd21c7524b38d9122a5fe0c967ce07409' 00000000000000000000000000

 

RSA加密

公鑰加密演算法,一種非對稱密碼演算法

公鑰加密,私鑰解密

3個引數:

rsa_n, rsa_e,message

rsa_n, rsa_e 用於生成公鑰

message: 需要加密的訊息

安裝 pip install rsa

使用

import rsa
from binascii import b2a_hex, a2b_hex



class rsacrypt():
    def __init__(self, pubkey, prikey):
        self.pubkey = pubkey
        self.prikey = prikey

    def encrypt(self, text):
        self.ciphertext = rsa.encrypt(text.encode(), self.pubkey)
        # 因為rsa加密時候得到的字串不一定是ascii字符集的,輸出到終端或者儲存時候可能存在問題
        # 所以這裡統一把加密後的字串轉化為16進位制字串
        return b2a_hex(self.ciphertext)

    def decrypt(self, text):
        decrypt_text = rsa.decrypt(a2b_hex(text), prikey)
        return decrypt_text


if __name__ == '__main__':
    pubkey, prikey = rsa.newkeys(256)
    rs_obj = rsacrypt(pubkey,prikey)
    text='hello'
    ency_text = rs_obj.encrypt(text)
    print(ency_text)
    print(rs_obj.decrypt(ency_text))

輸出:

b'923af53dbc976be4c727589bddd66ffd981120d1b230de4075cc3e06bca4e4f6'
b'hello'