RSA加密
RSA加密是一種非對稱加密算法(與AES等對稱加密不同),由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)于1977年提出,名字取自三人姓氏首字母。它通過一對密鑰(公鑰和私鑰) 實現加密和解密,是目前應用最廣泛的非對稱加密技術之一。
核心特點:
-
非對稱密鑰體系
- 公鑰:可公開傳播,用于加密數據或驗證簽名。
- 私鑰:必須保密,用于解密公鑰加密的數據,或生成簽名。
核心邏輯:用公鑰加密的數據,只有對應的私鑰能解密;用私鑰加密的數據(簽名),只有對應的公鑰能驗證。
-
安全性基礎
基于大數分解難題:將兩個大質數相乘容易,但要分解其乘積(得到原始質數)在計算上幾乎不可行。密鑰長度越長(如2048位、4096位),破解難度呈指數級增長,目前2048位及以上被認為足夠安全。 -
加密與解密效率
因涉及復雜的大數運算,RSA加密速度遠慢于對稱加密(如AES),因此不適合加密大量數據,通常用于加密對稱加密的密鑰(即“混合加密”),或用于數字簽名。
典型應用場景:
- 密鑰交換:在HTTPS、VPN等通信中,用對方公鑰加密對稱加密的密鑰,確保密鑰安全傳輸(如TLS握手階段)。
- 數字簽名:發送方用私鑰對數據哈希值加密(生成簽名),接收方用公鑰驗證簽名,確認數據未被篡改且來自合法發送方(如軟件簽名、電子合同)。
- 身份認證:通過驗證私鑰持有者的身份(如SSH登錄用公鑰認證)。
示例(生成公鑰和私鑰) :
"""
@File : 非對稱加密RSA.py
@Editor : 百年
"""
'''
非對稱加密,加密和解密的密鑰不是同一個密鑰,而是需要兩把密鑰
一個是公鑰,一個是私鑰,公鑰發送給客戶端,發送端用公鑰對數據進行加密,
再發送給接收端,接收端使用私鑰來對數據進行解密,
由于私鑰只存放在接收端這邊,
所以即使數據被截獲了,也是無法進行解密的
常見的非對稱加密算法:RSA,DSA
rsa是最常見的一種加密方案
公鑰是用來加密的
私鑰是用來解密的
密鑰(私鑰)不能公開
公鑰和私鑰是成對的,是有一定的關聯的
加密和解密用的不是同一個密鑰,私鑰放在服務器上不公開
'''
from Crypto.PublicKey import RSA #這是處理密鑰的
from Crypto import Random
import base64
# 生成密鑰,默認生成的是私鑰
key = RSA.generate(2048)
print(key)
# Private RSA key at 0x1D92A324690 生成了私鑰,后面跟的是內存地址# print(key.export_key())
# print(key.exportKey()) #tips:這倆一樣的
private_key = key.export_key()
# print(private_key)
#直接這樣輸出的是base64字節而且帶有換行符
# 可以decode,將base64字節轉換為b64字符串
print(private_key.decode())# private_key_b = key.export_key(format='DER') #輸出純字節的私鑰
# print(private_key_b)#生成公鑰puiblic_key = key.public_key()
print(puiblic_key)
# Public RSA key at 0x227A7D9ADD0
print(puiblic_key.export_key())
#這樣打印也是有換行符的
print(puiblic_key.export_key().decode())
#還得decode
'''
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuTelupiUOptxRuq0HdXe
wvxw7mfpE45uxPGybbFWCykczUjthcsrnfe33zX6GikGN8O/h1Z2LGvslkupeGYB
mixLnTMTahL45P2o92szSb9xiixa50FrfFCwkkuCTcpHARkMDMawAIH+xt+bKjq9
DJKHXTaTpjrcaqXI38TYwMtGYRFJhOQr39B3P28UNAa03gKbajh4sRSA0WF6I8My
wdZZmmccW6q+rgZOs92UCwUTd4ZmzweU2FQeailhLrQWTbO9g/w9HLtFFgUWx6Vf
2WO8S5zEBPFHqbvh1Kjtvn9HK+w12uM7NDBdLgMg0PgU9AfGNzDj2pOU+drdPzbM
uwIDAQAB
-----END PUBLIC KEY-----
'''#這正使用過程中,服務器一開始就會直接寫入到文件當中去#important:注意寫入的是二進制
#寫出私鑰
with open('private.pem','wb') as f:f.write(key.export_key())#寫出公鑰
with open('public.pem','wb') as f1:f1.write(key.public_key().export_key())
示例(用公鑰加密)
"""
@File : 使用自己的rsa密鑰加密.py
@Editor : 百年
"""'''
加密流程是客戶端最有用的地方
解密流程是發生在服務器端的
'''from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64#step1 :加載密鑰,需要的是公鑰,公鑰是用來加密的
#這里用我們上一個文件中生成的公鑰
#export是導出,那么我們就可以用import進行導入
# tips: 可以讀字節import_key(b'b64密鑰',),也可以讀字符串
pub_k = RSA.import_key(open('public.pem','rb').read())
#step2 :創建加密器的流程和之前的AES,DES很像
rsa = PKCS1_v1_5.new(key=pub_k)#step3 :進入加密邏輯
s = 'hello,我叫hero,你是??'
enc_s = rsa.encrypt(s.encode('utf-8'))print(enc_s)
#打印出來是混亂字節
#step4 :為了傳輸,需要利用base64進行編碼enc_s = base64.b64encode(enc_s)
print(enc_s.decode())
#important:rsa加密后的東西,如果不是純數學算法,每次都是隨機的
'''
FfXEjq4Uy3zikwtTMVw+q9HqmhSyoMkUjI/VaA/JrKkp/gdLgqlKCg+0s+dttvtlDKdLE2L+WD0hseEFXhSo7hVo3aQyevtzOAokZY0ZM5Anq+hQSt4EyBxnco7ABe3iCYTJuUEqWIw0bnUB+Fq9tRshDwKsBwNCKQ2TBjM8QSUmcGa9Zvy/pdY4sPM9FGKe3vYcsejnmAbnp3llIcquSjO+clUrCI9/4HDB2bB5yxw4trxVtDukxtMWYZgyYDBvW1waL6i70h9F7/blTNSJiE5GSfktENHXY1tQsQuSpQx9N7N8sLLpIDMmmFfqv122GPncbA1zz7eoGU/Vncopkg=='''
示例(用私鑰解密):
"""
@File : 使用私鑰進行解密.py
@Editor : 百年
"""
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64#密文
miwen = 'FfXEjq4Uy3zikwtTMVw+q9HqmhSyoMkUjI/VaA/JrKkp/gdLgqlKCg+0s+dttvtlDKdLE2L+WD0hseEFXhSo7hVo3aQyevtzOAokZY0ZM5Anq+hQSt4EyBxnco7ABe3iCYTJuUEqWIw0bnUB+Fq9tRshDwKsBwNCKQ2TBjM8QSUmcGa9Zvy/pdY4sPM9FGKe3vYcsejnmAbnp3llIcquSjO+clUrCI9/4HDB2bB5yxw4trxVtDukxtMWYZgyYDBvW1waL6i70h9F7/blTNSJiE5GSfktENHXY1tQsQuSpQx9N7N8sLLpIDMmmFfqv122GPncbA1zz7eoGU/Vncopkg=='#step1:因為是base64字符串,先將其轉換為字節
b_s = base64.b64decode(miwen)
print(b_s)#構建解密器,對其進行解密
#step2:讀取自己的私鑰,但其實我們一般不考慮解密的事情,這是交給服務器端的pri_k = RSA.import_key(open('private.pem','rb').read())
# pri_k = RSA.import_key(k) 或者直接寫的話就導入字節格式的密鑰
rsa = PKCS1_v1_5.new(key=pri_k)
s = rsa.decrypt(b_s,sentinel='None') #important:注意這里要求要有一個位置參數表示報錯后該參數執行,是規定,雖然用不到但是也要強制指定
print(s)
# b'hello,\xe6\x88\x91\xe5\x8f\xabhero,\xe4\xbd\xa0\xe6\x98\xaf??'#step3:還原
print(s.decode()) #tips:因為默認是utf-8,這里就不指定了
# hello,我叫hero,你是??