Skip to content

Commit 71629b0

Browse files
authored
Merge pull request #17 from Safeheron/dev
Dev
2 parents 916f33f + feb1963 commit 71629b0

File tree

3 files changed

+88
-12
lines changed

3 files changed

+88
-12
lines changed

safeheron_api_sdk_python/cosigner/co_signer_converter.py

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,33 @@ def __init__(self):
99
self.txKey = None
1010

1111

12+
class CoSignerResponseV3:
13+
def __init__(self):
14+
# action
15+
self.action = None
16+
# approvalId
17+
self.approvalId = None
18+
19+
1220
class CoSignerConverter:
1321

1422
def __init__(self, config):
15-
self.api_pub_key = config['apiPubKey']
16-
if config.get('bizPrivKey'):
17-
self.biz_privKey = PEM_PRIVATE_HEAD + config['bizPrivKey'] + PEM_PRIVATE_END
18-
if config.get('bizPrivKeyPemFile'):
19-
self.biz_privKey = load_rsa_private_key(config['bizPrivKeyPemFile'])
23+
# Supports both coSignerPubKey and apiPublKey
24+
self.co_signer_pub_key = config.get('coSignerPubKey') or config.get('apiPubKey')
25+
26+
# Supports both approvalCallbackServicePrivateKey and bizPrivKey
27+
private_key = config.get('approvalCallbackServicePrivateKey') or config.get('bizPrivKey')
28+
if private_key:
29+
self.approval_callback_service_private_key = PEM_PRIVATE_HEAD + private_key + PEM_PRIVATE_END
30+
31+
# Supports both approvalCallbackServicePrivateKeyPemFile and bizPrivKeyPemFile
32+
pem_file = config.get('approvalCallbackServicePrivateKeyPemFile') or config.get('bizPrivKeyPemFile')
33+
if pem_file:
34+
self.approval_callback_service_private_key = load_rsa_private_key(pem_file)
2035

