Overview

Cryptography in MUFL uses the specialized domain CRYPTO_ELEMENT. Values of this domain represent any cryptographic data, including keys, signatures, and encrypted messages.

cryptographic hashes use domain HASH_CODE.

MUFL is designed to be able to use a wide range of cryptography primitives from third-party library implementations. The language is designed to support multiple encryption schemes, multiple signing schemes, and so on.

Because different schemes expect different types of keys and encryption formats, and in order to support runtime safety of cryptographic data (for example, so it is impossible to pass the wrong type of key to an encryption function), the CRYPTO_ELEMENT domain contains, in addition to the data itself, an identifier for the cryptography scheme for which the data is suitable and the kind of data represented.

Each kind of data has an associated MUFL data subtype of the crypto data type. These kinds of data are currently supported (and additions are expected in the future):

  • pubkey_sign for a public key in an asymmetric keypair used for cryptographic signatures
  • seckey_sign a private key in an asymmetric keypair used for cryptographic signatures
  • pubkey_encrypt for a public key in an asymmetric keypair used for encryption
  • seckey_encrypt for a private key in an asymmetric keypair used for encryption
  • signature for cryptographic signatures
  • encrypted_data for encrypted data

To determine or verify the kind of data in your specific use cases, use _crypto_get_element_kind <crypto_data>, which returns one of the string values listed above.

Cryptography Schemes

There are many ways to perform encryption and signing and many different implementations of these pritimives. A cryptography scheme is a grouping of primitives by their implementation. For example, the current implementation uses a cryptography scheme implemented by the libsodium library and is identified as cryptography scheme 1. When invoking cryptography functions, it is often required to pass the scheme identifier to let the engine know which specific implementation to use. The implementation checks that the data passed to it matches the scheme it expects.

Here is an example that tests encryption and decryption using a cryptography scheme 1:

// generate the keypair belonging to the originator of the encrypted message
// parameter is the scheme ID. Currently only number '1' is supported. 
my_keypair = _crypto_construct_encryption_keypair /* schemeID = */ 1. 
her_keypair = _crypto_construct_encryption_keypair /* schemeID = */ 1. // addressee keypair

binary = _string_to_binary "hello_world". // encryption only works on binary values

// encrypt message
// the system determines the encryption scheme from the scheme id of the keys. 
encrypted_message = _crypto_encrypt_message (my_keypair $secret_key) (her_keypair $public_key) binary. 

_print "ENCRYPTED=" encrypted_message "\n". 

// decrypt message
decrypted_message = _crypto_decrypt_message (her_keypair $secret_key) (my_keypair $public_key) encrypted_message. // same

// conver binary into a string
msg1 = _binary_as_ascii_string decrypted_message. 
_assert (msg1 == "hello_world").

Printed for the encrypted message:

ENCRYPTED=|SX1-ENCRYPTED_DATA|2B0601006000000032E6DA756FA4F44BAAE4B9A0BE28A239CC230FB25FDC0D24A8C9965A85C6AD4C43908D96CD691186A8812AD1C2B2B9CA07CBB77A7EF0E27498BF1C0644346E39640E8C1F3ABD968BF97E359F4F6A01C21C280DD4423C0FB703ACCB2267A9061C

Cryptography Functions

Inspection

_crypto_get_scheme_id

Usage:

_crypto_get_scheme_id <crypto_element>

Returns integer value that represents the ID of the cryptography scheme to which the supplied data belongs.

_crypto_get_element_kind

Usage:

_crypto_get_element_kind <crypto_element>

Returns a string from the set PUBKEY_SIGN, SECKEY_SIGN, PUBKEY_ENCRYPT, SECKEY_ENCRYPT, SIGNATURE, ENCRYPTED_DATA.

Other return values may be added in the future

_crypto_default_scheme_id

Usage:

_crypto_default_scheme_id(). 

Returns the ID of the default crypto scheme for encryption and signing.

_crypto_scheme_id_valid_range

Usage:

_crypto_scheme_id_valid_range(). 

Returns an integer-valued dictionary with elements “min” and “max”. The return value indicates the valid range of scheme identifiers. Current both “min” and “max” are 1.

_crypto_element_validate

Usage:

_crypto_element_validate <crypto_element> <SchemeID> <ElementKind>

Performs all checks to ensure that the data passed to the function is valid, represents the given kind of data, and corresponds to the given scheme.

_crypto_get_key_id

Key ID is a binary value that serves as an identifier for a cryptographic key. Public and private keys from the same keypair have the same Key ID. Additionally, this function can be invoke on any crypto element (including signatures and encrypted envelopes) to determine the key id of the signing or encryption key that has been used.

Usage:

_crypto_get_key_id <any_crypto_element>. 

Returns a binary value.

_crypto_get_key_id_target

When invoked on ENCRYPTED_DATA, the _crypto_get_key_id function returns the key ID of the sender’s key. To determine the key ID of the recipient’s key, use

_crypto_get_key_id_target <encrypted_envelope>. 

This function is valid only for crypto elements of type ENCRYPTED_DATA.

Cryptographic signing

_crypto_construct_signing_keypair

Usage:

_crypto_construct_signing_keypair <schemeID>. 

Returns a dictionary with two elements: “public_key” and “secret_key” that can be used to generate and verify cryptographic signatures.

_crypto_sign_hash

Used to sign a hash value. Usage:

_crypto_sign_hash <hash_code> <secret_key>. 

Returns a crypto element of type SIGNATURE.

_crypto_verify_hash_signature

Used to verify a signature. Usage:

_crypto_verify_hash_signature <hash> <signature> <public_key>. 

Returns TRUE if signature is correct or NIL if the signature verification failed. If any of the data passed to the function is invalid, the current transaction is aborted.

Encryption/Decryption

_crypto_construct_encryption_keypair

Usage:

_crypto_construct_encryption_keypair <schemeID>. 

Returns a dictionary with two elements: “public_key” and “secret_key” that can be used to encrypt and decrypt data, respectively.

_crypto_encrypt_message

Encrypts a message for a given addressee, which is signed by the private key of the sender. Usage:

_crypto_encrypt_message <sender_secret_key> <recipient_public_key> <binary_message>. 

Returns a ENCRYPTED_DATA crypto element. The crypto scheme is implied by the keys.

_crypto_decrypt_message

Decrypts a message and verifies the sender.

Usage:

_crypto_decrypt_message <recievers_secret_key> <sender_public_key> <encrypted_message>. 

Returns a binary value representing the decrypted message. Abort the transaction on any error, including a mismatch in the sender’s signature.