Skip to content

Latest commit

 

History

History

csharp

devolutions-crypto

[Build Status] Cryptographic library used in Devolutions products. It is made to be fast, easy to use and misuse-resistant.

Usage

Overview

The library is split into multiple modules, which are explained below.

Ciphertext

This module contains everything related to encryption. You can use it to encrypt and decrypt data using either a shared key of a keypair.

Symmetric

using Devolutions.Cryptography;

byte[] key = Managed.GenerateKey(32);

byte[] data = Utils.StringToUtf8ByteArray("somesecretdata");

byte[] encrypted_data = Managed.Encrypt(data, key, CipherVersion.Latest);

byte[] decrypted_data = Managed.Decrypt(encrypted_data, key);

Asymmetric

Here, you will need a PublicKey to encrypt data and the corresponding PrivateKey to decrypt it. You can generate them by using GenerateKeyPair or DeriveKeyPair in the Key module.

using Devolutions.Cryptography;

KeyPair keypair = Managed.GenerateKeyPair();

byte[] data = Utils.StringToUtf8ByteArray("somesecretdata");

byte[] encrypted_data = Managed.EncryptAsymmetric(data, keypair.PublicKey, CipherVersion.Latest);

byte[] decrypted_data = Managed.DecryptAsymmetric(data, keypair.PrivateKey);

Generation/Derivation

You have two ways to generate a KeyPair: Using GenerateKeyPair will generate a random one, using DeriveKeyPair will derive one from another password or key along with derivation parameters(including salt). Except in specific circumstances, you should use GenerateKeyPair.

Asymmetric keys have two uses. They can be used to encrypt and decrypt data and to perform a key exchange.

Generate Key Pair

using Devolutions.Cryptography;

KeyPair keypair = Managed.GenerateKeyPair();

DeriveKeyPair

using Devolutions.Cryptography;

Argon2Parameters parameters = Managed.GetDefaultArgon2Parameters();

KeyPair keypair = Managed.DeriveKeyPair(Utils.StringToUtf8ByteArray("thisisapassword"), parameters);

Key Exchange

The goal of using a key exchange is to get a shared secret key between two parties without making it possible for users listening on the conversation to guess that shared key.

  1. Alice and Bob each generate a KeyPair.
  2. Alice and Bob exchange their PublicKey.
  3. Alice mixes her PrivateKey with Bob's PublicKey. This gives her the shared key.
  4. Bob mixes his PrivateKey with Alice's PublicKey. This gives him the shared key.
  5. Both Bob and Alice have the same shared key, which they can use for symmetric encryption for further communications.
using Devolutions.Cryptography;

KeyPair bob_keypair = Managed.GenerateKeyPair();
KeyPair alice_keypair = Managed.GenerateKeyPair();

byte[] bob_shared = Managed.MixKeyExchange(bob_keypair.PrivateKey, alice_keypair.PublicKey);

byte[] alice_shared = Managed.MixKeyExchange(alice_keypair.PrivateKey, bob_keypair.PublicKey);

PasswordHash

You can use this module to hash a password and validate it afterward. This is the recommended way to verify a user password on login.

using Devolutions.Cryptography;

byte[] password = Utils.StringToUtf8ByteArray("somesuperstrongpa$$w0rd!");

byte[] hashed_password = Managed.HashPassword(password, 10000);

SecretSharing

This module is used to generate a key that is split in multiple Share and that requires a specific amount of them to regenerate the key.
You can think of it as a "Break The Glass" scenario. You can for example generate a key, encrypt your data and then require 3 out of the 5 administrators to decrypt the data. That data could also be an API key or password of a super admin account.

using Devolutions.Cryptography;
using System.Linq;

// You want a key of 32 bytes, split between 5 people, and a 
// minimum of 3 of these shares to regenerate the key.
byte[][] shares = Managed.GenerateSharedKey(5, 3, 32);

byte[] key = Managed.JoinShares(shares.Skip(2).ToArray());

Signature

This module is used to sign data using a keypair to certify its authenticity.

Generating Key Pairs

using Devolutions.Cryptography;
using System.Linq;

SigningKeyPair keypair = Managed.GenerateSigningKeyPair();

Signing Data

byte[] dataToSign = System.Text.Encoding.UTF8.GetBytes("some data");

byte[] signature = Managed.Sign(dataToSign, keypair);

Verifying the signature

byte[] dataToVerify = System.Text.Encoding.UTF8.GetBytes("some data");

bool valid = Managed.VerifySignature(dataToVerify, keypair.GetPublicKey(), signature);

Utils

These are a bunch of functions that can be useful when dealing with the library.

Key Generation

This is a method used to generate a random key. In almost all case, the keySize parameter should be 32.

using Devolutions.Cryptography;

byte[] key = Managed.GenerateKey(32);

Key Derivation

This is a method used to generate a key from a password or another key. Useful for password-dependant cryptography. Salt should be a random 16 bytes array if possible and iterations should be 10000 or configurable by the user.

using Devolutions.Cryptography;

byte[] key = Utils.StringToUtf8ByteArray("this is a secret password");
byte[] salt = Managed.GenerateKey(16);
uint iterations = 10000;
uint length = 32;

byte[] new_key = Managed.DeriveKey(key, salt, iterations, length);

Underlying algorithms

As of the current version:

  • Symmetric cryptography uses XChaCha20Poly1305
  • Asymmetric cryptography uses Curve25519
  • Asymmetric encryption uses ECIES
  • Key exchange uses x25519, or ECDH over Curve25519
  • Password Hashing uses PBKDF2-HMAC-SHA2-256
  • Secret Sharing uses Shamir Secret sharing over GF256