EMIP-003

cardano_error_t cardano_crypto_emip3_encrypt(const byte_t *data, size_t data_length, const byte_t *passphrase, size_t passphrase_length, cardano_buffer_t **encrypted_data)

Encrypts data using the EMIP-003 standard encryption format with password-based key derivation.

The cardano_crypto_emip3_encrypt function securely encrypts the provided data using a passphrase, following the encryption scheme outlined in EMIP-003. This method is particularly suitable for encrypting sensitive data, such as cryptographic keys, before storing them on disk.

Encryption Methodology

  1. Password-Based Key Derivation (PBKDF2):

    • Uses HMAC-SHA512 [RFC 6234] as the Pseudo-Random Function (PRF) for the derivation process.

    • A randomly generated 32-byte salt is applied.

    • Iterates 19,162 times (as defined in EMIP-003) to strengthen the key derivation process against brute-force attacks.

    • The derived key size is 32 bytes.

  2. ChaCha20Poly1305 Encryption:

    • Encrypts the data using ChaCha20 [RFC 8439] with the derived key.

    • A randomly-initialized 12-byte nonce is used for the encryption process.

    • Poly1305 ensures authenticity and integrity of the encrypted data, providing AEAD (Authenticated Encryption with Associated Data).

    • An empty AAD (Additional Authenticated Data) is used.

    • The output includes the MAC (Message Authentication Code) for data verification.

  3. Output Format:

    • The resulting encrypted data is concatenated as follows:

      • The 32-byte salt.

      • The 12-byte nonce.

      • The 16-byte MAC.

      • The encrypted data.

Example:

// Encrypt sensitive data using a passphrase
const byte_t* data = (const byte_t*)"My secret data";
const size_t data_len = strlen((const char*)data);
const byte_t* passphrase = (const byte_t*)"MyStrongPassphrase";
const size_t passphrase_len = strlen((const char*)passphrase);
cardano_buffer_t* encrypted_data = NULL;

// Encrypt the data
cardano_error_t result = cardano_crypto_emip3_encrypt(data, data_len, passphrase, passphrase_len, &encrypted_data);

if (result == CARDANO_SUCCESS)
{
  printf("Encryption successful! Encrypted data length: %zu\n", encrypted_data->size);

  cardano_buffer_unref(encrypted_data);
}
else
{
  printf("Encryption failed!\n");
}

See also

EMIP-003 for full specification details.

Note

The passphrase and sensitive data are securely wiped from memory after encryption is completed.

Parameters:
const byte_t *data

[in] The raw data to be encrypted.

size_t data_length

[in] The length of the raw data.

const byte_t *passphrase

[in] The user-provided passphrase used for deriving the encryption key.

size_t passphrase_length

[in] The length of the passphrase.

cardano_buffer_t **encrypted_data

[out] A pointer to a buffer where the resulting encrypted byte array will be stored. The caller is responsible for managing this buffer and securely wiping it after use.

Returns:

cardano_error_t An error code indicating success or failure.


cardano_error_t cardano_crypto_emip3_decrypt(const byte_t *encrypted_data, size_t encrypted_data_length, const byte_t *passphrase, size_t passphrase_length, cardano_buffer_t **data)

Decrypts data that was encrypted using the EMIP-003 standard encryption format.

The cardano_crypto_emip3_decrypt function securely decrypts the provided encrypted_data using a passphrase, following the decryption scheme outlined in EMIP-003. This function expects data that was encrypted using the cardano_crypto_emip3_encrypt function and will return the original data in its raw form.

Decryption Methodology

  1. Password-Based Key Derivation (PBKDF2):

    • The decryption process regenerates the key using PBKDF2, with the same parameters that were used during encryption.

    • HMAC-SHA512 is used as the Pseudo-Random Function (PRF) for key derivation, and the salt is extracted from the provided encrypted_data.

    • 19,162 iterations are used to produce a 32-byte key.

  2. ChaCha20Poly1305 Decryption:

    • The derived key is used to decrypt the data, which is extracted from the encrypted_data.

    • The 12-byte nonce and the 16-byte MAC are also extracted from the encrypted data.

    • ChaCha20Poly1305 is then used to decrypt and authenticate the data, ensuring both confidentiality and integrity.

  3. Output Format:

    • The decrypted data is returned as a buffer, with the size of the original data before encryption.

Example:

const byte_t*     encrypted_data     = ...; // Encrypted data from the encryption function
const size_t      encrypted_data_len = ...; // Length of the encrypted data
const byte_t*     passphrase         = (const byte_t*)"MyStrongPassphrase";
const size_t      passphrase_len     = strlen((const char*)passphrase);
cardano_buffer_t* decrypted_data     = NULL;

// Decrypt the data
cardano_error_t result = cardano_crypto_emip3_decrypt(encrypted_data, encrypted_data_len, passphrase, passphrase_len, &decrypted_data);

if (result == CARDANO_SUCCESS)
{
  // Use the decrypted data
  ...
  // Securely wipe sensitive data from memory before freeing the buffer
  cardano_buffer_memzero(decrypted_data);
  cardano_buffer_unref(decrypted_data);
}
else
{
  // Handle decryption failure
  printf("Decryption failed!\n");
}

See also

EMIP-003 for full specification details.

Note

It is important to securely wipe sensitive data from memory after its use. Before calling cardano_buffer_unref to free the data, you must call cardano_buffer_memzero to ensure that the sensitive information is properly erased from memory, reducing the risk of exposing private data.

Parameters:
const byte_t *encrypted_data

[in] The encrypted data to be decrypted.

size_t encrypted_data_length

[in] The length of the encrypted data.

const byte_t *passphrase

[in] The user-provided passphrase used for deriving the decryption key.

size_t passphrase_length

[in] The length of the passphrase.

cardano_buffer_t **data

[out] A pointer to a buffer where the resulting decrypted byte array will be stored. The caller is responsible for managing this buffer and securely wiping it after use.

Returns:

cardano_error_t An error code indicating success or failure.