溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python3常見(jiàn)加密計(jì)數(shù)方法有哪些

發(fā)布時(shí)間:2022-01-25 09:18:28 來(lái)源:億速云 閱讀:159 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹了Python3常見(jiàn)加密計(jì)數(shù)方法有哪些的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇Python3常見(jiàn)加密計(jì)數(shù)方法有哪些文章都會(huì)有所收獲,下面我們一起來(lái)看看吧。

Python 3 的標(biāo)準(zhǔn)庫(kù)中沒(méi)多少用來(lái)解決加密的,不過(guò)卻有用于處理哈希的庫(kù)。在這里我們會(huì)對(duì)其進(jìn)行一個(gè)簡(jiǎn)單的介紹,但重點(diǎn)會(huì)放在兩個(gè)第三方的軟件包:PyCrypto 和 cryptography 上。

Python3常見(jiàn)加密計(jì)數(shù)方法有哪些

哈希

如果需要用到安全哈希算法或是消息摘要算法,那么你可以使用標(biāo)準(zhǔn)庫(kù)中的 hashlib 模塊。這個(gè)模塊包含了符合 FIPS(美國(guó)聯(lián)邦信息處理標(biāo)準(zhǔn))的安全哈希算法,包括 SHA1,SHA224,SHA256,SHA384,SHA512 以及 RSA 的 MD5 算法。Python 也支持 adler32 以及 crc32 哈希函數(shù),不過(guò)它們?cè)?zlib 模塊中。

哈希的一個(gè)最常見(jiàn)的用法是,存儲(chǔ)密碼的哈希值而非密碼本身。當(dāng)然了,使用的哈希函數(shù)需要穩(wěn)健一點(diǎn),否則容易被破解。另一個(gè)常見(jiàn)的用法是,計(jì)算一個(gè)文件的哈希值,然后將這個(gè)文件和它的哈希值分別發(fā)送。接收到文件的人可以計(jì)算文件的哈希值,檢驗(yàn)是否與接受到的哈希值相符。如果兩者相符,就說(shuō)明文件在傳送的過(guò)程中未經(jīng)篡改。

讓我們?cè)囍鴦?chuàng)建一個(gè) md5 哈希:

>>> import hashlib
>>> md5 = hashlib.md5()
>>> md5.update('Python rocks!')
Traceback (most recent call last):
 File "", line 1, in    md5.update('Python rocks!')
TypeError: Unicode-objects must be encoded before hashing
>>> md5.update(b'Python rocks!')
>>> md5.digest()
b'/x14/x82/xec/x1b#d/xf6N}/x16*+[/x16/xf4w'

讓我們花點(diǎn)時(shí)間一行一行來(lái)講解。首先,我們導(dǎo)入 hashlib ,然后創(chuàng)建一個(gè) md5 哈希對(duì)象的實(shí)例。接著,我們向這個(gè)實(shí)例中添加一個(gè)字符串后,卻得到了報(bào)錯(cuò)信息。原來(lái),計(jì)算 md5 哈希時(shí),需要使用字節(jié)形式的字符串而非普通字符串。正確添加字符串后,我們調(diào)用它的 digest 函數(shù)來(lái)得到哈希值。如果你想要十六進(jìn)制的哈希值,也可以用以下方法:

>>> md5.hexdigest()'1482ec1b2364f64e7d162a2b5b16f477'

實(shí)際上,有一種精簡(jiǎn)的方法來(lái)創(chuàng)建哈希,下面我們看一下用這種方法創(chuàng)建一個(gè) sha1 哈希:

>>> sha = hashlib.sha1(b'Hello Python').hexdigest()
>>> sha'422fbfbc67fe17c86642c5eaaa48f8b670cbed1b'

可以看到,我們可以同時(shí)創(chuàng)建一個(gè)哈希實(shí)例并且調(diào)用其 digest 函數(shù)。然后,我們打印出這個(gè)哈希值看一下。這里我使用 sha1 哈希函數(shù)作為例子,但它不是特別安全,讀者可以隨意嘗試其他的哈希函數(shù)。

密鑰導(dǎo)出

Python 的標(biāo)準(zhǔn)庫(kù)對(duì)密鑰導(dǎo)出支持較弱。實(shí)際上,hashlib 函數(shù)庫(kù)提供的唯一方法就是 pbkdf2_hmac 函數(shù)。它是 PKCS#5 的基于口令的第二個(gè)密鑰導(dǎo)出函數(shù),并使用 HMAC 作為偽隨機(jī)函數(shù)。因?yàn)樗С帧凹欲}”和迭代操作,你可以使用類似的方法來(lái)哈希你的密碼。例如,如果你打算使用 SHA-256 加密方法,你將需要至少 16 個(gè)字節(jié)的“鹽”,以及最少 100000 次的迭代操作。

