---
title: "Applied Cryptography for Developers"
description: "A comprehensive guide to implementing secure cryptographic primitives in software applications"
keywords: ["cryptography", "encryption", "hashing", "key management", "security"]
category: "security"
---

AES-256-GCM is a widely adopted authenticated encryption algorithm that provides both confidentiality and integrity for data. It uses a 256-bit key and the Galois/Counter Mode (GCM) of operation to encrypt and authenticate messages. The AES-256-GCM algorithm is available in many cryptographic libraries, such as OpenSSL 1.1.1, .NET's System.Security.Cryptography.AesGcm class, and the crypto_aead_aes256gcm_* functions in libsodium 1.0.18. When using AES-256-GCM, it's important to generate a unique 96-bit initialization vector (IV) for each message and to securely manage the 256-bit encryption key.

RSA and Elliptic Curve Digital Signature Algorithm (ECDSA) are two popular public-key cryptography algorithms used for digital signatures. RSA-2048 is a widely used RSA configuration, while ECDSA with the secp256r1 (NIST P-256) curve is a common ECDSA implementation. The choice between RSA and ECDSA depends on factors such as key size, performance, and quantum-resistance. RSA-2048 keys can be generated using the openssl genrsa command, while ECDSA secp256r1 keys can be generated with the openssl ecparam and openssl ec commands.

Argon2id is a memory-hard password hashing function recommended by the Password Hashing Competition. It is designed to be resistant to GPU-based and ASIC-based attacks. Argon2id can be configured with parameters such as the number of iterations, memory usage, and parallelism. The Argon2id algorithm is available in many cryptographic libraries, including the Crypto.Password.Argon2 module in .NET Core 3.1 and the crypto_pwhash_argon2id function in libsodium 1.0.18.

HKDF (HMAC-based Extract-and-Expand Key Derivation Function) is a standardized key derivation function that can be used to derive multiple cryptographic keys from a single input key or password. HKDF is specified in RFC 5869 and is available in many cryptographic libraries, such as the Crypto.KDF.HKDF module in .NET Core 3.1 and the crypto_kdf_* functions in libsodium 1.0.18. HKDF can be used to derive keys for various purposes, such as encrypting data with AES-256-GCM or signing messages with RSA or ECDSA.

Envelope encryption is a technique that combines symmetric and asymmetric cryptography to provide efficient and secure data encryption. In this approach, a randomly generated symmetric key is used to encrypt the data, and the symmetric key is then encrypted using a public-key algorithm, such as RSA or ECDSA. This allows for efficient bulk data encryption with AES-256-GCM while still leveraging the key management and non-repudiation benefits of public-key cryptography.

Libsodium's sealed boxes provide a high-level abstraction for public-key encryption and authentication. Sealed boxes use the Curve25519, XSalsa20, and Poly1305 algorithms to provide authenticated encryption with a single function call. The crypto_box_seal and crypto_box_open_seal functions in libsodium 1.0.18 handle the key exchange, encryption, and authentication, allowing developers to focus on the application-level logic rather than the cryptographic details.

Constant-time comparison is a technique used to mitigate timing side-channel attacks when comparing sensitive values, such as cryptographic keys or authentication tokens. By ensuring that the comparison time is independent of the input values, constant-time comparison prevents attackers from inferring information about the compared values based on the time it takes to perform the comparison. Many cryptographic libraries, including OpenSSL 1.1.1 and libsodium 1.0.18, provide constant-time comparison functions, such as CRYPTO_memcmp and sodium_memcmp, that should be used instead of the standard memcmp function.

Cryptographically Secure Pseudo-Random Number Generators (CSPRNGs) are essential for generating high-quality random numbers used in cryptographic operations, such as key generation, nonces, and salts. Operating system-provided CSPRNGs, such as /dev/urandom on Unix-like systems or the CryptGenRandom function on Windows, should be used instead of standard pseudo-random number generators. Cryptographic libraries like OpenSSL 1.1.1 and libsodium 1.0.18 provide functions like RAND_bytes and randombytes_buf to access the system CSPRNG in a platform-independent way.When using AES-256-GCM for authenticated encryption, it's important to properly handle the Initialization Vector (IV) and the Additional Authenticated Data (AAD). The IV should be unique for each message encrypted with the same key, and it can be generated using a secure random number generator like the one provided by the operating system. The AAD is additional data that is authenticated but not encrypted, such as message headers or metadata. The crypto_aead_aes256gcm_encrypt and crypto_aead_aes256gcm_decrypt functions in libsodium 1.0.18 allow you to specify the IV and AAD parameters.

