0

I'm writing code to retrieve certificate (as key, cert) from Azure Key Vault. The code runs perfectly when i remove the password from the certificate. How can i make it work with a password for example: abc()^WER123. I've already tried several methods for decoding the password, transforming to bytes, using hashes.SHA256 as kdf algorithm. Nothing works.. It gives me this error:

"ValueError: Invalid password or PKCS12 data"

Here my latest code:

import base64
from azure.identity import ClientSecretCredential
from azure.keyvault.certificates import CertificateClient
from azure.keyvault.secrets import SecretClient
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.serialization import pkcs12


def get_keyCert_fromKeyVault():
    TENANT_ID = ''
    CLIENT_ID = ''
    CLIENT_SECRET = ''

    KEYVAULT_NAME = ''
    KEYVAULT_URI = f"https://{KEYVAULT_NAME}.vault.azure.net/"

    credential = ClientSecretCredential(
        tenant_id=TENANT_ID,
        client_id=CLIENT_ID,
        client_secret=CLIENT_SECRET
    )
    
    #get certificate from vault
    certificate_client = CertificateClient(vault_url=KEYVAULT_URI, credential=credential)
    certificate = certificate_client.get_certificate("cert_name")

    #get certificate from secret id of the cert.
    secret_client = SecretClient(vault_url=KEYVAULT_URI, credential=credential)
    certificate_secret = secret_client.get_secret(name=certificate.name)
    
    cert_bytes = base64.b64decode(certificate_secret.value)

    password_provided =b'abc()^WER123'
    
    salt = os.urandom(16)
     
    kdf = PBKDF2HMAC(
            algorithm=hashes.SHA1(),
            length=64,
            salt=salt,
            iterations=480000,
            backend=default_backend()
        )
    password = base64.urlsafe_b64encode(kdf.derive(password_provided))
    
    private_key, public_certificate, additional_certificates = 
    pkcs12.load_key_and_certificates(
        data=cert_bytes,
        password=password
    )
    return private_key, public_certificate

Please Help!

Thanks in advance

Nat
  • 81
  • 1
  • 6
  • I think the certificate content you can download as secret is not protected by a password (even when you used a password for the import), so loading it with a password is expected to complain about wrong password. – Esta Nagy Feb 05 '23 at 06:42
  • The certificate definitely has a password – Nat Feb 05 '23 at 07:40
  • Interesting! I thought it didn't based on this: https://learn.microsoft.com/en-us/azure/key-vault/certificates/how-to-export-certificate?tabs=azure-cli#export-stored-certificates – Esta Nagy Feb 05 '23 at 09:48
  • I have a certificate which was created with a password and uploaded to azure key vault certificates with the same password. – Nat Feb 05 '23 at 11:11
  • That is still matching what I have seen: "Key Vault doesn't save the associated password. When you export the certificate, the password is blank." Based on this it is removed during the upload. – Esta Nagy Feb 05 '23 at 14:57

1 Answers1

0

I have followed the below steps to retrieve the certificate from the Azure key vault.

Step 1: Create Azure key vault and upload certificates to it. enter image description here

enter image description here

Step 2: Setup python and run below code to retrieve certificates.

import os
import base64
import requests
import json

KEY_VAULT_URL = "https://<keyvault-name>.vault.azure.net"
TENANT_ID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
CLIENT_ID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
CLIENT_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
CERT_NAME = "testcert010203"

def get_access_token():
    auth_url = f"https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token"
    auth_data = {
        "client_id": CLIENT_ID,
        "client_secret": CLIENT_SECRET,
        "grant_type": "client_credentials",
        "scope": f"https://vault.azure.net/.default"
    }

    response = requests.post(auth_url, data=auth_data)
    response.raise_for_status()

    return response.json()["access_token"]


def get_certificate(access_token):
    """Get the certificate from Azure Key Vault."""
    cert_url = f"{KEY_VAULT_URL}/certificates/{CERT_NAME}?api-version=7.0"

    headers = {
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json"
    }

    response = requests.get(cert_url, headers=headers)
    response.raise_for_status()

    return response.json()


if __name__ == "__main__":
    access_token = get_access_token()
    cert_data = get_certificate(access_token)

    print("Certificate data:")
    print(json.dumps(cert_data, indent=4))

Step 3: Verify the certificate in the output. enter image description here

enter image description here

Sourav
  • 814
  • 1
  • 9