Python3基礎-使用RSA2(SHA256WithRSA)簽名加密作為sign值的問題
接口規范
1、篩選并排序
獲取所有請求參數,不包括字節類型參數,如文件、字節流,剔除 sign 字段,剔除值為空的參數,并按照第一個字符的鍵值 ASCII 碼遞增排序(字母升序排序),如果遇到相同字符則按照第二個字符的鍵值 ASCII 碼遞增排序,以此類推
2、拼接
將排序后的參數與其對應值,組合成“參數=參數值”的格式,并且把這些參數用 & 字符連接起來,此時生成的字符串為待簽名字符串。
app_id=2021072300007148 request_body={"user_id":1} timestamp=1612776451123 version=1.0
待簽名字符串
app_id=2021072300007148&request_body={"user_id":1}×tamp=1612776451123&version=1.0
3、調用簽名函數
使用各自語言對應的 SHA256WithRSA簽名函數利用商戶私鑰對待簽名字符串進行簽名,并進行 Base64 編碼。
4、生成的簽名復制給sign參數
接口Demo
需要插件:pycryptodome
接口文檔格式,以下文件在同一個目錄下
logo_demo目錄 --- config.py 配置文件
logo_demo目錄 --- rsa_crypt.py 加密文件
logo_demo目錄 --- sign_demo.py sigh值文件
# coding=utf-8 import json import time from base64 import b64decode from urllib.parse import urlencode from config import APP_ID, VERSION, APP_PRIVATE_KEY, APP_PUBLIC_KEY, ZAN_PRIVATE_KEY, ZAN_PUBLIC_KEY from rsa_crypt import RSAPubCrypt, RSAPrvCrypt def main(): # 1. 非碼簽名驗簽測試 jump_page = 'https://test-group.51zan.com/into-channel' request_body = { "notify_url":"http://106.54.78.58:58082/", "partner_id": "40000000000000000000", "staff_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa24000" } test_data_dict = { "app_id": APP_ID, "request_body": json.dumps(request_body, sort_keys=True, separators=(',', ':')), "timestamp": int(time.time() * 1000), "version": VERSION, } print("test_data_dict:",test_data_dict) # 私鑰簽名 rsa_prv_crypt = RSAPrvCrypt(b64decode(APP_PRIVATE_KEY)) test_data_str = rsa_prv_crypt.sign_data(test_data_dict) print("test_data_str:",test_data_str) test_data_sign = rsa_prv_crypt.sign(test_data_str) print("test_data_sign:",test_data_sign) # 公鑰驗簽 rsa_pub_crypt = RSAPubCrypt(b64decode(APP_PUBLIC_KEY)) print("公鑰驗簽",rsa_pub_crypt.verify_sign(test_data_str, test_data_sign)) # 成功返回 True 或 失敗返回 False test_data_dict['sign'] = test_data_sign query_string = urlencode(test_data_dict) print('{}?{}'.format(jump_page, query_string)) if __name__ == '__main__': main()
# coding=utf-8 import base64 import json from Crypto.Cipher import PKCS1_v1_5 from Crypto.Hash import SHA256 from Crypto.PublicKey import RSA from Crypto.Signature import pkcs1_15 # RSA加密類 class RSACrypt(object): def __init__(self, key): self.key = RSA.importKey(key) @staticmethod def sign_data(data_dict): tmp = [] print("data_dict:",data_dict) for key in sorted(data_dict.keys()): value = data_dict[key] # print("value:",value) if isinstance(value, dict) or isinstance(value, list): tmp.append('{}={}'.format(key, json.dumps(value, sort_keys=True, separators=(',', ':')))) else: tmp.append('{}={}'.format(key, value)) # print("tmp",tmp) return '&'.join(tmp) # RSA公鑰 class RSAPubCrypt(RSACrypt): # RSA公鑰加密 def encrypt(self, data, length=200): try: # 1024bit的證書用100,2048bit證書用200位 data = data.encode('utf-8') cipher = PKCS1_v1_5.new(self.key) res = [] for i in range(0, len(data), length): res.append(cipher.encrypt(data[i:i + length])) return str(base64.b64encode(b"".join(res)), encoding='utf-8') except: return False # RSA公鑰驗證簽名 def verify_sign(self, data, signature): try: if isinstance(data, dict): data = self.sign_data(data) data = data.encode('utf-8') h = SHA256.new(data) pkcs1_15.new(self.key).verify(h, base64.b64decode(signature)) return True except (ValueError, TypeError): return False # RSA私鑰 class RSAPrvCrypt(RSACrypt): # RSA私鑰解密 def decrypt(self, encrypt_data, length=256): # 1024bit的證書用128,2048bit證書用256位 print("=====") try: cipher = PKCS1_v1_5.new(self.key) encrypt_data = base64.b64decode(encrypt_data) data = [] for i in range(0, len(encrypt_data), length): data.append(cipher.decrypt(encrypt_data[i:i + length], 'xyz')) return str(b"".join(data), encoding='utf-8') except: return False # RSA私鑰生成簽名 def sign(self, data): try: if isinstance(data, dict): data = self.sign_data(data) data = data.encode('utf-8') h = SHA256.new(data) signature = pkcs1_15.new(self.key).sign(h) return str(base64.b64encode(signature), encoding='utf-8') except: return False
# coding=utf-8 # 公鑰 ZAN_PUBLIC_KEY = ('xxx',''sss) # 私鑰 ZAN_PRIVATE_KEY = ('aa','bb') APP_ID = "20210800007148" # VERSION = "1.0" # 接口版本號,目前固定為1.0 # 測試私鑰 APP_PRIVATE_KEY = "MITDDDD" # 測試公鑰 APP_PUBLIC_KEY = " DDDDD"
浙公網安備 33010602011771號