pythonrsadigital-signatureazure-keyvaultpycryptodome

Verifying an Azure Key Vault signature without vault access


I sign a file with Azure Key Vault and store the signature. Then, on a machine without vault access, I would like to verify the signature with the original file, the RSA modulus and RSA public exponent which I also read from files. I've looked into the RSA and pkcs1_15 modules from PyCryptoDome, however I cant seem to pass the signature as it's a byte object, and not a PyCryptoDome hash object. I feel like I'm going about this in a convoluted way. Does anyone know the proper way to do this?

Here's a cut-down overview of my code so far:

import hashlib

from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15

from azure.identity import DefaultAzureCredential
from azure.keyvault.keys import KeyClient
from azure.keyvault.keys.crypto import SignatureAlgorithm
from azure.keyvault.certificates import CertificateClient
from azure.keyvault.secrets import SecretClient
from azure.keyvault.keys.crypto import CryptographyClient, EncryptionAlgorithm

VAULT_URL = os.environ["AZURE_VAULT_URL"]
CERTIFICATE_NAME = os.environ["AZURE_CERTIFICATE_NAME"]

credential = DefaultAzureCredential()
certificate_client = CertificateClient(vault_url=VAULT_URL, credential=credential)
key_client = KeyClient(vault_url=VAULT_URL, credential=credential)
secret_client = SecretClient(vault_url=VAULT_URL, credential=credential)

key = key_client.get_key(CERTIFICATE_NAME)
cryptography_client = CryptographyClient(key, credential=credential)

input_digest = hashlib.sha256(input_bytes).digest() # input_bytes is the file bytes

result = cryptography_client.sign(SignatureAlgorithm.rs256, input_digest)

public_key = RSA.construct((int.from_bytes(key.key.n), int.from_bytes(key.key.e)))
signature_object = pkcs1_15.new(public_key)
signature_object.verify(input_digest, result.signature)

Thank you.


Solution

  • Instead of hasing with hashlib we can instead hash with PyCryptodome's Crypto.Hash.SHA256. It's the same result, except this time it exposes the OID constant 1.2.840.113549.2..