背景:工作需要,部分?jǐn)?shù)據(jù)進(jìn)行了加密傳輸,對(duì)方使用了RSA對(duì)密碼進(jìn)行了加密,需要獲取到解密的數(shù)據(jù)。
目標(biāo):在已知公鑰,私鑰的情況下,使用python對(duì)其進(jìn)行解密。

一、遇到的問(wèn)題
收到加密的文件與加密密鑰,如下。需要通過(guò)密鑰對(duì)信息進(jìn)行解密。
已知是RSA進(jìn)行的加密數(shù)據(jù)。
json = {
'PUBLIC_KEY' :'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz4C8rDjl6NAAvdUxLl7p8eA+xxc4Sa20puq2gFPk+8B5W30o+8xAaktLoji9wEsf7WTEllxZcIXw7d4K9b1M34ZDQT1iR4ZreB3GkxEXDeQIV3f/W7C3NL1bF5ePn7DRGZYKTEry8pp/lK/1ESP9Z+giaN29xm+jsmvNAOJlLjndn8nYcmA1sdDzuX8JSlZOiijAwyKUkwrBd+FqlhbAfF9ebcEgQcRISZsBMpcsZ66HQ0nvEnhmLzkfXxLUu2w7ccwLc/W7a4V1SNFEMZifRyiI7IhYYpRFw7egQN2RgzVWW/O6HKzk2Mxaz/6Y+HEehuDfRDn5MjMCkhnfbpRKKwIDAQAB',
'PRIVATE_KEY' : 'MIIEowIBAAKCAQEAz4C8rDjl6NAAvdUxLl7p8eA+xxc4Sa20puq2gFPk+8B5W30o+8xAaktLoji9wEsf7WTEllxZcIXw7d4K9b1M34ZDQT1iR4ZreB3GkxEXDeQIV3f/W7C3NL1bF5ePn7DRGZYKTEry8pp/lK/1ESP9Z+giaN29xm+jsmvNAOJlLjndn8nYcmA1sdDzuX8JSlZOiijAwyKUkwrBd+FqlhbAfF9ebcEgQcRISZsBMpcsZ66HQ0nvEnhmLzkfXxLUu2w7ccwLc/W7a4V1SNFEMZifRyiI7IhYYpRFw7egQN2RgzVWW/O6HKzk2Mxaz/6Y+HEehuDfRDn5MjMCkhnfbpRKKwIDAQABAoIBAD7xpkn32IYO0qrDCPAwCnc8ts5d1M1EzA/2EvZKfKOBd06xYMVA6ClWPdMvsx+pqj2w25Fg4iCoALWnLVvt2GvVpoEbxbw8ok0Fez8RaBTmn0EpPWTq7igpaIB3kTG3yTYhtW3/LkM5aooH9icE69GhMQ7udKrFIrr0yHMEOf0TNKBUNlwwHWJrpUuodXxIbERonkNdri1AnsWsnh4ePkKFlgaIdOZ24W4kHjfQAQkz3bPTjRzU5Q0LpkCpuYxk+TeOvR5tNPHXtzTWYek7JbCbnIKr1SiJx+ncwWM7QEnuvbzCU2VeTwb6Rq94WIg3RpfqSKJPr5w5e/df4jmi58ECgYEA74ty4UiChdp27/xvy2sJMilgkcL5Z0A+McPrjM82CqfPvr1+ZMBkTwuQGxFWlNtdE7DLpneVCWmzAexUJ02dFndSJMqsN81335VYfLc94qk5HXwmc9UBK7+qL2Ugyz76KoRGogqkKYw0ZR2kdpcNoXjQfeVgqrumt+jnZChpAl8CgYEA3cHPuDbdqqhcslz4+Zz8B0zWKN8Kj5CgG9ReEmJGpE6w5D7bds5iPcmp5xwFctuumAtroA/+bpGX/2oXc1nXucf/dI3AWoaBQrZ9iL6xfe7+ZPiRYuZjz3ygZ+Vcgp6xixbTT86jaIHwsD1wYtzOiiYOUBt4jDk89xookjpBg7UCgYEAtCriQOdUpHBoPKBVRV5AEGZmp7tJ8oqzPKLrK4E+WE1XR1MnGYhK6dj8jh9AS72iCAlVYuNWSToi1TN3KAiMOjWMpvd5CI+VtaiSYVtBRJWay75w/XYb51fFHNinDbdUWV4b8gym5Ej7r4HYDQoXyncf+VDooAF7p5+ZSg/Ky2kCgYAlVsv+Dab3ZE/vbH4zsX4yUHrC+QNTNxvuc6y/VbLlWaapV/gmIgwisUEde/di5qCYU1v04JyLy5IXXKrELn2Hd6iI3JFl7L35GLc8fjdup/5HzB7W00o9FpP/ynvwNn5YmChOiNG0+CQp2L6CtwFD+7JvRKDgo4ajaNEqBgsf/QKBgE6kbfW6FSpFdOs+2qpIXTEWnTqUC3WD1h1qB8G8J3Tn/o/bSm8C5lHmjmg9vRJtHisaoLyc2ikH7UZwPGU32340s22igkDZml730CKrYtnnBZAG+tIiERtI4Zj432X7qzBYgTgwO7wRAvds+WDCwwV5FMGNCzbPEXos8HmS0812'
}
message = 'qFH2uuSYzDrxZ+MiQS/s/zRr5oOm/jfkCOYmJs+X/5elStsWkoVDxp6ONQFddLRi0Y797BMuE+yDwgPz73SLKnJcB3H9i/hxRO3VYZ1x6UdT1i7jypDm7dbfyJ0HNv8aL/1luOgSIRgLXoHg42SnY8xdpGsog77tKDl5NYlTfxCelMifMhLbhBCVtUPzKy75vhBXndUxzIThZynUeWa8CuyJSUmTmAnr/Qrq7BGo859NX8YXpjG9PdxoV00I67mtvuZXTkE295XnRbBAFRuuNlSTPjj/bXQp1cggy25f831NW0DdWy6pcH34HCTpP8eoJ2UaGsOQtEFYIHS2WfirFA=='
二、RSA算法簡(jiǎn)介
RSA 非對(duì)稱(chēng)加密算法
RSA是一種公鑰密碼算法,RSA的密文是對(duì)代碼明文的數(shù)字的 E 次方求mod N 的結(jié)果。也就是將明文和自己做E次乘法,然后再將其結(jié)果除以 N 求余數(shù),余數(shù)就是密文。RSA是一個(gè)簡(jiǎn)潔的加密算法。E 和 N 的組合就是公鑰(public key)。
對(duì)于RSA的解密,即密文的數(shù)字的 D 次方求mod N 即可,即密文和自己做 D 次乘法,再對(duì)結(jié)果除以 N 求余數(shù)即可得到明文。D 和 N 的組合就是私鑰(private key)
總結(jié)
1、乙方生成兩把密鑰(公鑰和私鑰)。公鑰是公開(kāi)的,任何人都可以獲得,私鑰則是保密的。
2、甲方獲取乙方的公鑰,然后用它對(duì)信息加密。
3、乙方得到加密后的信息,用私鑰解密
原理詳解
三、準(zhǔn)備工作
網(wǎng)上查詢(xún)資料后,了解到
windows上使用的是pycryptodome包。------ pip install pycryptodome
Linux上使用pycrypto包。------ pip install pycryptodome
pycryptodome的更新選擇
但是自己測(cè)試后,發(fā)現(xiàn)python3.7上直接調(diào)包Crypto也可以直接使用。
from Crypto import Random
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.PublicKey import RSA
四、開(kāi)始解密
首先對(duì)密鑰進(jìn)行提取。
Crypto包中對(duì)密鑰有格式要求,如下所示
python實(shí)現(xiàn)RSA解密
#-----------------------------------生成的公私鑰文件類(lèi)似于如下形式-------------------------------------------------------
# 私鑰
-----BEGIN RSA PRIVATE KEY-----
MIICX......./fx7KHM=
-----END RSA PRIVATE KEY-----
#公鑰
-----BEGIN PUBLIC KEY-----
MIGDA.......AQAB
-----END PUBLIC KEY-----
那么讀取文件
PUBLIC_KEY = r'-----BEGIN PUBLIC KEY-----\n{}\n-----END PUBLIC KEY-----\n'.format(json['PUBLIC KEY'])
RIVATE_KEY = r'-----BEGIN RSA PRIVATE KEY-----\n{}\n-----END RSA PRIVATE KEY-----\n'.format(json['PRIVATE KEY'])
其中字符串轉(zhuǎn)字節(jié)的形式
rsa_public_key = PUBLIC_KEY .encode('utf8')
rsa_private_key = RIVATE_KEY.encode('utf8')
同理加密信息也做同樣的操作
cipher_text = message.encode('utf8')
解密處理
# -*- coding: utf-8 -*-
import base64
from Crypto import Random
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.PublicKey import RSA
rsakey = RSA.importKey(rsa_private_key)
cipher = Cipher_pkcs1_v1_5.new(rsakey)
random_generator = Random.new().read
text = cipher.decrypt(base64.b64decode(cipher_text), None)
print(text.decode('utf8'))
# 加大力度!??!
解密成功~~~
五、加密&解密-代碼
利用random函數(shù)生成新的密鑰。
# -*- coding: utf-8 -*-
import base64
from Crypto import Random
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.PublicKey import RSA
message = b"this is test"
random_generator = Random.new().read
rsa = RSA.generate(1024, random_generator)
rsa_private_key = rsa.exportKey()
rsa_public_key = rsa.publickey().exportKey()
rsakey = RSA.importKey(rsa_public_key)
cipher = Cipher_pkcs1_v1_5.new(rsakey)
cipher_text = base64.b64encode(cipher.encrypt(message))
print(cipher_text)
rsakey = RSA.importKey(rsa_private_key)
cipher = Cipher_pkcs1_v1_5.new(rsakey)
random_generator = Random.new().read
text = cipher.decrypt(base64.b64decode(cipher_text), None)
print(text.decode('utf8'))
六、注意的點(diǎn)
1、密鑰要處理成python的格式。
2、密鑰&加密信息要處理成字節(jié)的形式。
七、其他備注
加密解密:公鑰加密,私鑰解密
簽名驗(yàn)簽:私鑰簽名,公鑰驗(yàn)簽
RSA的簽名/驗(yàn)證