Hua*_*eng 3 python encryption cryptography rsa pycrypto
我现在知道RSA公钥/私钥只能一次加密非常短的输入,但任何人都可以提供一种方法来加密任何类型的文件(.txt,.phf,.exe等)只有公钥/私钥?我不想要额外的AES密钥.
这是我的代码,在使用公钥和私钥对进行加密和解密后,我没有收到原始内容.我不关心加密或解密的安全性,我只想让简单的加密解密工作在它可能需要的任何输入上,无论它有多长或多大.
from Crypto.PublicKey import RSA
from Crypto import Random
random_generator = Random.new().read
key = RSA.generate(1024, random_generator)
public_key = key.publickey()
f = open('C:\Users\Administrator\Desktop\jack.txt','r').read()
print 'original content: '+ f
enc_data = public_key.encrypt(f, 32)
print 'encrypted data: '
print enc_data
dec_data = key.decrypt(enc_data)
print 'decrypted data: '+ dec_data
Run Code Online (Sandbox Code Playgroud)
这是输出:
original content: Python Cryptography Toolkit
A collection of cryptographic modules implementing various algorithms and protocols.
Subpackages:
Crypto.Cipher
Secret-key (AES, DES, ARC4) and public-key encryption (RSA PKCS#1) algorithms
Crypto.Hash
Hashing algorithms (MD5, SHA, HMAC)
Crypto.Protocol
Cryptographic protocols (Chaffing, all-or-nothing transform, key derivation functions). This package does not contain any network protocols.
Crypto.PublicKey
Public-key encryption and signature algorithms (RSA, DSA)
Crypto.Signature
Public-key signature algorithms (RSA PKCS#1)
Crypto.Util
Various useful modules and functions (long-to-string conversion, random number generation, number theoretic functions)
encrypted data:
('\x08\xe3\x9d\x03\x1e\xe9(\xe2\xc7\xc6e\x0b5\x02\xc0\xd8G\x1f\xf5\xb8\x9cMC\x93Z\x982\xa5\x97\xec\xab4\x18\xc2\xc8\xd9\xd3\x99aX\xd96b\x19\x96\xdc\x1d|F\xe0\xa9\xa9\xea\x03\x10>0g\x83\xdb\xeb\xdb\x13\x91\xc6\xd8\xf6\x95\xedE@A\x0bc\xae\xbe\xbe\xf0\xde\xcc\xcexk\x10\xb3\x86\xd3\xdd\xd0\xca@T2\x9a\x8a6ut\xb1\xaf\x07\x1f\xa2M\r\xf0D\xa2`h\xc3\x89\x18\x0e\xd4\xca\xee\xf5\xfc\x01\xed\x95}X\x1f\x13 1',)
decrypted data: ???J?rPX ?????ju?a,?xm?'?]?????y;?)??t??,?D4^?ba?8????9q
+?i??l ?q]Kd?Y???u??S?B?????^?A3
.7??j??m?
?6?dl? qU
Run Code Online (Sandbox Code Playgroud)
RSA 速度很慢,因此它不太适合加密/解密大块数据。它通常用于加密/解密更快的对称密码的密钥,例如 AES。
乍一看,你的加密数据看起来有点小,与你的输入数据相对应,但我对 Crypto 不太熟悉(我前几天才自己安装了它),所以我无法解释它对你做了什么数据。
但这段代码对我有用:
#!/usr/bin/env python
from Crypto.PublicKey import RSA
from Crypto import Random
src_data = 'To be, or not to be - that is the question.'
print `src_data`
random_generator = Random.new().read
key = RSA.generate(1024, random_generator)
print 'Key generated'
pub_key = key.publickey()
print 'Public key', pub_key
enc_data = pub_key.encrypt(src_data, 32)[0]
print `enc_data`
dec_data = key.decrypt(enc_data)
print `dec_data`
Run Code Online (Sandbox Code Playgroud)
典型输出
#!/usr/bin/env python
from Crypto.PublicKey import RSA
from Crypto import Random
src_data = 'To be, or not to be - that is the question.'
print `src_data`
random_generator = Random.new().read
key = RSA.generate(1024, random_generator)
print 'Key generated'
pub_key = key.publickey()
print 'Public key', pub_key
enc_data = pub_key.encrypt(src_data, 32)[0]
print `enc_data`
dec_data = key.decrypt(enc_data)
print `dec_data`
Run Code Online (Sandbox Code Playgroud)
FWIW,这是上面的一个稍微修改的版本,它可以在 Python 2 和 Python 3 上运行,尽管这两个版本的输出会有细微的差别。
在 Python 3 中,我们不能将字符串传递给加密或解密函数,我们必须传递字节。此外,Python 3 不支持repr在 Python 2中获取对象的反引号语法。
此代码调用 string.encode()和 bytes.decode()方法来执行转换。我们可以指定一个编码编解码器,例如
src_data.encode('utf-8')
Run Code Online (Sandbox Code Playgroud)
但这不是必需的,因为 UTF-8 是默认编解码器。
from __future__ import print_function
from Crypto.PublicKey import RSA
from Crypto import Random
src_data = 'To be, or not to be - that is the question.'
print(repr(src_data))
random_generator = Random.new().read
key = RSA.generate(1024, random_generator)
pub_key = key.publickey()
print('Key generated')
print(key.exportKey().decode())
print(pub_key.exportKey().decode())
enc_data = pub_key.encrypt(src_data.encode(), 32)[0]
print('Encoded\n', repr(enc_data))
dec_data = key.decrypt(enc_data).decode()
print('Decoded\n', repr(dec_data))
Run Code Online (Sandbox Code Playgroud)
典型的 Python 3 输出
'To be, or not to be - that is the question.'
Key generated
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDL/TzI4yHmlcC8qP3xWNieujmXR7CnEaZJrDH1Hyr/tGNa0aEE
jDIz+RlMntBbhOuiQMkMtCSB5X28h7HetiD4XkWTXmlIiKZQLZ074cO5mxF+HhF7
WIG30VONpX+Q4t/beqtaqbzyeIWvDdcCjUwOSQLrUKU5PX9LFzX+FnN1UwIDAQAB
AoGASRVZib+Wjb5pZy5EjQt/0J53s7ODnte78/k1jNS12xcN4aPpRG/WLLi6T7E2
hROCOIdtgJep3MAT5E/ZciledflaDwwmLo6+NsrhMppsNhpIHsvxWxmwxnH+bC2H
lpyeUmxku4xzqwYW4kuF3iaR45K2eUpXQyWTE9+pgvepgoECQQDT6Waiavstvs4W
btW2P4J+7O//NmTcvnyLTnhFTXklxTxnSun54HYOce8+TttsXWESTbzf91saN5SW
0vPyKK25AkEA9m3gbwFppiA65464jnDCP1AnrR15n3tbsLpaadYdRm07b+4BB0R2
M820cgber14JiGndOfv1uPl1Ooy0IH4hawJBAJKRC/uqIrAxGDlLz2SN6KQBHL1X
0csbtOhlDaphOzl0gaKvncTGCuFSzDY8NGdu7oTKX6hIXSp05sCqhy8mE4ECQE49
xKx5/llIkmtC3UYcdxAzGuXUHfGM8SfDg0FnQhRCSkTXhGwSSJVaEpjBpaJ4cP5m
3l6yqOn6CkZ0thw679ECQCWNC5hVEtsAb0TcjGdTpw+xTFusiZciNyHTQ64Zq2cc
ehQrxTRDIEBA4wIgUwrTwdVXk10OtpcVZvLIVjqdC84=
-----END RSA PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDL/TzI4yHmlcC8qP3xWNieujmX
R7CnEaZJrDH1Hyr/tGNa0aEEjDIz+RlMntBbhOuiQMkMtCSB5X28h7HetiD4XkWT
XmlIiKZQLZ074cO5mxF+HhF7WIG30VONpX+Q4t/beqtaqbzyeIWvDdcCjUwOSQLr
UKU5PX9LFzX+FnN1UwIDAQAB
-----END PUBLIC KEY-----
Encoded
b'\x843\x9aJ\xe6\x91p\xd2\x9c\xd0r{37\xa2G\x13Q\xc7~\xbd5\xce\x9f\xd4\x16\xda\x11\x02.\xb7\xf1\xf3Q\x8c|\xb0R2B\x1b)e\xeaD\x8e\x11\x1b\xb0J:\xbal\xac\x86\xdcb}_\x16IX\xccd\x0c\xb5E?Im<\x04ORT\xc9\xc6K|;\xf3\xbcK\xfd\x89\x96ZF(\x0b\x82v\x19`\xc3\xa1N\x934*\x9c\xfcT\xf4i\x02g\x1fl\xec\xc1\x19z\x9f7\xa6}\xe2\xe3}\xaa|\x1e\x13z\xd9$\xea'
Decoded
'To be, or not to be - that is the question.'
Run Code Online (Sandbox Code Playgroud)
我们真的不需要在这里使用 UTF-8 编码。由于src_data是纯 7 位 ASCII 字符串,并且我们已将其作为文字嵌入到脚本中,因此我们可以将其作为文字字节字符串提供:
src_data = b'To be, or not to be - that is the question.'
Run Code Online (Sandbox Code Playgroud)
RSA只能加密有限的输入.多少取决于RSA的密钥大小(在您的情况下为1024位)和使用的填充.比这更大的东西(没有使用填充时为128字节,如果使用填充则更少)并且您无法再恢复它.
解决方案是使用混合加密.
AES加密:
from Crypto.Cipher import AES
from Crypto import Random
aeskey = Random.new().read(32)
iv = Random.new().read(AES.block_size)
cipher = AES.new(aeskey, AES.MODE_CFB, iv)
msg = iv + cipher.encrypt(b'Attack at dawn')
Run Code Online (Sandbox Code Playgroud)
RSA加密(使用像OAEP这样的正确填充,因为教科书RSA被严重破坏):
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
message = aeskey
random_generator = Random.new().read
rsakey = RSA.generate(1024, random_generator)
cipher = PKCS1_OAEP.new(rsakey.publickey())
ciphertext = cipher.encrypt(message)
Run Code Online (Sandbox Code Playgroud)
而且只发送msg和ciphertext.解密类似,但后退,因为您首先必须从RSA密文恢复AES密钥.在使用AES解密时,不要忘记切掉IV.