簡(jiǎn)單來(lái)說(shuō),“鹽”就是隨機(jī)的數(shù)據(jù),被用來(lái)加入到哈希的過(guò)程中,以加大破解的難度。這基本可以保護(hù)你的密碼免受字典和彩虹表的攻擊。

讓我們看一個(gè)簡(jiǎn)單的例子:

>>> import binascii
>>> dk = hashlib.pbkdf2_hmac(hash_name='sha256',
       password=b'bad_password34',
       salt=b'bad_salt',
       iterations=100000)
>>> binascii.hexlify(dk)
b'6e97bad21f6200f9087036a71e7ca9fa01a59e1d697f7e0284cd7f9b897d7c02'

這里,我們用 SHA256 對(duì)一個(gè)密碼進(jìn)行哈希,使用了一個(gè)糟糕的鹽,但經(jīng)過(guò)了 100000 次迭代操作。當(dāng)然,SHA 實(shí)際上并不被推薦用來(lái)創(chuàng)建密碼的密鑰。你應(yīng)該使用類似 scrypt 的算法來(lái)替代。另一個(gè)不錯(cuò)的選擇是使用一個(gè)叫 bcrypt 的第三方庫(kù),它是被專門設(shè)計(jì)出來(lái)哈希密碼的。

PyCryptodome

PyCrypto 可能是 Python 中密碼學(xué)方面最有名的第三方軟件包。可惜的是,它的開(kāi)發(fā)工作于 2012 年就已停止。其他人還在繼續(xù)發(fā)布最新版本的 PyCrypto,如果你不介意使用第三方的二進(jìn)制包,仍可以取得 Python 3.5 的相應(yīng)版本。比如,我在 Github 上找到了對(duì)應(yīng) Python 3.5 的 PyCrypto 二進(jìn)制包。

幸運(yùn)的是,有一個(gè)該項(xiàng)目的分支 PyCrytodome 取代了 PyCrypto 。為了在 Linux 上安裝它,你可以使用以下 pip 命令:

pip install pycryptodome

在 Windows 系統(tǒng)上安裝則稍有不同:

pip install pycryptodomex

如果你遇到了問(wèn)題,可能是因?yàn)槟銢](méi)有安裝正確的依賴包(LCTT 譯注:如 python-devel),或者你的 Windows 系統(tǒng)需要一個(gè)編譯器。如果你需要安裝上的幫助或技術(shù)支持,可以訪問(wèn) PyCryptodome 的網(wǎng)站。

還值得注意的是,PyCryptodome 在 PyCrypto 最后版本的基礎(chǔ)上有很多改進(jìn)。非常值得去訪問(wèn)它們的主頁(yè),看看有什么新的特性。

加密字符串

訪問(wèn)了他們的主頁(yè)之后,我們可以看一些例子。在第一個(gè)例子中,我們將使用 DES 算法來(lái)加密一個(gè)字符串:

>>> from Crypto.Cipher import DES
>>> key = 'abcdefgh'>>> def pad(text):
       while len(text) % 8 != 0:
           text += ' '       return text
>>> des = DES.new(key, DES.MODE_ECB)
>>> text = 'Python rocks!'>>> padded_text = pad(text)
>>> encrypted_text = des.encrypt(text)
Traceback (most recent call last):
 File "", line 1, in    encrypted_text = des.encrypt(text)
 File "C:/Programs/Python/Python35-32/lib/site-packages/Crypto/Cipher/blockalgo.py", line 244, in encrypt
   return self._cipher.encrypt(plaintext)
ValueError: Input strings must be a multiple of 8 in length
>>> encrypted_text = des.encrypt(padded_text)
>>> encrypted_text
b'>/xfc/x1f/x16x/x87/xb2/x93/x0e/xfcH/x02/xd59VQ'

這段代碼稍有些復(fù)雜,讓我們一點(diǎn)點(diǎn)來(lái)看。首先需要注意的是,DES 加密使用的密鑰長(zhǎng)度為 8 個(gè)字節(jié),這也是我們將密鑰變量設(shè)置為 8 個(gè)字符的原因。而我們需要加密的字符串的長(zhǎng)度必須是 8 的倍數(shù),所以我們創(chuàng)建了一個(gè)名為 pad 的函數(shù),來(lái)給一個(gè)字符串末尾填充空格,直到它的長(zhǎng)度是 8 的倍數(shù)。然后,我們創(chuàng)建了一個(gè) DES 的實(shí)例,以及我們需要加密的文本。我們還創(chuàng)建了一個(gè)經(jīng)過(guò)填充處理的文本。我們嘗試著對(duì)未經(jīng)填充處理的文本進(jìn)行加密,啊歐,報(bào)了一個(gè) ValueError 錯(cuò)誤!我們需要對(duì)經(jīng)過(guò)填充處理的文本進(jìn)行加密,然后得到加密的字符串。代碼為:encrypted_text = des.encrypt(padded_text.encode('utf-8'))

