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 signaturesseckey_sign
a private key in an asymmetric keypair used for cryptographic signaturespubkey_encrypt
for a public key in an asymmetric keypair used for encryptionseckey_encrypt
for a private key in an asymmetric keypair used for encryptionsignature
for cryptographic signaturesencrypted_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.