文档:https://stuvel.eu/python-rsa-doc/usage.html#generating-keys
安装 rsa
pip install rsa -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
加密、解密
python 版 rsa 库不提供密钥直接加密信息的函数,只提供公钥加密+私钥解密。但是它提供一对 sign()
和 verify()
函数来验证文件签名。sign()
函数需要使用密钥加密文件的 hash值,而使用 verify()
函数解密这个 hash 值,所以从这一对函数里面找到了私钥加密+公钥解密的方式。
class RsaPrivate():
def __init__(self, pem):
if isinstance(pem, str) or isinstance(pem, io.BytesIO):
# read from filepath
with open(pem, 'rb') as f:
self.privkey = rsa.PrivateKey.load_pkcs1(f.read())
self.pubkey = rsa.PublicKey(self.privkey.n, self.privkey.e)
elif isinstance(pem, bytes):
# read from memory
self.privkey = rsa.PrivateKey.load_pkcs1(pem)
self.pubkey = rsa.PublicKey(self.privkey.n, self.privkey.e)
elif isinstance(pem, rsa.PrivateKey):
self.privkey = pem
self.pubkey = rsa.PublicKey(self.privkey.n, self.privkey.e)
else:
raise Exception("unsupported pem type")
def padding(self, msg):
keylength = self.keylen()
assert isinstance(msg, bytes)
if len(msg) >= keylength:
raise Exception(f"msg length is too long: {len(msg)} > {keylength - 1}")
mlen = len(msg)
bmlen = mlen.to_bytes(1, 'big')
logger.debug("meglen: {} {} , keylength: {}".format(str(bmlen), len(msg), keylength))
okmsg = bmlen + b'\xff' * (keylength - mlen - 1) + msg
assert len(okmsg) == keylength
return okmsg
def keylen(self):
keylength = rsa.common.byte_size(self.privkey.n)
return keylength
def encrypt(self, message):
cleartext = message
if isinstance(message, bytes):
cleartext = message
elif isinstance(message, str):
cleartext = message.encode()
else:
raise Exception("unsupported message type, should be bytes or str")
keylength = self.keylen()
padded = self.padding(cleartext)
logger.debug(f"padded type: {type(padded)} , length: {len(padded)}")
payload = rsa.transform.bytes2int(padded)
encrypted = self.privkey.blinded_encrypt(payload)
block = rsa.transform.int2bytes(encrypted, keylength)
return block
def decrypt(self, message):
msg = message
if isinstance(message, bytes):
msg = message
elif isinstance(message, str):
msg = message.encode()
else:
raise Exception("unsupported message type, should be bytes or str")
keylength = rsa.common.byte_size(self.privkey.n)
ened = rsa.transform.bytes2int(msg)
deed = rsa.core.decrypt_int(ened, self.pubkey.e, self.pubkey.n)
txt = rsa.transform.int2bytes(deed, keylength)
logger.debug(f"txt[0] type: {type(txt[0])}", txt[0])
mlen = txt[0]
originmsg = txt[keylength - mlen:]
return originmsg
keylen = 512 # 1024
(pubkey, priv_key) = rsa.newkeys(keylen)
#xx = priv_key.save_pkcs1()
#rsaprivkey = RsaPrivate(xx)
rsaprivkey = RsaPrivate(priv_key)