For RSA key generation, the openssl genrsa command can be used to generate a private key with a specified modulus size, e.g., openssl genrsa -out rsa_private_key.pem 2048. The corresponding public key can then be derived from the private key using the openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem command. ECDSA key generation with the secp256r1 curve can be performed using the openssl ecparam -name prime256v1 -genkey -out ec_private_key.pem and openssl ec -in ec_private_key.pem -pubout -out ec_public_key.pem commands.

The Argon2id algorithm can be configured with several parameters to adjust the memory usage, parallelism, and number of iterations. The Crypto.Password.Argon2 module in .NET Core 3.1 allows you to specify the Argon2id parameters using the Argon2IdOptions class, for example, new Argon2IdOptions { TimeCost = 2, MemoryCost = 65536, Parallelism = 4 }. The crypto_pwhash_argon2id function in libsodium 1.0.18 also accepts similar parameters, such as the opslimit and memlimit options.

The HKDF algorithm can be used to derive multiple keys from a single input key or password. For example, in .NET Core 3.1, you can use the Crypto.KDF.HKDF.DeriveKey method to derive an AES-256 encryption key and an HMAC signing key from a master secret: var (encryptionKey, signingKey) = HKDF.DeriveKey(masterSecret, 32, 32, "myapp-keys"). In libsodium 1.0.18, the crypto_kdf_derive_from_key function can be used to derive multiple keys from a single master key.

Envelope encryption can be implemented using a combination of symmetric and asymmetric cryptography. First, a random AES-256-GCM key is generated to encrypt the data. Then, this key is encrypted using a public-key algorithm, such as RSA or ECDSA. The encrypted data and the encrypted key are then stored or transmitted together. When decrypting, the recipient first decrypts the symmetric key using their private key, and then uses the decrypted key to decrypt the data.

Libsodium's sealed boxes provide a high-level interface for public-key encryption and authentication. The crypto_box_seal function is used to encrypt a message for a recipient, and the crypto_box_open_seal function is used to decrypt and verify the message. Sealed boxes automatically handle the key exchange, encryption, and authentication, making it easier for developers to implement secure communication channels without worrying about the underlying cryptographic details.

Constant-time comparison is crucial when comparing sensitive values, such as cryptographic keys or authentication tokens, to prevent timing side-channel attacks. The CRYPTO_memcmp function in OpenSSL 1.1.1 and the sodium_memcmp function in libsodium 1.0.18 are examples of constant-time comparison functions that should be used instead of the standard memcmp. These functions ensure that the comparison time is independent of the input values, preventing attackers from inferring information about the compared values based on the comparison time.

Cryptographically Secure Pseudo-Random Number Generators (CSPRNGs) are essential for generating high-quality random numbers used in cryptographic operations. On Unix-like systems, the /dev/urandom device provides access to the system's CSPRNG, while on Windows, the CryptGenRandom function can be used. Cryptographic libraries like OpenSSL 1.1.1 and libsodium 1.0.18 provide platform-independent wrappers for accessing the system CSPRNG, such as the RAND_bytes and randombytes_buf functions. It's important to always use these functions instead of standard pseudo-random number generators, which may not be suitable for cryptographic use.When using AES-256-GCM for authenticated encryption, it's crucial to properly handle the Initialization Vector (IV) and the Additional Authenticated Data (AAD). The IV should be unique for each message encrypted with the same key, and it can be generated using a secure random number generator like the one provided by the operating system. The AAD is additional data that is authenticated but not encrypted, such as message headers or metadata. The crypto_aead_aes256gcm_encrypt and crypto_aead_aes256gcm_decrypt functions in libsodium 1.0.18 allow you to specify the IV and AAD parameters, ensuring the confidentiality and integrity of the encrypted data.

