在pycrypto中使用RSA解密大文件?
Decrypting Large files with RSA in pycrypto?
我一直在使用 pycrypto 模块通过 RSA 密钥对和算法进行加密和解密。问题是当我尝试加密大文件(10kB 的文本文件)时,我在读取文件和加密时采用 32 字节的块大小
>>> f = open('10kb','rb')
>>> p = open('enc','wb')
>>> while True:
data = f.read(32)
if not data:
break
enc_data = public_key.encrypt(data,32)
p.write(enc_data[0])
p.close()
f.close()
它给出了输出:
128
128
.......and the many 128 blocks it is writing
当我尝试解密加密文件时,我需要用 128 字节块读取它以便返回 32 字节块,
>>> f = open('enc','rb')
>>> p = open('dec','wb')
>>> while True:
data = f.read(128)
if not data:
break
dec_data = private_key.decrypt(data)
p.write(dec_data)
p.close()
f.close()
它给出输出:
32
32
.....so many 32 byte blocks it is decrypting, then
128
128
128
128
Traceback (most recent call last):
File "<pyshell#251>", line 5, in <module>
enc_data = private_key.decrypt(data)
File "/usr/lib/python3/dist-packages/Crypto/PublicKey/RSA.py", line 174, in decrypt
return pubkey.pubkey.decrypt(self, ciphertext)
File "/usr/lib/python3/dist-packages/Crypto/PublicKey/pubkey.py", line 93, in decrypt
plaintext=self._decrypt(ciphertext)
File "/usr/lib/python3/dist-packages/Crypto/PublicKey/RSA.py", line 237, in _decrypt
cp = self.key._blind(ciphertext, r)
ValueError: Message too large
到输出块大小为 32 的地步,它是正确解密的,但是从 128 开始的地方,它搞砸了。为什么它说 Message size too large ?有没有更好更快的方法来使用 pycrypto 模块解密大文本文件?
部分 答案即将出现...
RSA 处理数字。当您序列化那些长整数时,您只能从中获取字节。由于这些数字没有固定大小,因此会根据需要使用尽可能多的字节对它们进行序列化,但不会更多。
一个RSA加密c = me mod n 会产生比 n 小得多的密文,以至于并非所有字节都被填充,因为数字的前导零不必序列化。
有时(取决于 modulus 和明文)您可能会在加密期间写入 127 字节的块而不是 128 字节的块,但在加密期间您总是读取 128 字节的块解密。这意味着,您要从下一个块中拿走一个字节。当对齐中断时,您可以 运行 进入各种随机行为,例如大于 modulus 的块,因此不是有效的密文。
有两种方法可以解决:
永远把密文块的长度写在前面
加密:
data = f.read(readsize)
if not data:
break
i += 1
enc_data = public_key.encrypt(data, 32)[0]
p.write(chr(len(enc_data)))
p.write(enc_data)
解密:
length = f.read(1)
if not length:
break
data = f.read(ord(length))
print(length, len(data))
j += 1
dec_data = private_key.decrypt(data)
p.write(dec_data[:readsize])
最后你必须将密文减少到原始明文大小,因为你在没有 PKCS#1 v1.5 填充或 OAEP 的情况下工作。
填充加密过程中丢失的零字节。
加密:
data = f.read(readsize)
if not data:
break
i += 1
enc_data = public_key.encrypt(data, 32)[0]
while len(enc_data) < writesize:
enc_data = "\x00" + enc_data
p.write(enc_data)
解密:
data = f.read(writesize)
if not data:
break
j += 1
dec_data = private_key.decrypt(data)
p.write(dec_data[:readsize])
请注意 readsize = 127
和 writesize = 128
。 Here 是两个变体的完整源代码。
现在,这是部分答案,因为这仍然会导致损坏的文件,这些文件也太短了,但至少它修复了 OP 的错误。
我一直在使用 pycrypto 模块通过 RSA 密钥对和算法进行加密和解密。问题是当我尝试加密大文件(10kB 的文本文件)时,我在读取文件和加密时采用 32 字节的块大小
>>> f = open('10kb','rb')
>>> p = open('enc','wb')
>>> while True:
data = f.read(32)
if not data:
break
enc_data = public_key.encrypt(data,32)
p.write(enc_data[0])
p.close()
f.close()
它给出了输出:
128
128
.......and the many 128 blocks it is writing
当我尝试解密加密文件时,我需要用 128 字节块读取它以便返回 32 字节块,
>>> f = open('enc','rb')
>>> p = open('dec','wb')
>>> while True:
data = f.read(128)
if not data:
break
dec_data = private_key.decrypt(data)
p.write(dec_data)
p.close()
f.close()
它给出输出:
32
32
.....so many 32 byte blocks it is decrypting, then
128
128
128
128
Traceback (most recent call last):
File "<pyshell#251>", line 5, in <module>
enc_data = private_key.decrypt(data)
File "/usr/lib/python3/dist-packages/Crypto/PublicKey/RSA.py", line 174, in decrypt
return pubkey.pubkey.decrypt(self, ciphertext)
File "/usr/lib/python3/dist-packages/Crypto/PublicKey/pubkey.py", line 93, in decrypt
plaintext=self._decrypt(ciphertext)
File "/usr/lib/python3/dist-packages/Crypto/PublicKey/RSA.py", line 237, in _decrypt
cp = self.key._blind(ciphertext, r)
ValueError: Message too large
到输出块大小为 32 的地步,它是正确解密的,但是从 128 开始的地方,它搞砸了。为什么它说 Message size too large ?有没有更好更快的方法来使用 pycrypto 模块解密大文本文件?
部分 答案即将出现...
RSA 处理数字。当您序列化那些长整数时,您只能从中获取字节。由于这些数字没有固定大小,因此会根据需要使用尽可能多的字节对它们进行序列化,但不会更多。
一个RSA加密c = me mod n 会产生比 n 小得多的密文,以至于并非所有字节都被填充,因为数字的前导零不必序列化。
有时(取决于 modulus 和明文)您可能会在加密期间写入 127 字节的块而不是 128 字节的块,但在加密期间您总是读取 128 字节的块解密。这意味着,您要从下一个块中拿走一个字节。当对齐中断时,您可以 运行 进入各种随机行为,例如大于 modulus 的块,因此不是有效的密文。
有两种方法可以解决:
永远把密文块的长度写在前面
加密:
data = f.read(readsize) if not data: break i += 1 enc_data = public_key.encrypt(data, 32)[0] p.write(chr(len(enc_data))) p.write(enc_data)
解密:
length = f.read(1) if not length: break data = f.read(ord(length)) print(length, len(data)) j += 1 dec_data = private_key.decrypt(data) p.write(dec_data[:readsize])
最后你必须将密文减少到原始明文大小,因为你在没有 PKCS#1 v1.5 填充或 OAEP 的情况下工作。
填充加密过程中丢失的零字节。
加密:
data = f.read(readsize) if not data: break i += 1 enc_data = public_key.encrypt(data, 32)[0] while len(enc_data) < writesize: enc_data = "\x00" + enc_data p.write(enc_data)
解密:
data = f.read(writesize) if not data: break j += 1 dec_data = private_key.decrypt(data) p.write(dec_data[:readsize])
请注意 readsize = 127
和 writesize = 128
。 Here 是两个变体的完整源代码。
现在,这是部分答案,因为这仍然会导致损坏的文件,这些文件也太短了,但至少它修复了 OP 的错误。