介绍
Python中实现RSA方式的加解密以及加签
依赖包
pycryptodome
加密加签
import base64
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256, MD5
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.Signature import PKCS1_v1_5 as Signature_pkcs1_v1_5
import json
from copy import deepcopy
from collections import OrderedDict
from Crypto import Random
def rsa_pkcs1_encryptAndSign(thirdPublicKey, privateKey, requestJson):
# 本例中,要加密的内容为 requestJson["bizContent"]
# 加签后放在 requestJson["signContent"]
# 用己方私钥加签(privateKey),第三方公钥加密(thirdPublicKey)
bizContent = json.dumps(requestJson["bizContent"])
if "signContent" in requestJson.keys():
del requestJson["signContent"]
# 加密
rsakey = RSA.importKey(base64.b64decode(thirdPublicKey))
bizContent = bytes(bizContent, encoding="utf-8")
cipher = Cipher_pkcs1_v1_5.new(rsakey)
length = len(bizContent)
default_length = 117
offset = 0
res = bytes()
while length - offset > 0:
if length - offset > default_length:
_res = cipher.encrypt(bizContent[offset:offset + default_length])
else:
_res = cipher.encrypt(bizContent[offset:])
offset += default_length
res += _res
requestJson["bizContent"] = base64.b64encode(res).decode('utf-8')
# 加签
# 这一部分参考双方约定,下方模仿Java中的map方法
order_request = deepcopy(requestJson)
linkedmap = OrderedDict()
linkedkeys = sorted(order_request.keys())
for _key in linkedkeys:
linkedmap[_key] = str(order_request[_key])
sign_request = "{"
for key, value in linkedmap.items():
_k_v = "{}={}, ".format(key, value)
sign_request += _k_v
sign_request = sign_request[:-2] + "}"
rsaprivatekey = RSA.importKey(base64.b64decode(bytes(privateKey, encoding='utf-8')))
signer = Signature_pkcs1_v1_5.new(rsaprivatekey)
digest = MD5.new(bytes(sign_request, encoding='utf-8'))
sign = base64.b64encode(signer.sign(digest))
requestJson["signContent"] = sign.decode('utf-8')
return requestJson
解密
def decryptByPrivateKey(bizcontent, privateKey):
# 用己方私钥解密 privateKey
# bizcontent 对应上方加密过程
MAX_DECRYPT_BLOCK = 128
bizcontent = base64.b64decode(bytes(bizcontent, encoding='utf-8'))
privateKey = base64.b64decode(bytes(privateKey, encoding='utf-8'))
privateKey = RSA.import_key(privateKey)
dsize = SHA256.digest_size
sentinel = Random.new().read(15 + dsize)
cipher = Cipher_pkcs1_v1_5.new(privateKey)
input_len = len(bizcontent)
off_set = 0
_bizcontent = bytes()
while input_len - off_set > 0:
if input_len - off_set > MAX_DECRYPT_BLOCK:
_cache = cipher.decrypt(bizcontent[off_set:MAX_DECRYPT_BLOCK + off_set], sentinel)
else:
_cache = cipher.decrypt(bizcontent[off_set:], sentinel)
off_set += MAX_DECRYPT_BLOCK
_bizcontent += _cache
return json.loads(_bizcontent.decode('utf-8'))