知道了如何加密,還要知道如何解密:

>>> des.decrypt(encrypted_text)
b'Python rocks!   '

幸運(yùn)的是,解密非常容易,我們只需要調(diào)用 des 對(duì)象的 decrypt 方法就可以得到我們?cè)瓉?lái)的 byte 類型字符串了。下一個(gè)任務(wù)是學(xué)習(xí)如何用 RSA 算法加密和解密一個(gè)文件。首先,我們需要?jiǎng)?chuàng)建一些 RSA 密鑰。

創(chuàng)建 RSA 密鑰

如果你希望使用 RSA 算法加密數(shù)據(jù),那么你需要擁有訪問(wèn) RAS 公鑰和私鑰的權(quán)限,否則你需要生成一組自己的密鑰對(duì)。在這個(gè)例子中,我們將生成自己的密鑰對(duì)。創(chuàng)建 RSA 密鑰非常容易,所以我們將在 Python 解釋器中完成。

>>> from Crypto.PublicKey import RSA
>>> code = 'nooneknows'>>> key = RSA.generate(2048)
>>> encrypted_key = key.exportKey(passphrase=code, pkcs=8,
       protection="scryptAndAES128-CBC")
>>> with open('/path_to_private_key/my_private_rsa_key.bin', 'wb') as f:
       f.write(encrypted_key)
>>> with open('/path_to_public_key/my_rsa_public.pem', 'wb') as f:
       f.write(key.publickey().exportKey())

首先我們從 Crypto.PublicKey 包中導(dǎo)入 RSA,然后創(chuàng)建一個(gè)傻傻的密碼。接著我們生成 2048 位的 RSA 密鑰。現(xiàn)在我們到了關(guān)鍵的部分。為了生成私鑰,我們需要調(diào)用 RSA 密鑰實(shí)例的 exportKey 方法,然后傳入密碼,使用的 PKCS 標(biāo)準(zhǔn),以及加密方案這三個(gè)參數(shù)。之后,我們把私鑰寫入磁盤的文件中。

接下來(lái),我們通過(guò) RSA 密鑰實(shí)例的 publickey 方法創(chuàng)建我們的公鑰。我們使用方法鏈調(diào)用 publickey 和 exportKey 方法生成公鑰,同樣將它寫入磁盤上的文件。

加密文件

有了私鑰和公鑰之后,我們就可以加密一些數(shù)據(jù),并寫入文件了。這里有個(gè)比較標(biāo)準(zhǔn)的例子:

from Crypto.PublicKey import RSA
from Crypto.Random import get_random_bytes
from Crypto.Cipher import AES, PKCS1_OAEP

with open('/path/to/encrypted_data.bin', 'wb') as out_file:
   recipient_key = RSA.import_key(
       open('/path_to_public_key/my_rsa_public.pem').read())
   session_key = get_random_bytes(16)

   cipher_rsa = PKCS1_OAEP.new(recipient_key)
   out_file.write(cipher_rsa.encrypt(session_key))

   cipher_aes = AES.new(session_key, AES.MODE_EAX)
   data = b'blah blah blah Python blah blah'   ciphertext, tag = cipher_aes.encrypt_and_digest(data)

   out_file.write(cipher_aes.nonce)
   out_file.write(tag)
   out_file.write(ciphertext)

代碼的前三行導(dǎo)入 PyCryptodome 包。然后我們打開(kāi)一個(gè)文件用于寫入數(shù)據(jù)。接著我們導(dǎo)入公鑰賦給一個(gè)變量,創(chuàng)建一個(gè) 16 字節(jié)的會(huì)話密鑰。在這個(gè)例子中,我們將使用混合加密方法,即 PKCS#1 OAEP ,也就是最優(yōu)非對(duì)稱加密填充。這允許我們向文件中寫入任意長(zhǎng)度的數(shù)據(jù)。接著我們創(chuàng)建 AES 加密,要加密的數(shù)據(jù),然后加密數(shù)據(jù)。我們將得到加密的文本和消息認(rèn)證碼。最后,我們將隨機(jī)數(shù),消息認(rèn)證碼和加密的文本寫入文件。

順便提一下,隨機(jī)數(shù)通常是真隨機(jī)或偽隨機(jī)數(shù),只是用來(lái)進(jìn)行密碼通信的。對(duì)于 AES 加密,其密鑰長(zhǎng)度最少是 16 個(gè)字節(jié)。隨意用一個(gè)你喜歡的編輯器試著打開(kāi)這個(gè)被加密的文件,你應(yīng)該只能看到亂碼。

