Skip to content

how to: cipher (symmetric)

amir zamani edited this page Aug 5, 2016 · 1 revision

the cipher class can do symmetric encryption/decryption:

constexpr auto algorithm = cipher_t::aes_256_cbc;

fmt::print("{}: block size: {} [bytes]\n"
           "  iv size: {} [bytes] key size: {} [bits]",
           to_string(algorithm),
           cipher::block_size(algorithm),
           cipher::iv_size(algorithm),
           cipher::key_bitlen(algorithm));

If a cipher block mode allows, the cipher class automatically breaks input data into chunks (cipher::block_size()) and frees the user from breaking/merging of input/output data:

using namespace mbedcrypto;

std::string source_plain_data = read_from_somewhere();

// encrypt and decrypt by single-shot functions
auto ciphered_buffer = cipher::encrypt(
    cipher_t::aes_256_cbc,
    padding_t::pkcs7,
    initial_vector_data,  // get iv size from cipher::iv_size()
    key_data,             // get key length in bit by cipher::key_bitlen()
    source_plain_data     // could be in any size because of cbc block mode
    );

auto decrypted_buffer = cipher::decrypt(
    cipher_t::aes_256_cbc,
    padding_t::pkcs7,
    initial_vector_data,
    key_data,
    ciphered_buffer
    );

REQUIRE( source_plain_data == decrypted_buffer );

the same API also works with QByteArray:

QTcpSocket sok;

QObject::connect(&sok, &QTcpSocket::readyRead, [this]() {
  auto ciphered = cipher::encrypt<QByteArray>(
      cipher_t::aes_256_cbc,
      padding_t::pkcs7,
      initial_vector_data, 
      key_data,            
      sok.readAll()
      );
  sok.write(ciphered_);
});

to use authenticated encryption with associated data (aka aead):

std::string the_additional_data = ...;

auto encr = cipher::encrypt_aead(
    cipher_t::aes_256_ccm,
    iv_data,
    key_data,
    the_additional_data,
    source_plain_data
    );  ///< returns a std::tuple< computed_tag, encrypted_data >


auto decr = cipher::decrypt_aead(
    cipher_t::aes_256_ccm,
    iv_data,
    key_data,
    the_additional_data,
    encr
    );  ///< returns a std::tuple< authentication_status, decrypted_data >


  REQUIRE( std::get<0>(decr) == true ); // authenticated?
  REQUIRE( std::get<1>(decr) == source_plain_data );

to reuse cipher object:

// construct and setup properties
cipher cipdec(cipher_t::aes_256_cbc);
cipdec
  .padding(padding_t::pkcs7)
  .iv(iv_data)
  .key(key_data, cipher::decrypt_mode);

// by start() / update()s / finish()
cipdec.start();
std::string decrypted_data;
while ( ... ) {
    decrypted_data += cipdec.update(read_some_encrypted_data());
}
decrypted_data += cipdec.finish();
REQUIRE( source_plain_data == decrypted_data );

// re-use the object
cipdec.start();
cipdec.update(...); // or multiple updates
cipdec.finish();

// single shot re-use
decrypted_data = cipdec.crypt(encrypted_data);

see cipher.hpp

Clone this wiki locally