For RSA key generation, the openssl genrsa command can be used to generate a private key with a specified modulus size, e.g., openssl genrsa -out rsa_private_key.pem 2048. The corresponding public key can then be derived from the private key using the openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem command. ECDSA key generation with the secp256r1 curve can be performed using the openssl ecparam -name prime256v1 -genkey -out ec_private_key.pem and openssl ec -in ec_private_key.pem -pubout -out ec_public_key.pem commands. The choice between RSA and ECDSA depends on factors such as key size, performance, and quantum-resistance.

The Argon2id algorithm can be configured with several parameters to adjust the memory usage, parallelism, and number of iterations. The Crypto.Password.Argon2 module in .NET Core 3.1 allows you to specify the Argon2id parameters using the Argon2IdOptions class, for example, new Argon2IdOptions { TimeCost = 2, MemoryCost = 65536, Parallelism = 4 }. The crypto_pwhash_argon2id function in libsodium 1.0.18 also accepts similar parameters, such as the opslimit and memlimit options, to fine-tune the algorithm's behavior for your specific use case.

The HKDF algorithm can be used to derive multiple keys from a single input key or password. For example, in .NET Core 3.1, you can use the Crypto.KDF.HKDF.DeriveKey method to derive an AES-256 encryption key and an HMAC signing key from a master secret: var (encryptionKey, signingKey) = HKDF.DeriveKey(masterSecret, 32, 32, "myapp-keys"). In libsodium 1.0.18, the crypto_kdf_derive_from_key function can be used to derive multiple keys from a single master key, allowing you to efficiently manage and distribute cryptographic keys within your application.

Envelope encryption is a technique that combines symmetric and asymmetric cryptography to provide efficient and secure data encryption. In this approach, a randomly generated symmetric key, such as an AES-256-GCM key, is used to encrypt the data, and the symmetric key is then encrypted using a public-key algorithm, such as RSA or ECDSA. This allows for efficient bulk data encryption while still leveraging the key management and non-repudiation benefits of public-key cryptography, making it a popular choice for secure data storage and communication.

Libsodium's sealed boxes provide a high-level interface for public-key encryption and authentication, abstracting away the underlying cryptographic details. The crypto_box_seal function is used to encrypt a message for a recipient, and the crypto_box_open_seal function is used to decrypt and verify the message. Sealed boxes automatically handle the key exchange, encryption, and authentication, making it easier for developers to implement secure communication channels without worrying about the complexities of public-key cryptography.

Constant-time comparison is crucial when comparing sensitive values, such as cryptographic keys or authentication tokens, to prevent timing side-channel attacks. The CRYPTO_memcmp function in OpenSSL 1.1.1 and the sodium_memcmp function in libsodium 1.0.18 are examples of constant-time comparison functions that should be used instead of the standard memcmp. These functions ensure that the comparison time is independent of the input values, preventing attackers from inferring information about the compared values based on the comparison time, thus mitigating a class of side-channel attacks.

Cryptographically Secure Pseudo-Random Number Generators (CSPRNGs) are essential for generating high-quality random numbers used in cryptographic operations, such as key generation, nonces, and salts. Operating system-provided CSPRNGs, such as /dev/urandom on Unix-like systems or the CryptGenRandom function on Windows, should be used instead of standard pseudo-random number generators, which may not be suitable for cryptographic use. Cryptographic libraries like OpenSSL 1.1.1 and libsodium 1.0.18 provide functions like RAND_bytes and randombytes_buf to access the system CSPRNG in a platform-independent way, ensuring the high quality of the generated random data.When using AES-256-GCM for authenticated encryption, it's essential to properly handle the Initialization Vector (IV) and the Additional Authenticated Data (AAD) to ensure the confidentiality and integrity of the encrypted data. The IV should be unique for each message encrypted with the same key, and it can be generated using a secure random number generator like the one provided by the operating system. The AAD is additional data that is authenticated but not encrypted, such as message headers or metadata. The crypto_aead_aes256gcm_encrypt and crypto_aead_aes256gcm_decrypt functions in libsodium 1.0.18 allow you to specify the IV and AAD parameters, providing a comprehensive solution for AES-256-GCM authenticated encryption.