現(xiàn)在讓我們學(xué)習(xí)如何解密我們的數(shù)據(jù)。

from Crypto.PublicKey import RSA
from Crypto.Cipher import AES, PKCS1_OAEP

code = 'nooneknows'with open('/path/to/encrypted_data.bin', 'rb') as fobj:
   private_key = RSA.import_key(
       open('/path_to_private_key/my_rsa_key.pem').read(),
       passphrase=code)

   enc_session_key, nonce, tag, ciphertext = [ fobj.read(x)
                                               for x in (private_key.size_in_bytes(),
                                               16, 16, -1) ]

   cipher_rsa = PKCS1_OAEP.new(private_key)
   session_key = cipher_rsa.decrypt(enc_session_key)

   cipher_aes = AES.new(session_key, AES.MODE_EAX, nonce)
   data = cipher_aes.decrypt_and_verify(ciphertext, tag)print(data)

如果你認(rèn)真看了上一個(gè)例子,這段代碼應(yīng)該很容易解析。在這里,我們先以二進(jìn)制模式讀取我們的加密文件,然后導(dǎo)入私鑰。注意,當(dāng)你導(dǎo)入私鑰時(shí),需要提供一個(gè)密碼,否則會(huì)出現(xiàn)錯(cuò)誤。然后,我們文件中讀取數(shù)據(jù),首先是加密的會(huì)話密鑰,然后是 16 字節(jié)的隨機(jī)數(shù)和 16 字節(jié)的消息認(rèn)證碼,最后是剩下的加密的數(shù)據(jù)。

接下來(lái)我們需要解密出會(huì)話密鑰,重新創(chuàng)建 AES 密鑰,然后解密出數(shù)據(jù)。

你還可以用 PyCryptodome 庫(kù)做更多的事。不過(guò)我們要接著討論在 Python 中還可以用什么來(lái)滿足我們加密解密的需求。

Cryptography 包

Cryptography 的目標(biāo)是成為“人類易于使用的密碼學(xué)包,就像 requests 是“人類易于使用的 HTTP 庫(kù)”一樣。這個(gè)想法使你能夠創(chuàng)建簡(jiǎn)單安全、易于使用的加密方案。如果有需要的話,你也可以使用一些底層的密碼學(xué)基元,但這也需要你知道更多的細(xì)節(jié),否則創(chuàng)建的東西將是不安全的。

如果你使用的 Python 版本是 3.5, 你可以使用 pip 安裝,如下:

pip install cryptography

你會(huì)看到 cryptography 包還安裝了一些依賴包,如果安裝都順利,我們就可以試著加密一些文本了。讓我們使用 Fernet 對(duì)稱加密算法,它保證了你加密的任何信息在不知道密碼的情況下不能被篡改或讀取。Fernet 還通過(guò) MultiFernet 支持密鑰輪換。下面讓我們看一個(gè)簡(jiǎn)單的例子:

>>> from cryptography.fernet import Fernet
>>> cipher_key = Fernet.generate_key()
>>> cipher_key
b'APM1JDVgT8WDGOWBgQv6EIhvxl4vDYvUnVdg-Vjdt0o='>>> cipher = Fernet(cipher_key)
>>> text = b'My super secret message'>>> encrypted_text = cipher.encrypt(text)
>>> encrypted_text
(b'gAAAAABXOnV86aeUGADA6mTe9xEL92y_m0_TlC9vcqaF6NzHqRKkjEqh5d21PInEP3C9HuiUkS9f'b'6bdHsSlRiCNWbSkPuRd_62zfEv3eaZjJvLAm3omnya8=')
>>> decrypted_text = cipher.decrypt(encrypted_text)
>>> decrypted_text
b'My super secret message'

首先我們需要導(dǎo)入 Fernet,然后生成一個(gè)密鑰。我們輸出密鑰看看它是什么樣兒。如你所見(jiàn),它是一個(gè)隨機(jī)的字節(jié)串。如果你愿意的話,可以試著多運(yùn)行 generate_key 方法幾次,生成的密鑰會(huì)是不同的。然后我們使用這個(gè)密鑰生成 Fernet 密碼實(shí)例。

現(xiàn)在我們有了用來(lái)加密和解密消息的密碼。下一步是創(chuàng)建一個(gè)需要加密的消息,然后使用 encrypt 方法對(duì)它加密。我打印出加密的文本,然后你可以看到你再也讀不懂它了。為了解密出我們的秘密消息,我們只需調(diào)用 decrypt 方法,并傳入加密的文本作為參數(shù)。結(jié)果就是我們得到了消息字節(jié)串形式的純文本。

關(guān)于“Python3常見(jiàn)加密計(jì)數(shù)方法有哪些”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“Python3常見(jiàn)加密計(jì)數(shù)方法有哪些”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI