我只有一些关于 RSA 的非常基本的理论知识。
在阅读有关如何在实践中使用它的不同来源时,PKCS#1 OAEP 似乎是一件好事。
对于测试实现,我使用 Python 和 PyCrypto。例如,这是一个使用 PKCS#1 OAEP 的示例。
使用公钥加密然后使用私钥解密可以正常工作。例如,公众可以使用私钥向 X 人发送一些数据。
根据我对 RSA 工作原理的基本了解,我认为我可以互换公钥/私钥,即我可以使用公钥进行加密,使用私钥进行解密。例如,某人 X 可以使用自己的私钥加密某些数据,而公众可以使用公钥对其进行解密。如果解密工作正常,这可以证明数据来自 X 人。
当我尝试使用公钥解密时,PyCrypto 会抱怨。
通过阅读 PyCrypto 源代码,在_RSAKey._decrypt
函数(此处)中,似乎密钥对象本身知道它是私钥还是公钥并且它们之间存在差异(令我惊讶的是,再次基于我非常基本的 RSA 理解)。
从那里,看起来我可以破解解密功能,以便它使用公钥。或者有些不同:我可以在关键对象中交换公共指数e
和私有指数。d
但这一切似乎并不打算以这种方式使用/被黑客入侵。所以我想在这里问一下我的误解。
另外,出于好奇,我生成了一些键 ( RSA.generate(2048)
) 并查看了n
,e
和d
. 在所有情况下,n
并且d
非常巨大,而e
在所有情况下都是恒定的(65537)(我没想到会这样)。
我想从这一切来看,我真的不应该只是交换e
和d
.
所以我想我应该使用其他方法来签名,比如 PKCS1_PSS。
如果有人感兴趣,一些用于加密/解密的代码:
def randomString(l):
import random
return ''.join(chr(random.randint(0, 0xFF)) for i in range(l))
def genkeypair():
from Crypto.PublicKey import RSA
key = RSA.generate(2048)
pubkey = key.publickey().exportKey("DER")
privkey = key.exportKey("DER")
return (pubkey,privkey)
def encrypt(v, rsapubkey):
from Crypto.PublicKey import RSA
rsakey = RSA.importKey(rsapubkey)
from Crypto.Cipher import PKCS1_OAEP
rsa = PKCS1_OAEP.new(rsakey)
import binstruct
from array import array
aeskey = randomString(32)
iv = randomString(16)
from Crypto.Cipher import AES
aes = AES.new(aeskey, AES.MODE_CBC, iv)
data = binstruct.varEncode(v)
data += array("B", (0,) * (-len(data) % 16))
out = binstruct.strEncode(rsa.encrypt(aeskey + iv))
out += array("B", aes.encrypt(data))
return out
def decrypt(stream, rsaprivkey):
from array import array
from StringIO import StringIO
if isinstance(stream, array): stream = stream.tostring()
if isinstance(stream, str): stream = StringIO(stream)
from Crypto.PublicKey import RSA
rsakey = RSA.importKey(rsaprivkey)
from Crypto.Cipher import PKCS1_OAEP
rsa = PKCS1_OAEP.new(rsakey)
import binstruct
aesdata = binstruct.strDecode(stream)
aesdata = rsa.decrypt(aesdata)
aeskey = aesdata[0:32]
iv = aesdata[32:]
from Crypto.Cipher import AES
aes = AES.new(aeskey, AES.MODE_CBC, iv)
class Stream:
buffer = []
def read1(self):
if len(self.buffer) == 0:
nextIn = stream.read(16)
self.buffer += list(aes.decrypt(nextIn))
return self.buffer.pop(0)
def read(self, n):
return "".join([self.read1() for i in range(n)])
v = binstruct.varDecode(Stream())
return v
(binstruct
是一个可以编码/解码树数据结构的小模块 - 类似于 JSON/BSON。)
这就是我认为我也可以使用encrypt
私钥和decrypt
公钥的地方。
(希望)正确签名/身份验证的最终实现可以在 binstruct 中找到。