2

プロジェクトに統合するための POC として、Signature API (JSON) を使用して小さなバッファーに署名しようとしています。CoSign トライアル開発者アカウント サーバーを使用しています。署名は正常に作成されましたが、バッファーを検証しようとすると、応答に次の (あまり役に立たない) エラーが含まれています。

{u'ErrData': {u'Code': -24,
          u'InnerCode': -1878850959,
          u'Message': u'Failed to verify buffer.',
          u'Module': u'VerifyBuffer'},
 u'Success': False}

私はこのページのドキュメントに従っています:

http://docs.arx.com/CoSign_APIs/doc_v7.1/Default.htm#doc_7.1/Verify Buffer.htm#_Toc398808255%3FTocPath%3DCoSign%2520Signature%7CAPI%7CSigning%2520and%2520Verifying%7C_____4

そして、Pythonでコードを添付しています(ユーザー名とパスワードは消去されています)

import urllib2
import hashlib
import xml.dom.minidom
import base64
import pprint
import json


class Client:
    SIGN_URL = 'https://prime.cosigntrial.com:8081/sapiws/SignBuffer'
    VERIFY_URL = 'https://prime.cosigntrial.com:8081/sapiws/VerifyBuffer'
    GET_CERTS_URL = 'https://prime.cosigntrial.com:8081/sapiws/UserCertificatesGet'
    HEADERS = {'Content-Type': 'application/json; charset=utf-8'}

    def __init__(self, username, password):
        self._username = username
        self._password = password

    def signBytes(self, bytes):
        obj = dict(
            Username=self._username, Password=self._password,
            BufferToSign=base64.b64encode(bytes))
        return self._transaction(obj)

    def verifyBytes(self, bytes, signature):
        obj = dict(
            BufferToSign=base64.b64encode(bytes), Signature=signature)
        return self._transaction(obj, url=self.VERIFY_URL)

    def getCertificates(self):
        return self._transaction(dict(Username=self._username, Password=self._password), url=self.GET_CERTS_URL)

    def signUsingHash(self, bytes):
        digest = hashlib.sha512(bytes).digest()
        obj = dict(
            Username=self._username, Password=self._password,
            BufferToSign=base64.b64encode(digest),
            BufferHash=True, HashAlg="Sha512")
        return self._transaction(obj)

    def verifyUsingHash(self, bytes, signature):
        digest = hashlib.sha512(bytes).digest()
        obj = dict(
            BufferToSign=base64.b64encode(digest), Signature=signature,
            BufferHash=True)
        return self._transaction(obj, url=self.VERIFY_URL)

    def _transaction(self, message, url=SIGN_URL):
        print "Y"*100
        pprint.pprint(message)
        request = urllib2.Request(url, json.dumps(message))
        connection = urllib2.urlopen(request)
        try:
            return json.loads(connection.read())
        finally:
            connection.close()


client = Client(username="", password="")
value = "ABCDEFG"
response1 = client.signBytes(value)
print "X"*100
print response1
verified1 = client.verifyBytes(value, response1[u'Data']    [u'Signature'])
print "Z"*100
pprint.pprint(verified1)

私も BufferHash 引数を使用しようとし、自分でハッシュを計算しましたが、同じエラーが発生します。

4

3 に答える 3

2

Almog と ALX に感謝します。あなたの回答が役に立ちました。残念ながら、私はあなたの答えに賛成票を投じることができません.十分なスタックオーバーフローの評判がありません.

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"
于 2015-02-19T10:09:46.187 に答える
2

コードを適切に実行するために必要なことは、次のとおりです。

  1. 定義済みのリクエスト ヘッダーをリクエスト自体に渡します。

    urllib2.Request(url, json.dumps(message), self.HEADERS)
    
  2. 返された署名の base64 エンコード データには冗長な \r\n 文字が含まれていることに注意してください (これは既知の問題であり、今後のリリースで修正される予定です)。データを検証操作に渡す前に、これらの文字を削除するだけです。例えば-

    client.verifyBytes(value, response1[u'Data'][u'Signature'].replace("\r\n", ""))
    
于 2015-02-18T17:41:33.223 に答える