python 实现私钥加密公钥解密
业界普遍的用法是公钥用来加密,私钥来解密,许多人却不知道也可以用私钥加密,公钥来解密
基础知识
对称加密
非对称加密
公私钥的几个常见格式
图片来源: https://www.openssl.org/docs/...
使用私钥加密
待编辑
使用公钥解密
参考文档:
https://www.cnblogs.com/masak...
https://www.linuxidc.com/Linu...
python2.7 的实现
from rsa import PublicKey, common, transform, core
# 公钥格式如下,若公钥已经是 RSAPublicKey 格式,则无需将 pub key 转换为 string
PUB_KEY_STRING = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsKfRext58G0buLDabQQNBVWEB1/B62PapiZ2tSiITw/3X4cI00QB6m7dryMqs7pKntUD3MTGeMCj9zwXX0kmqkrA8og0H0eOHQnAeuw671lkSVYnD1YVcICPv+fbJ1JL+DP3RkXuy0+V2iQC2GDQmfgTcKVowU4c+ToQIp0pUBQIDAQAB'
class DecryptByPublicKey(object):
"""
使用 publib key来解密用primary key加密后生成的base64类型的密文
返回解密后的数据
"""
def __init__(self, encrypt_text):
self.encrypt_text = encrypt_text
@staticmethod
def str2key(s):
# 对字符串解码, 解码成功返回 模数和指数
b_str = base64.b64decode(s)
if len(b_str) < 162:
return False
hex_str = ''
# 按位转换成16进制
for x in b_str:
h = hex(ord(x))[2:]
h = h.rjust(2, '0')
hex_str += h
# 找到模数和指数的开头结束位置
m_start = 29 * 2
e_start = 159 * 2
m_len = 128 * 2
e_len = 3 * 2
modulus = hex_str[m_start:m_start + m_len]
exponent = hex_str[e_start:e_start + e_len]
return modulus,exponent
@staticmethod
def f(cipher, PUBLIC_KEY):
"""
decrypt msg by public key
"""
public_key = PublicKey.load_pkcs1(PUBLIC_KEY)
encrypted = transform.bytes2int(cipher)
decrypted = core.decrypt_int(encrypted, public_key.e, public_key.n)
text = transform.int2bytes(decrypted)
if len(text) > 0 and text[0] == '\x01':
pos = text.find('\x00')
if pos > 0:
return text[pos+1:]
else:
return None
def pub_decrypt_with_pubkeystr(self):
"""
将 base64 编码的 pub_key 转成 bio 对象,
再将bio对象转换成公钥对象
"""
# 将 pub key 转换为 string
# Note: 若公钥已经是 RSAPublicKey 格式,则无需执行这一步 !
try:
key = self.str2key(PUB_KEY_STRING) # 将 base64 编码的公钥进行拆解,取出模数和指数
if not key:
raise Exception, "decode public key falid"
modulus = int(key[0], 16)
exponent = int(key[1], 16)
rsa_pubkey = PublicKey(modulus, exponent) # 根据模数和指数生成 pubkey 对象
self.pub_key = rsa_pubkey.save_pkcs1() # 将 pubkey 对象导出为 RSAPublicKey 格式的公钥
except Exception, e:
assert False, "Invalid public_key"
# 开始解密
try:
ret = self.f(self.encrypt_text.decode("base64"), self.pub_key)
except Exception, e:
self.error_info = str(e)
assert False, "Decrypt by public key fails! Invalid encrypt_text"
return ret
if __name__ == "__main__":
encrypt_text = 'xxxxxx' # encrypt_text 是被私钥加密后的密文
decrypt = DecryptByPublicKey(encrypt_text)
result = decrypt.pub_decrypt_with_pubkeystr()
print result
python3 的实现
# 系统库
import six
import logging
import coloredlogs
# 第三方库
import rsa
import base64
p = logging.getLogger()
console_formatter = logging.StreamHandler()
console_formatter.setFormatter(coloredlogs.ColoredFormatter('%(asctime)s - %(module)-14s[line:%(lineno)3d] - %(levelname)-8s: %(message)s'))
p.addHandler(console_formatter)
p.setLevel(logging.DEBUG)
PUB_KEY_STRING = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsKfRext58G0buLDabQQNBVWEB1/B62PapiZ2tSiITw/3X4cI00QB6m7dryMqs7pKntUD3MTGeMCj9zwXX0kmqkrA8og0H0eOHQnAeuw671lkSVYnD1YVcICPv+fbJ1JL+DP3RkXuy0+V2iQC2GDQmfgTcKVowU4c+ToQIp0pUBQIDAQAB'
class DecryptByPublicKey(object):
"""
先产生模数因子
然后生成rsa公钥
再使用rsa公钥去解密传入的加密str
"""
def __init__(self, encrypt_text):
self._encrypt_text = encrypt_text
self._pub_string_key = PUB_KEY_STRING
# 使用公钥字符串求出模数和因子
self._modulus = None # 模数
self._exponent = None # 因子
# 使用PublicKey(模数,因子)算出公钥
self._pub_rsa_key = None
def _gen_modulus_exponent(self, s) ->int:
p.debug("Now base64 decode pub key,return modulus and exponent")
# 对字符串解码, 解码成功返回 模数和指数
b_str = base64.b64decode(s)
if len(b_str) < 162:
return False
hex_str = b_str.hex()
# 找到模数和指数的开头结束位置
m_start = 29 * 2
e_start = 159 * 2
m_len = 128 * 2
e_len = 3 * 2
self._modulus = int(hex_str[m_start:m_start + m_len], 16)
self._exponent = int(hex_str[e_start:e_start + e_len], 16)
def _gen_rsa_pubkey(self):
# 将pub key string 转换为 pub rsa key
p.debug("Now turn key string to rsa key")
try:
rsa_pubkey = rsa.PublicKey(self._modulus, self._exponent)
# 赋值到_pub_rsa_key
self._pub_rsa_key = rsa_pubkey.save_pkcs1()
# p.debug("self._pub_rsa_key:{}".format(self._pub_rsa_key))
except Exception as e:
p.error(e)
p.error("Invalid public_key")
raise e
def decode(self) ->str:
"""
decrypt msg by public key
"""
p.debug("Now decrypt msg by public rsa key")
b64decoded_encrypt_text = base64.b64decode(self._encrypt_text)
public_key = rsa.PublicKey.load_pkcs1(self._pub_rsa_key)
encrypted = rsa.transform.bytes2int(b64decoded_encrypt_text)
decrypted = rsa.core.decrypt_int(encrypted, public_key.e, public_key.n)
# p.debug('decrypted: {}'.format(decrypted))
decrypted_bytes = rsa.transform.int2bytes(decrypted)
# 这里使用了six库的iterbytes()方法去模拟python2对bytes的轮询
if len(decrypted_bytes) > 0 and list(six.iterbytes(decrypted_bytes))[0] == 1:
try:
raw_info = decrypted_bytes[decrypted_bytes.find(b'\x00')+1:]
except Exception as e:
p.error(e)
raise e
return raw_info.decode("utf-8")
def decrypt(self) -> str:
"""
先产生模数因子
然后生成rsa公钥
再使用rsa公钥去解密
"""
self._gen_modulus_exponent(self._pub_string_key)
self._gen_rsa_pubkey()
ret = self.decode()
return ret
if __name__ == "__main__":
encrypt_text = 'xxxxxx' # encrypt_text 是被私钥加密后的密文
result = DecryptByPublicKey(encrypt_text).decrypt()
p.info(result)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。