Secure Message

Secure Message is a lightweight service that can help deliver some message or data to your peer in a secure manner. It provides a simple way to protect your messages and bind them to the credentials of the communicating peers through the use of strong cryptography. It adds data confidentiality, integrity, and authenticity to your message in a single go (single function call).

Some of the features of Secure Message are: strong data encryption, message integrity and authentication, key generation (both RSA and ECC), stateless, easy-to-use API.

Secure Message assumes that peers have each other's public key that they trust. Then they can freely exchange any messages with a high level of security and little overhead.

Secure Message comes in two flavours: signed message (integrity and authenticity) and encrypted message (confidentiality, integrity, and authenticity).

Signed message

Signed message is useful for cases where you don't need data confidentiality. It allows the receiver to verify the origin and integrity of the data while still allowing intermediate nodes to process it accordingly (for example, route data based on its type).

Encrypted message

Encrypted message is useful when you need the full stack of protection for your data — in most cases, you will be using this flavour. The encrypted message currently uses Secure Cell in Seal mode for data protection.

Implementation details

As described above, Secure Message may be used in two modes:

  1. sign/verify (integrity and authenticity only) mode;
  2. encrypt/decrypt (confidentiality, integrity and authenticity; authenticity is provided through the use of EC cryptography) mode.

In sign/verify mode the message will be signed by the appropriate signature algorithm (ECDSA by default) and packed into THEMIS_SIGNED_MESSAGE_CONTAINER.

In encrypt/decrypt mode the message will be encrypted by a randomly generated symmetric key (in RSA) or derived by ECDH (in ECDSA). All the additional necessary data for encryption will be derived by Themis and packed into the THEMIS_ENCRYPTED_MESSAGE_CONTAINER.

The Secure Message interface is described in src/themis/secure_message.h.

Select the Secure Message mode by setting key parameters to themis_secure_message_wrap function. If the peer_public_key parameter is set to NULL, Secure Message will work in sign/verify mode, and the message will be signed and packed ("wrapped") into the THEMIS_SIGNED_MESSAGE_CONTAINER:

// sign message
themis_status_t themis_secure_message_wrap(const uint8_t* private_key,
                       const size_t private_key_length,
                       NULL,                             // peer_public_key
                       0,                                // peer_public_key_length
                       const uint8_t* message,
                       const size_t message_length,
                       uint8_t* wrapped_message,
                       size_t* wrapped_message_length);

If peer_public_key parameter is set to using peer's public key, Secure Message will work in encrypt/decrypt mode, and the message will be encrypted and packed ("wrapped") into the THEMIS_ENCRYPTED_MESSAGE_CONTAINER:

// encrypt message
themis_status_t themis_secure_message_wrap(const uint8_t* private_key,
                       const size_t private_key_length,
                       const uint8_t* public_key,
                       const size_t public_key_length,
                       const uint8_t* message,
                       const size_t message_length,
                       uint8_t* wrapped_message,
                       size_t* wrapped_message_length);

The unwrapping mode is activated by parsing the wrapped_message header.

NOTE: The current verify implementation doesn't signal about appending extra data to the end of a signed message and returns correct signed data, excluding the extra data at the end.

// verify or decrypt, depending on `wrapped_message` header
themis_status_t themis_secure_message_unwrap(const uint8_t* private_key,
                       const size_t private_key_length,
                       const uint8_t* public_key,
                       const size_t public_key_length,
                       const uint8_t* wrapped_message,
                       const size_t wrapped_message_length,
                       uint8_t* message,
                       size_t* message_length);