Skip to content
Adrien Béraud edited this page Mar 29, 2024 · 5 revisions

OpenDHT provides a simple, easy to use C++ cryptographic API built on top of GnuTLS.

The crypto API is exposed in the dht::crypto C++ namespace.

dht::crypto::PrivateKey

crypto::PrivateKey represents an RSA private key.

Constructor allows to import an existing PEM or DER encoded private key:

PrivateKey(const std::vector<uint8_t>& key, const std::string& password = {});

A new RSA key pair can be generated using PrivateKey::generate():

static PrivateKey PrivateKey::generate(unsigned key_length = 4096);

The corresponding public key can be obtained using getPublicKey():

PublicKey PrivateKey::getPublicKey() const;

A private key can sign data:

/** Returns the signature of 'data'. */
std::vector<uint8_t> PrivateKey::sign(const std::vector<uint8_t>& data) const;

A private key can decrypt data previously encrypted with the corresponding public key:

std::vector<uint8_t> PrivateKey::decrypt(const std::vector<uint8_t>& encrypted_data) const;

dht::crypto::PublicKey

crypto::PublicKey represents an RSA public key.

Constructor allows to import an existing PEM or DER encoded public key:

PublicKey(const std::vector<uint8_t>& pk);

A public key can encrypt data:

std::vector<uint8_t> PublicKey::encrypt(const std::vector<uint8_t>& data) const;

A public key can check data signed by the corresponding private key:

bool PublicKey::checkSignature(const std::vector<uint8_t>& data, const std::vector<uint8_t>& signature) const;

Example use of crypto::PrivateKey and crypto::PublicKey:

auto key = dht::crypto::PrivateKey::generate();
auto public_key = key.getPublicKey();

std::vector<uint8_t> data {5, 10};
std::vector<uint8_t> signature = key.sign(data);

// check signature
assert(public_key.checkSignature(data, signature));

// encrypt data
std::vector<uint8_t> encrypted = public_key.encrypt(data);
std::vector<uint8_t> decrypted = key.decrypt(encrypted);
assert(data == decrypted);

dht::crypto::Certificate

crypto::Certificate represents an x509 certificate.

Constructors allows to import an existing PEM or DER encoded certificate:

Certificate(const uint8_t* dat, size_t dat_size);
Certificate(const std::vector<uint8_t>& crt);

A new certificate can be generated using generate():

static Certificate
Certificate::generate(const PrivateKey& key, const std::string& name, Identity ca = {});

AES encryption

OpenDHT provides 128, 192 or 256 bits AES-GCM encryption. Using a raw key of 16, 24 or 32 bytes:

std::vector<uint8_t> crypto::aesEncrypt(const std::vector<uint8_t>& data, const std::vector<uint8_t>& key);
std::vector<uint8_t> crypto::aesDecrypt(const std::vector<uint8_t>& encrypted_data, const std::vector<uint8_t>& key);

Using a text password. The password is stretched and a generated salt appended to the encrypted data.

std::vector<uint8_t> crypto::aesEncrypt(const std::vector<uint8_t>& data, const std::string& password);
std::vector<uint8_t> crypto::aesDecrypt(const std::vector<uint8_t>& encrypted_data, const std::string& password);

Key stretching

Key stretching is the process of making a text password more secure against a brute force attack by increasing the time it takes to test each possible key.

Key stretching in OpenDHT makes use of argon2i (mono-threaded, 65536 rounds, 64 MiB). If an empty salt is provided, the salt parameter is filled with a generated salt. The same salt and password must be used to get the same output. The salt can be transmitted in clear.

std::vector<uint8_t> crypto::stretchKey(const std::string& password, std::vector<uint8_t>& salt);