感谢 Almog 和 ALX,您的回答有所帮助。不幸的是,我不能赞成你的答案,没有足够的 stackoverflow 声誉。
我已经解决了一些其他细节,例如创建 pkcs#1 签名并验证它。我在这里发布完整的清理源代码以供其他人将来参考。我的结论是,使用 REST API 的源代码示例确实会有所帮助,无论使用哪种语言 - 所以我建议在文档站点的示例页面中的某处编写一个甚至使用我的源代码示例。
再次感谢你的帮助。
import urllib2
import hashlib
import base64
import json
import string
class Client:
_HEADERS = {'Content-Type': 'application/json; charset=utf-8'}
_ALGORITHMS = dict(
Sha256=lambda x: hashlib.sha256(x).digest(),
Sha384=lambda x: hashlib.sha385(x).digest(),
Sha512=lambda x: hashlib.sha512(x).digest())
_PKCS1_FLAGS = 0x80000
_ALGORITHM_FLAGS = dict(
Sha256=0x04000,
Sha384=0x08000,
Sha512=0x10000)
def __init__(self, username, password, hostname="prime.cosigntrial.com"):
self._username = username
self._password = password
self._signURL = 'https://%s:8081/sapiws/SignBuffer' % hostname
self._verifyURL = 'https://%s:8081/sapiws/VerifyBuffer' % hostname
self._getCertificatesURL = 'https://%s:8081/sapiws/UserCertificatesGet' % hostname
self._serverInfoURL = 'https://%s:8081/sapiws/ServerInfoGet' % hostname
def signBytes(self, bytes, algorithm="Sha512", pkcs1=False):
assert algorithm in self._ALGORITHMS, "'%s' is not Sha256|384|512" % algorithm
parameters = dict(
Username=self._username, Password=self._password,
BufferToSign=base64.b64encode(bytes), HashAlg=algorithm)
if pkcs1:
parameters['Flags'] = self._PKCS1_FLAGS
result = self._transaction(self._signURL, parameters)
if not result[u'Success']:
raise Exception("Sign buffer failed (%s)" % result)
return result[u'Data'][u'Signature']
def verifyBytes(self, bytes, signature, pkcs1Certificate=None, pkcs1Algorithm="Sha512"):
assert self._isBase64(signature), "Signature must be in base64 format"
parameters = dict(
BufferToSign=base64.b64encode(bytes), Signature=self._removeCRLF(signature))
if pkcs1Certificate is not None:
assert self._isBase64(pkcs1Certificate), "Certificate must be in base 64 format"
assert pkcs1Algorithm in self._ALGORITHM_FLAGS, "'%s' is no Sha256|384|512" % pkcs1Algorithm
parameters['Flags'] = self._PKCS1_FLAGS | self._ALGORITHM_FLAGS[pkcs1Algorithm]
parameters['Certificate'] = self._removeCRLF(pkcs1Certificate)
result = self._transaction(self._verifyURL, parameters)
if not result[u'Success']:
raise Exception("Verify buffer failed (%s)" % result)
return result[u'Data']
def signUsingHash(self, bytes, algorithm="Sha512", pkcs1=False):
assert algorithm in self._ALGORITHMS, "'%s' is not Sha256|384|512" % algorithm
digest = self._ALGORITHMS[algorithm](bytes)
parameters = dict(
Username=self._username, Password=self._password,
BufferToSign=base64.b64encode(digest),
BufferHash=True, HashAlg=algorithm)
if pkcs1:
parameters['Flags'] = self._PKCS1_FLAGS
result = self._transaction(self._signURL, parameters)
if not result[u'Success']:
raise Exception("Sign buffer failed (%s)" % result)
return result[u'Data'][u'Signature']
def verifyUsingHash(self, bytes, signature, algorithm="Sha512", pkcs1Certificate=None):
assert self._isBase64(signature), "Signature must be in base64 format"
assert algorithm in self._ALGORITHMS, "'%s' is not Sha256|384|512" % algorithm
digest = self._ALGORITHMS[algorithm](bytes)
parameters = dict(
BufferToSign=base64.b64encode(digest), Signature=self._removeCRLF(signature),
BufferHash=True)
if pkcs1Certificate is not None:
assert self._isBase64(pkcs1Certificate), "Certificate must be in base 64 format"
parameters['Flags'] = self._PKCS1_FLAGS
parameters['Certificate'] = self._removeCRLF(pkcs1Certificate)
result = self._transaction(self._verifyURL, parameters)
if not result[u'Success']:
raise Exception("Verify buffer failed (%s)" % result)
return result[u'Data']
def getCertificates(self):
result = self._transaction(
self._getCertificatesURL,
dict(Username=self._username, Password=self._password))
if not result[u'Success']:
raise Exception("Getting certificates failed (%s)" % result)
return result[u'Data'][u'Certificates']
def serverInfo(self):
result = self._transaction(self._serverInfoURL, {})
if not result[u'Success']:
raise Exception("Getting server info failed (%s)" % result)
return result[u'Data']
def _transaction(self, url, parameters):
request = urllib2.Request(url, json.dumps(parameters), self._HEADERS)
connection = urllib2.urlopen(request)
try:
return json.loads(connection.read())
finally:
connection.close()
def _isBase64(self, data):
valid = string.lowercase + string.uppercase + string.digits + "+/=\r\n"
return [x for x in data if x not in valid] == []
def _removeCRLF(self, s):
return s.replace("\r\n", "")
if __name__ == "__main__":
import pprint
USERNAME = "" # fill this
PASSWORD = "" # fill this
VALUE = "ABCDEFG"
client = Client(username=USERNAME, password=PASSWORD)
print "SERVER INFO:"
pprint.pprint(client.serverInfo())
print "USER CERTIFICATES:"
certificates = client.getCertificates()
pprint.pprint(certificates)
firstCertificate = certificates[0]['Certificate']
print "Signing bytes using pkcs#7:"
signedWith7 = client.signBytes(VALUE)
print "Signing bytes using pkcs#1:"
signedWith1 = client.signBytes(VALUE, pkcs1=True)
print "Signing hash using pkcs#7:"
signedHashWith7 = client.signUsingHash(VALUE)
print "Signing hash using pkcs#1:"
signedHashWith1 = client.signUsingHash(VALUE, pkcs1=True)
assert signedWith1 == signedHashWith1, \
"Expected signature from hash to be equals to be identical"
print "Verify bytes using pkcs#7:"
result = client.verifyBytes(VALUE, signedWith7)
assert result[u'IsValid'], "Expected to be valid"
pprint.pprint(result)
print "Verify bytes using pkcs#1:"
result = client.verifyBytes(VALUE, signedWith1, pkcs1Certificate=firstCertificate)
assert result[u'IsValid'], "Expected to be valid"
pprint.pprint(result)
print "Verify hash using pkcs#7:"
result = client.verifyUsingHash(VALUE, signedWith7)
assert result[u'IsValid'], "Expected to be valid"
pprint.pprint(result)
print "Verify hash, using hash signature, using pkcs#7:"
result = client.verifyUsingHash(VALUE, signedHashWith7)
assert result[u'IsValid'], "Expected to be valid"
pprint.pprint(result)
print "Verify hash using pkcs#1:"
result = client.verifyUsingHash(VALUE, signedWith1, pkcs1Certificate=firstCertificate)
assert result[u'IsValid'], "Expected to be valid"
pprint.pprint(result)
print "All tests passed"