Asymmetric cryptography

The asymmetric module defines the functions for Asymmetric Cryptography or sometimes referred to as Public Key Cryptography. The functions publish_key and fetch_key manage publishing and retrieving of the public key to the PV080 server. They allow you to share your public key and retrieve the keys of other students.

For asymmetric cryptography we are using the Rivert-Shamir-Adleman (RSA) cryptosystem. The functions for encryption and decryption are rsa_encrypt and rsa_decrypt.

The asymmetric nature of RSA allows for the definition of digital signatures as well, therefore we have the function create_signature for creating the digital signature and verify_signature for verifying it.

All functions in the module work with RSA keys from the cryptography module, i.e. rsa.RSAPrivateKey and rsa.RSAPublicKey. To generate an RSA key pair, use the function rsa.generate_private_key and the member function rsa.RSAPrivateKey.public_key:

>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
>>> public_key = private_key.public_key()
pv080_crypto.asymmetric.publish_key(uco: int, key: RSAPublicKey) str[source]

Publishes the key under the uco to https://pv080.fi.muni.cz/msg server, where it is readable by anyone on the internet.

Parameters:
  • uco – The UČO of the owner of the key.

  • key – The RSA public key of the owner.

Returns:

The status message of the result of this API call to the server.

Example:

>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
>>> public_key = private_key.public_key()
>>> publish_key(uco=408788, key=public_key)
'overwritten'
pv080_crypto.asymmetric.fetch_key(uco: int) RSAPublicKey | None[source]

Fetches the public key associated with the uco from https://pv080.fi.muni.cz/msg.

Parameters:

uco – The UČO of the party we want to communicate with.

Returns:

The rsa.RSAPublicKey corresponding to uco if found, otherwise None.

Example:

>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
>>> public_key = private_key.public_key()
>>> publish_key(uco=408788, key=public_key)
'overwritten'
>>> assert isinstance(fetch_key(uco=408788), rsa.RSAPublicKey)
pv080_crypto.asymmetric.rsa_encrypt(key: RSAPublicKey, plaintext: bytes) bytes[source]

Uses RSA public key to encrypt the plaintext.

Parameters:
  • key – The RSA public key to use for the encryption.

  • plaintext – The plaintext bytes to be encrypted.

Returns:

The ciphertext bytes.

Example:

>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
>>> public_key = private_key.public_key()
>>> ciphertext = rsa_encrypt(key=public_key, plaintext=b"hello world")
pv080_crypto.asymmetric.rsa_decrypt(key: RSAPrivateKey, ciphertext: bytes) bytes[source]

Use RSA private key to decrypt the ciphertext.

Parameters:
  • key – The RSA private key to use for the decryption.

  • ciphertext – The ciphertext bytes to be decrypted.

Returns:

The plaintext bytes.

Example:

>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
>>> public_key = private_key.public_key()
>>> ciphertext = rsa_encrypt(key=public_key, plaintext=b"hello world")
>>> plaintext = rsa_decrypt(key=private_key, ciphertext=ciphertext)
>>> assert b"hello world" == plaintext
pv080_crypto.asymmetric.create_signature(private_key: RSAPrivateKey, data: bytes) bytes[source]

Use the RSA private_key to digitally sign the data.

Parameters:
  • private_key – The RSA private key to be used for signing.

  • data – The data to be signed.

Returns:

The bytes of the signature.

Example:

>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
>>> public_key = private_key.public_key()
>>> signature = create_signature(private_key=private_key, data=b"a contract contents")
pv080_crypto.asymmetric.verify_signature(public_key: RSAPublicKey, data: bytes, signature: bytes) bool[source]

Verify that the signature of data was signed using the RSAPrivateKey corresponding to public_key.

Parameters:
  • public_key – The RSAPublicKey to be used for the verification.

  • data – The data that were signed.

  • signature – The bytes of the signature.

Returns:

True if the signature is a valid, False otherwise.

Example:

>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
>>> public_key = private_key.public_key()
>>> data = b"the contract contents"
>>> signature = create_signature(private_key=private_key, data=data)
>>> assert verify_signature(public_key=public_key, data=data, signature=signature)