Certificates

The certificates module contains functions dealing with X.509 public key certificates.

The functions request_cert and verify_challenge are used during the challenge-response protocol when one wants to obtain a public key certificate from the PV080 Certificate Authority.

The function fetch_cert can be used to obtain a certificate of any user, and the signature in any certificate can be verified using verify_cert_signature

pv080_crypto.certificates.verify_cert_signature(ca_public_key: RSAPublicKey, cert: Certificate) bool[source]

Verifies whether a given certificate was signed by the Certificate Authority whose public key is provided.

Parameters:
  • ca_public_key – The public key of the Certificate Authority, used to verify the signature.

  • cert – The certificate in which the signature should be verified.

Returns:

True if cert was signed with the private key corresponding to ca_public_key, False otherwise.

Example:

>>> from pv080_crypto import verify_cert_signature, fetch_cert, load_cert 
>>> ca_cert = load_cert("pv080-root.pem")                                 
>>> ca_public_key = ca_cert.public_key()                                  
>>> cert = fetch_cert(410390)                                             
>>> print(verify_cert_signature(ca_public_key, cert))                     
pv080_crypto.certificates.request_cert(csr: CertificateSigningRequest) Tuple[str, bytes] | None[source]

Requests a certificate from the PV080 Server CA using a provided certificate signing request.

Parameters:

csr – The Certificate Signing Request (created with the create_csr function).

Returns:

None if unsuccessful, a challenge sent by the CA otherwise.

The challenge is a pair of the following two elements:

  • path is a random hexadecimal string specifying a path to a file. To prove that you are, indeed, the person with xlogin, you must create a file at this path on your aisa web server.

    (Since only you have the access to your Aisa web server, this counts as a proof of your identity.)

  • nonce are random bytes. By signing this nonce, you prove that you hold the private key corresponding to the public key in the CSR.

Example:

>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> from pv080_crypto import request_cert, create_csr
>>> private_key = rsa.generate_private_key(65537, 2048)
>>> public_key = private_key.public_key()
>>> csr = create_csr(private_key, "xzacik", 485305)
>>> path, nonce = request_cert(csr)                  
pv080_crypto.certificates.verify_challenge(nonce: bytes, signed_nonce: bytes) bool[source]

Sends a request to the PV080 Server CA asking to verify the completion of a challenge.

The CA verifies 3 things:

  • That the received nonce was previously issued as a challenge.

  • That the received signed_nonce was signed by the private key of the challenged entity.

  • That the entity created a file on the Aisa web server according to the challenge.

When the verification succeeds, the CA publishes the certificate of the challenged entity which can then be downloaded using fetch_cert.

Parameters:
  • nonce – The nonce to be signed with the private key of the challenged entity.

  • signed_nonce – The signature of the nonce.

Returns:

True if verified successfully, False otherwise.

Example:

>>> from pv080_crypto import request_cert, create_signature, verify_challenge 
>>> # Assume `private_key` and `csr` are already created                      
>>> path, nonce = request_cert(csr)                                           
>>> signed_nonce = create_signature(private_key, nonce)                       
>>> # The `~/public_html/<path>` must be present on Aisa                      
>>> verify_challenge(nonce, signed_nonce)                                     
pv080_crypto.certificates.fetch_cert(uco: int) Certificate | None[source]

Fetches a certificate for a given UCO from the PV080 server.

Parameters:

uco – The UČO of the person whose certificate is going to be fetched.

Returns:

The certificate from of the person with uco, None if no such certificate is found.

Example:

>>> from pv080_crypto import fetch_cert 
>>> cert = fetch_cert(410390)