2015-02-10 138 views
3

我現在知道RSA公鑰/私鑰只能立即加密非常短的輸入,但任何人都可以提供加密任何類型文件(.txt,。 phf,.exe等)只有公鑰/私鑰?我不想擁有額外的AES密鑰。Python加密,RSA公鑰/私鑰,大文件

這裏是我的代碼,我沒有得到我的加密和解密與公鑰&私鑰後解密的原始內容。我不在乎我的加密或解密有多安全,我只是希望簡單的加密解密可以處理任何可能需要的輸入,無論它有多長或多長。

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 

這裏是輸出:

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\[email protected]\x0bc\xae\xbe\xbe\xf0\xde\xcc\xcexk\x10\xb3\x86\xd3\xdd\xd0\xc[email protected]\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 

回答

3

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` 

典型輸出

'To be, or not to be - that is the question.' 
Key generated 
Public key <_RSAobj @0xb7114dcc n(1024),e> 
',\x17\xb1\x8a\x98\xb0-z\x8c\xb8r\x17\xa2\xfe[\x10I\x97\x93\x9d[\x93\x19&\\\x16V\xc2\xa3\x99\x80\xa5\x08\xafT\xb5iA|\x89\xeeJ\x90%\xceXv\x9f\x9f\xcb\\P"i\x00D\xd4\x16\xee\xa9\xe49\x18[\xa5\x0f\xd3\xfb\x91\xd5\x98\x1bP\xbf\xa4\xa5Dz\x8b7\x13\x9dqk+\xf7A\xd3\x12\x1c\x06\xcep\xf2\xba\xc6\xee\xf8\xa2\xb4\x04v\xfb\xb7>\xb3U\x17\xban\xf7\xc0oM+Tq\xce\xe3D\x83\xb9\xa4\x90\xe6c,\x18' 
'To be, or not to be - that is the question.' 

FWIW,這裏的上面略加修改的版本,運行在Python 2和Python的3,儘管這兩個版本的輸出會有細微的差異。

在Python 3中,我們不能將字符串傳遞給加密或解密函數,我們必須傳遞字節。此外,Python 3不支持在Python 2中獲取對象的repr的反引號語法。

此代碼調用字符串.encode()和字節.decode()方法執行轉換。我們可以指定的編碼解碼器,如

src_data.encode('utf-8') 

但是這是沒有必要的,因爲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))  

典型的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.' 

我們不真的需要在這裏使用UTF-8編碼。由於src_data是一個純粹的7位ASCII字符串,我們嵌入了到腳本爲文字,我們可以提供它作爲文字字節字符串,而不是:

src_data = b'To be, or not to be - that is the question.' 
+0

是的,像這樣的短輸入也適用於我 – 2015-02-10 08:51:25

+0

爲了使這個工作在python 3中,你需要使用'.encode('UTF-8')' – ScottMcC 2017-05-10 09:40:18

+1

@ScottMcC編碼'src_data'感謝您的提醒。我已經更新了我的答案,以包含Python 2/3兼容代碼。我想這個答案並不真正回答OP的問題,但我想對於那些想在少量文本上使用RSA的人來說,它仍然是一個有用的演示。 – 2017-05-10 10:39:24

4

RSA只能加密有限的大寫金額的輸入。多少取決於RSA的密鑰大小(在你的情況下是1024位)和使用的填充。比這更大的東西(128個字節,當沒有使用填充時,減少使用填充),你不能恢復它。

解決方案是使用混合加密。

  1. 生成隨機字節串16,24或32個字節被用作AES密鑰,
  2. 加密的實際數據與使用先前生成的密鑰和
  3. 加密與RSA AES密鑰的AES。

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') 

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) 

只發送msgciphertext。解密是相似的,但是反過來,因爲你首先必須從RSA密文中恢復AES密鑰。使用AES解密時不要忘記切斷IV。

+0

無論如何,我可以做到這一點沒有一個額外的AES密鑰?因爲我真的只需要使用公鑰/私鑰尋找加密/解密和簽署/驗證文件。 – 2015-02-10 12:30:11

+0

我說過,如果文件太大,那麼你無法使用普通或填充的RSA進行加密/解密。您*需要*混合加密或RSA-KEM。簽名和驗證是可行的,因爲RSA簽名是文件內容散列的加密(使用私鑰),因此大小不可知。 – 2015-02-10 12:35:41

+0

我的教授想要的只是密鑰對的加密/簽名和解密/驗證,所以當你發送某個東西時,他們所需要的只是加密文件,而且只是其中一個密鑰。你所說的簽名是發送3件東西,文件,簽名,公鑰。他希望簽名時包含在文件內的簽名,所以你需要的是公鑰來驗證。 – 2015-02-10 12:39:58