python中的RSA加密與解密實例解析
這篇文章主要介紹了python RSA加密與解密實現(xiàn)詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
什么是RSA:
RSA公開密鑰密碼體制。所謂的公開密鑰密碼體制就是使用不同的加密密鑰與解密密鑰,是一種“由已知加密密鑰推導出解密密鑰在計算上是不可行的”密碼體制。
在公開密鑰密碼體制中,加密密鑰(即公開密鑰)PK是公開信息,而解密密鑰(即秘密密鑰)SK是需要保密的。加密算法E和解密算法D也都是公開的。雖然解密密鑰SK是由公開密鑰PK決定的,但卻不能根據(jù)PK計算出SK。
正是基于這種理論,1978年出現(xiàn)了著名的RSA算法,它通常是先生成一對RSA 密鑰,其中之一是保密密鑰,由用戶保存;另一個為公開密鑰,可對外公開,甚至可在網(wǎng)絡服務器中注冊。為提高保密強度,RSA密鑰至少為500位長,一般推薦使用1024位。這就使加密的計算量很大。為減少計算量,在傳送信息時,常采用傳統(tǒng)加密方法與公開密鑰加密方法相結(jié)合的方式,即信息采用改進的DES或IDEA密鑰加密,然后使用RSA密鑰加密對話密鑰和信息摘要。對方收到信息后,用不同的密鑰解密并可核對信息摘要。
RSA算法是第一個能同時用于加密和數(shù)字簽名的算法,也易于理解和操作。RSA是被研究得最廣泛的公鑰算法,從提出到現(xiàn)今的三十多年里,經(jīng)歷了各種攻擊的考驗,逐漸為人們接受,截止2017年被普遍認為是最優(yōu)秀的公鑰方案之一。
SET(Secure Electronic Transaction)協(xié)議中要求CA采用2048bits長的密鑰,其他實體使用1024比特的密鑰。RSA密鑰長度隨著保密級別提高,增加很快。下表列出了對同一安全級別所對應的密鑰長度。
python實現(xiàn)對RSA的加密和解密
Python密碼庫--Pycrypto
Python良好的生態(tài),對于加密解密技術(shù)都有成熟的第三方庫。大名鼎鼎的M2Crypto和Pycrypto,前者非常容易使用,可是安裝卻非常頭疼,不同的系統(tǒng)依賴軟件的版本還有影響。后者則比較方面,直接使用pip安裝即可。
密碼技術(shù)
為了進行加密以及通信,人們發(fā)明了很多公開的算法。對稱與非對稱算法等。常見的加密方式有RSA, AES等算法。對于選擇加密算法,一個常識就是使用公開的算法。一方面是這些算法經(jīng)過實踐檢驗,另一方面對于破譯難度和破譯條件破譯時間都有預估。對于任何加密算法,都是能破解的,不同在于時間上的投入。
Python密碼庫--Pycrypto
Python良好的生態(tài),對于加密解密技術(shù)都有成熟的第三方庫。大名鼎鼎的M2Crypto和Pycrypto,前者非常容易使用,可是安裝卻非常頭疼,不同的系統(tǒng)依賴軟件的版本還有影響。后者則比較方面,直接使用pip安裝即可。
安裝
pip install pycrypto
RSA 密碼算法與簽名
RSA是一種公鑰密碼算法,RSA的密文是對代碼明文的數(shù)字的 E 次方求mod N 的結(jié)果。也就是將明文和自己做E次乘法,然后再將其結(jié)果除以 N 求余數(shù),余數(shù)就是密文。RSA是一個簡潔的加密算法。E 和 N 的組合就是公鑰(public key)。
對于RSA的解密,即密文的數(shù)字的 D 次方求mod N 即可,即密文和自己做 D 次乘法,再對結(jié)果除以 N 求余數(shù)即可得到明文。D 和 N 的組合就是私鑰(private key)。
算法的加密和解密還是很簡單的,可是公鑰和私鑰的生成算法卻不是隨意的。本文在于使用,對生成秘鑰對的算法就暫時忽略。使用 Pycrypto生成秘鑰對很簡單,我們分別為 Server和Client各生成一對屬于自己的秘鑰對。
from Crypto import Random from Crypto.Hash import SHA from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5 from Crypto.Signature import PKCS1_v1_5 as Signature_pkcs1_v1_5 from Crypto.PublicKey import RSA # 偽隨機數(shù)生成器 random_generator = Random.new().read # rsa算法生成實例 rsa = RSA.generate(1024, random_generator) # Server的秘鑰對的生成 private_pem = rsa.exportKey() with open("server-private.pem", "w") as f: f.write(private_pem) public_pem = rsa.publickey().exportKey() with open("server-public.pem", "w") as f: f.write(public_pem) # Client的秘鑰對的生成 private_pem = rsa.exportKey() with open("client-private.pem", "w") as f: f.write(private_pem) public_pem = rsa.publickey().exportKey() with open("client-public.pem", "w") as f: f.write(public_pem)
所生成的私鑰和公鑰大概是這樣的:
-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQC26X6A0WCWiVxdxq3jtm42yDdGbf+99v2zyi0UMVGZfowlnkcW eMvpz8NBm2UVlrjZpnFr8wFkdHyjFFkq/ilclH3AN4+Xw8Ap7CGJ2jVMyS5h9RRB Uyf3F4D5Og8789Ywh9HXYyvD/6J62EtbbkhGPxg3aa8n2kfKZ9N6Q7DqrwIDAQAB AoGBAJn5qu1D1FxE24Vxl7ZGPzdMigN227+NaPptak9CSR++gLm2KL+JBpcXt5XF +20WCRvnWjl2QijPSpB5s6pWdHezEa1cl6WrqB1jDJd1U99WNCL5+nfEVD9IF+uE ig0pnj+wAT5fu78Z0UjxD9307f9S7BLC8ou3dWVkIqob6W95AkEAuPGTNlTkquu/ wBJTb4/+/2ZCf7Ci9qvsN3+RcrzFkKa3uTtBOa6Xk2R61zBkucUgY6cQHPbxhFLN TVmXdbwxTQJBAP0wGenVOq4dCPdz3NhyghkKT6SL2w/SgbrROiJ1mG9MoBq58/0g k85I91R7nuvOYTKTUkhWdPYITpDarmPJzesCQGRBmOMgHCHH0NfHV3Gn5rz+61eb IoyD4Hapceh4CsWCiyAfzhj9229sTecvdbr68Lb0zphVCdIIrQCca63IShUCQGYI e3jzmHlQdCudArQruWgz8pKiVf7TW7qY1O/MKkk4PRFoPP6WoVoxp5LhWtM20Y7b Nf628N2xzU+tAThvvE8CQQCI1C7GO3I5EMfqPbTSq2oZq8thvGlyFyI7SNNuvAHj hj2+0217B9CcTZqloYln01CNDVuaoUgEvFSw1OdRB1tC -----END RSA PRIVATE KEY----- -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC26X6A0WCWiVxdxq3jtm42yDdG bf+99v2zyi0UMVGZfowlnkcWeMvpz8NBm2UVlrjZpnFr8wFkdHyjFFkq/ilclH3A N4+Xw8Ap7CGJ2jVMyS5h9RRBUyf3F4D5Og8789Ywh9HXYyvD/6J62EtbbkhGPxg3 aa8n2kfKZ9N6Q7DqrwIDAQAB -----END PUBLIC KEY-----
加密與解密
通常通信的時候,發(fā)送者使用接受者的公鑰加密,接受者使用接受者私鑰解密。
簡而言之,Server給Client通信,需要加密內(nèi)容,那么Client會生成一個秘鑰對,Client的公鑰client-public.pem和私鑰client-private.pem 。Client把公鑰公開給發(fā)送者,任何人都可以用來加密,然后Server使用client-public.pem進行加密,然后把內(nèi)容發(fā)給Client,Client再使用私鑰client-private.pem進行解密。
1.加密(encrypt)
# Server使用Client的公鑰對內(nèi)容進行rsa 加密 message = "hello client, this is a message" with open("client-public.pem") as f: key = f.read() rsakey = RSA.importKey(key) cipher = Cipher_pkcs1_v1_5.new(rsakey) cipher_text = base64.b64encode(cipher.encrypt(message.encode('utf-8'))) print(cipher_text.decode('utf-8')) #加密結(jié)果: HYQPGB+axWCbPp7PPGNTJEAhVPW0TX5ftvUN2v40ChBLB1pS+PVM3YGT5vfcsvmPZhW8NKVSBp8FwjLUnMn6yXP1O36NaunUzyHwI+cpjlkTwZs3DfCY/32EzeuKuJABin1FHBYUMTOKtHy+eEDOuaJTnZTC7ZBkdha+J88HXSc=
cipher_text 即 Master加密后將要發(fā)送給Client的密文。
2.解密(decrypt)
# Client使用自己的私鑰對內(nèi)容進行rsa 解密 with open("client-private.pem") as f: key = f.read() rsakey = RSA.importKey(key) cipher = Cipher_pkcs1_v1_5.new(rsakey) text = cipher.decrypt(base64.b64decode(encrypt_text), random_generator) print(text.decode('utf-8')) #解密結(jié)果: hello client, this is a message
這樣Client就能看到Server所發(fā)的內(nèi)容了,當然,如果Client想要給Server發(fā)消息,就需要Server先把其的公鑰給Client,后者再使用公鑰加密,然后發(fā)送給Server,最后Server使用自己的私鑰解密。
簽名與驗簽
當然,對于竊聽者,有時候也可以對偽造Server給Client發(fā)送內(nèi)容。為此出現(xiàn)了數(shù)字簽名。也就是Server給Client發(fā)送消息的時候,先對消息進行簽名,表明自己的身份,并且這個簽名無法偽造。具體過程即Server使用自己的私鑰對內(nèi)容簽名,然后Client使用Server的公鑰進行驗簽。
簽名
# Server使用自己的私鑰對內(nèi)容進行簽名 with open("server-private.pem") as f: key = f.read() rsakey = RSA.importKey(key) signer = Signature_pkcs1_v1_5.new(rsakey) digest = SHA.new() digest.update(message) sign = signer.sign(digest) signature = base64.b64encode(sign) print signature #簽名結(jié)果: jVUcAYfgF5Pwlpgrct3IlCX7KezWqNI5tD5OIFTrfCOQgfyCrOkN+/gRLsMiSDOHhFPj2LnfY4Cr5u4eG2IiH8+uSF5z4gUX48AqCQlqiOTLk2EGvyp+w+iYo2Bso1MUi424Ebkx7SnuJwLiPqNzIBLfEZLA3ov69aDArh6hQiw=
驗簽
#Client使用Server的公鑰對內(nèi)容進行驗簽 with open("server-public.pem") as f: key = f.read() rsakey = RSA.importKey(key) verifier = Signature_pkcs1_v1_5.new(rsakey) digest = SHA.new() # Assumes the data is base64 encoded to begin with digest.update(message) is_verify = signer.verify(digest, base64.b64decode(signature)) print is_verify #驗簽結(jié)果: True
總結(jié)
Pycrypto提供了比較完善的加密算法。RSA廣泛用于加密與解密,還有數(shù)字簽名通信領(lǐng)域。使用Publick/Private秘鑰算法中,加密主要用對方的公鑰,解密用自己的私鑰。簽名用自己的私鑰,驗簽用對方的公鑰。
- 加密解密:公鑰加密,私鑰解密
- 簽名驗簽:私鑰簽名,公鑰驗簽
無論是加密解密還是簽名驗簽都使用同一對秘鑰對。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
python實現(xiàn)畫出e指數(shù)函數(shù)的圖像
今天小編就為大家分享一篇python實現(xiàn)畫出e指數(shù)函數(shù)的圖像,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11淺談python對象數(shù)據(jù)的讀寫權(quán)限
下面小編就為大家?guī)硪黄獪\談python對象數(shù)據(jù)的讀寫權(quán)限。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09Python 抓取動態(tài)網(wǎng)頁內(nèi)容方案詳解
這篇文章主要介紹了Python 抓取動態(tài)網(wǎng)頁內(nèi)容方案詳解,首先通過Chrome的工具來進行分析,然后再使用python進行處理,最終得到我們需要的內(nèi)容,非常的方便,這里也算是給大家提供一個思路2014-12-12Python?encode()方法和decode()方法詳解
encode() 方法為字符串類型(str)提供的方法,用于將 str 類型轉(zhuǎn)換成 bytes 類型,這個過程也稱為“編碼”,這篇文章主要介紹了Python?encode()方法和decode()方法,需要的朋友可以參考下2022-12-12