2136
def request_convert(self, co_signer_call_back):
22-
platform_rsa_pk = get_rsa_key(PEM_PUBLIC_HEAD + self.api_pub_key + PEM_PUBLIC_END)
23-
api_user_rsa_sk = get_rsa_key(self.biz_privKey)
37+
platform_rsa_pk = get_rsa_key(PEM_PUBLIC_HEAD + self.co_signer_pub_key + PEM_PUBLIC_END)
38+
api_user_rsa_sk = get_rsa_key(self.approval_callback_service_private_key)
2439
required_keys = {
2540
'key',
2641
'sig',
@@ -65,10 +80,50 @@ def request_convert(self, co_signer_call_back):
6580

6681
return json.loads(r.decode())
6782

83+
def request_v3_convert(self, co_signer_call_back):
84+
platform_rsa_pk = get_rsa_key(PEM_PUBLIC_HEAD + self.co_signer_pub_key + PEM_PUBLIC_END)
85+
required_keys = {
86+
'version',
87+
'sig',
88+
'bizContent',
89+
'timestamp',
90+
}
91+
92+
missing_keys = required_keys.difference(co_signer_call_back.keys())
93+
if missing_keys:
94+
raise Exception(co_signer_call_back)
95+
co_signer_call_back['version'] = 'v3'
96+
sig = co_signer_call_back.pop('sig')
97+
98+
need_sign_message = sort_request(co_signer_call_back)
99+
v = rsa_pass_verify(platform_rsa_pk, need_sign_message, sig)
100+
if not v:
101+
raise Exception("rsa verify: false")
102+
return json.loads(b64decode(co_signer_call_back['bizContent']).decode())
103+
104+
def response_v3_converter(self, co_signer_response: CoSignerResponseV3):
105+
api_user_rsa_sk = get_rsa_key(self.approval_callback_service_private_key)
106+
ret = dict()
107+
response_data = json.dumps(co_signer_response.__dict__).replace('\'', '\"').replace('\n', '').encode('utf-8')
108+
109+
if response_data is not None:
110+
ret['bizContent'] = b64encode(response_data).decode()
111+
112+
ret['timestamp'] = str(int(time.time() * 1000))
113+
ret['code'] = str('200')
114+
ret['version'] = str('v3')
115+
ret['message'] = str('SUCCESS')
116+
117+
# 4 sign request
118+
need_sign_message = sort_request(ret)
119+
ret['sig'] = rsa_pss_sign(api_user_rsa_sk, need_sign_message)
120+
return ret
121+
122+
68123
# It has been Deprecated,Please use convertCoSignerResponseWithNewCryptoType
69124
def response_converter(self, co_signer_response: CoSignerResponse):
70-
platform_rsa_pk = get_rsa_key(PEM_PUBLIC_HEAD + self.api_pub_key + PEM_PUBLIC_END)
71-
api_user_rsa_sk = get_rsa_key(self.biz_privKey)
125+
platform_rsa_pk = get_rsa_key(PEM_PUBLIC_HEAD + self.co_signer_pub_key + PEM_PUBLIC_END)
126+
api_user_rsa_sk = get_rsa_key(self.approval_callback_service_private_key)
72127

73128
ret = dict()
74129

@@ -98,8 +153,8 @@ def response_converter(self, co_signer_response: CoSignerResponse):
98153
return ret
99154

100155
def response_converter_with_new_crypto_type(self, co_signer_response: CoSignerResponse):
101-
platform_rsa_pk = get_rsa_key(PEM_PUBLIC_HEAD + self.api_pub_key + PEM_PUBLIC_END)
102-
api_user_rsa_sk = get_rsa_key(self.biz_privKey)
156+
platform_rsa_pk = get_rsa_key(PEM_PUBLIC_HEAD + self.co_signer_pub_key + PEM_PUBLIC_END)
157+
api_user_rsa_sk = get_rsa_key(self.approval_callback_service_private_key)
103158

104159
ret = dict()
105160

safeheron_api_sdk_python/tools.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from Cryptodome.Hash import SHA256, SHA1
99
from Cryptodome import Random
1010
from Crypto.Cipher import PKCS1_OAEP
11+
from Cryptodome.Signature import pss
1112
import json
1213
import time
1314
import requests
@@ -147,6 +148,16 @@ def rsa_sign(private_key, message_hash: bytes):
147148
except Exception as e:
148149
raise Exception("rsa sign error: %s" % e)
149150

151+
def rsa_pss_sign(private_key, message_hash: bytes):
152+
try:
153+
signer = pss.new(private_key)
154+
digest = SHA256.new()
155+
digest.update(message_hash)
156+
signed = signer.sign(digest)
157+
return b64encode(signed).decode()
158+
except Exception as e:
159+
raise Exception("rsa sign error: %s" % e)
160+
150161

151162
def rsa_verify(public_key, message_hash: bytes, signature):
152163
try:
@@ -157,6 +168,16 @@ def rsa_verify(public_key, message_hash: bytes, signature):
157168
except Exception as e:
158169
raise Exception("rsa sign error: %s" % e)
159170

171+
def rsa_pass_verify(public_key, message_hash: bytes, signature):
172+
try:
173+
verifier = pss.new(public_key)
174+
digest = SHA256.new()
175+
digest.update(message_hash)
176+
verifier.verify(digest, b64decode(signature))
177+
return True
178+
except Exception as e:
179+
raise Exception("rsa sign error: %s" % e)
180+
160181

161182
def sort_request(r: dict):
162183
sortData = json.dumps(r, sort_keys=True).replace(' ', '')

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
with open("README.rst", "r") as f:
44
long_description = f.read()
55
setup(name='safeheron_api_sdk_python',
6-
version='1.1.13',
6+
version='1.1.14',
77
description='Python for Safeheron API',
88
long_description=long_description,
99
author='safeheron',

0 commit comments

Comments
 (0)