sign_blob 使用方法

1 投票
2 回答
510 浏览
提问于 2025-04-17 12:30

我想给一些数据(叫做blob)签名,然后把这个签名发回给用户。用户该怎么验证这个签名呢?如果能有个例子,教我怎么获取公钥证书和处理这个签名就好了。

2 个回答

0

根据文档的说明,使用get_public_certificates可以获取用来验证签名的证书。

公共证书是普通的Python对象,里面有key_namex509_certificate_pem这两个属性。

sign_blob 返回一个元组,里面包含了用来签名的key_namesignature

然后,你可以使用任何加密库,通过x509证书来验证这个签名。

1

这个问题虽然是个老问题,但我还是觉得很难找到具体的例子来说明怎么做!所以我把我的解决方案发出来,希望能帮到其他想知道怎么验证sign_blog签名的人。搞笑的是,谷歌的Python页面居然没有任何例子。

这里有一个例子,展示了如何对一个数据块进行签名并验证它的签名:

但是没有任何示例。

我到处搜索后,终于在这个页面找到了一个例子。这个代码的作者是这样进行签名的:

from google.appengine.api import app_identity

def sign_blob(blob):
    """Signs a blob using current service's private key.

    Uses GAE app_identity.sign_blob function. It has a limit of 8KB on a size of
    a blob, so |blob| is hashed first (with sha512). So final signature is
    RSA+SHA256(sha512(blob)).

    Returns:
      Tuple (name of a key used, signature).
    """
    # app_identity.sign_blob is producing RSA+SHA256 signature. Sadly, it isn't
    # documented anywhere. But it should be relatively stable since this API is
    # used by OAuth2 libraries (and so changing signature method may break a lot
    # of stuff).
    return app_identity.sign_blob(hashlib.sha512(blob).digest())

同一个作者还使用了pycrypto来进行验证。这个函数叫做check_signature,在页面的底部。它工作得很好,但pycrypto看起来并没有在积极更新。

我自己想出的一个实现使用了cryptography库,这个库还在积极开发中。可以看看:

import base64

from google.appengine.api import app_identity

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.exceptions import InvalidSignature

def verify_signature(key_name, signature, data):

    # Decode the signature
    try:
        signature = base64.b64decode(signature)
    except TypeError:
        return False

    # Get the list of certificates app engine has been using
    certs = app_identity.get_public_certificates()

    # Match the key with a certificate
    x509_cert_pem = None
    for cert in certs:
        if cert.key_name == key_name:
            x509_cert_pem = cert.x509_certificate_pem
            break

    # Check that a certifcate matched
    if not x509_cert_pem:
        return False

    # Create x509 cert object
    x509_cert = load_pem_x509_certificate(x509_cert_pem, backend=default_backend())

    # Extract the public key
    public_key = x509_cert.public_key()

    # Prep the verifier
    verifier = public_key.verifier(
        signature,
        padding.PKCS1v15(),
        hashes.SHA256()
    )
    verifier.update(data)

    # No return value documented. Raises an error on mismatch
    # https://cryptography.io/en/latest/hazmat/primitives/asymmetric/interfaces/#cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext.verify # noqa
    try:
        result = verifier.verify()
    except InvalidSignature:
        return False

    return (result is None)

撰写回答