Это старый вопрос, но мне все еще трудно найти пример того, как это сделать! Поэтому я публикую свое решение на тот случай, если кто-то еще изучит, как проверить подпись от sign_blog
. Забавно, что страница Python в Google заканчивается на
Вот пример, показывающий, как подписать большой двоичный объект и проверить его подпись:
без каких-либо примеров.
После поиска я нашел один пример на этой странице . Вот как автор этого кода делает подпись:
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)