For RSA key generation, the openssl genrsa command can be used to generate a private key with a specified modulus size, e.g., openssl genrsa -out rsa_private_key.pem 2048. The corresponding public key can then be derived from the private key using the openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem command. ECDSA key generation with the secp256r1 curve can be performed using the openssl ecparam -name prime256v1 -genkey -out ec_private_key.pem and openssl ec -in ec_private_key.pem -pubout -out ec_public_key.pem commands. The choice between RSA and ECDSA depends on factors such as key size, performance, and quantum-resistance, with ECDSA offering advantages in terms of smaller key sizes and faster operations.

The Argon2id algorithm can be configured with several parameters to adjust the memory usage, parallelism, and number of iterations, allowing you to fine-tune the algorithm's behavior for your specific use case. The Crypto.Password.Argon2 module in .NET Core 3.1 allows you to specify the Argon2id parameters using the Argon2IdOptions class, for example, new Argon2IdOptions { TimeCost = 2, MemoryCost = 65536, Parallelism = 4 }. The crypto_pwhash_argon2id function in libsodium 1.0.18 also accepts similar parameters, such as the opslimit and memlimit options, providing a flexible and customizable password hashing solution.

The HKDF algorithm can be used to derive multiple keys from a single input key or password, enabling efficient key management and distribution within your application. For example, in .NET Core 3.1, you can use the Crypto.KDF.HKDF.DeriveKey method to derive an AES-256 encryption key and an HMAC signing key from a master secret: var (encryptionKey, signingKey) = HKDF.DeriveKey(masterSecret, 32, 32, "myapp-keys"). In libsodium 1.0.18, the crypto_kdf_derive_from_key function can be used to derive multiple keys from a single master key, providing a standardized and secure key derivation solution.

Envelope encryption is a technique that combines symmetric and asymmetric cryptography to provide efficient and secure data encryption. In this approach, a randomly generated symmetric key, such as an AES-256-GCM key, is used to encrypt the data, and the symmetric key is then encrypted using a public-key algorithm, such as RSA or ECDSA. This allows for efficient bulk data encryption while still leveraging the key management and non-repudiation benefits of public-key cryptography, making it a popular choice for secure data storage and communication in a wide range of applications.

Libsodium's sealed boxes provide a high-level interface for public-key encryption and authentication, abstracting away the underlying cryptographic details and simplifying the implementation of secure communication channels. The crypto_box_seal function is used to encrypt a message for a recipient, and the crypto_box_open_seal function is used to decrypt and verify the message. Sealed boxes automatically handle the key exchange, encryption, and authentication, reducing the complexity of working with public-key cryptography and allowing developers to focus on the application-level logic.

Constant-time comparison is a crucial technique for mitigating timing side-channel attacks when comparing sensitive values, such as cryptographic keys or authentication tokens. The CRYPTO_memcmp function in OpenSSL 1.1.1 and the sodium_memcmp function in libsodium 1.0.18 are examples of constant-time comparison functions that should be used instead of the standard memcmp. These functions ensure that the comparison time is independent of the input values, preventing attackers from inferring information about the compared values based on the comparison time, thus effectively mitigating a class of side-channel attacks.

Cryptographically Secure Pseudo-Random Number Generators (CSPRNGs) are essential for generating high-quality random numbers used in cryptographic operations, such as key generation, nonces, and salts. Operating system-provided CSPRNGs, such as /dev/urandom on Unix-like systems or the CryptGenRandom function on Windows, should be used instead of standard pseudo-random number generators, which may not be suitable for cryptographic use. Cryptographic libraries like OpenSSL 1.1.1 and libsodium 1.0.18 provide functions like RAND_bytes and randombytes_buf to access the system CSPRNG in a platform-independent way, ensuring the high quality and security of the generated random data.