🔀 Hashing
LibSodium.Net provides multiple hashing APIs for different use cases:
| API | Algorithm | Use Case |
|---|---|---|
GenericHash |
BLAKE2b | Cryptographic hash with optional key. Use for MAC, PRF, fingerprints. |
ShortHash |
SipHash‑2‑4 | Keyed hash designed to prevent collisions in hash tables. Fast for short inputs. |
CryptoSha256 |
SHA‑256 | Fast fixed‑length (32‑byte) hash for integrity checks, digital signatures, checksums. |
CryptoSha512 |
SHA‑512 | Fast fixed‑length (64‑byte) hash for high‑strength integrity and digital signatures. |
CryptoPasswordHashArgon |
Argon2id/i13 | Password hashing and key derivation (slow & memory‑hard) |
CryptoPasswordHashScrypt |
Scrypt | Password hashing and key derivation (slow & memory‑hard, legacy) |
📝 SHA‑2 functions are not suitable for password hashing or key derivation. Use Argon2 or scrypt instead.
🧂 Based on libsodium’s Hashing
🧂 Based on Password Hashing
đź§‚ Based on SHA-2
ℹ️ API Reference: CryptoGenericHash
ℹ️ API Reference: CryptoSha256
ℹ️ API Reference: CryptoSha512 ℹ️ API Reference: CryptoShortHash
ℹ️ API Reference: CryptoPasswordHashArgon
ℹ️ API Reference: CryptoPasswordHashScrypt
🌟 Features
- Cryptographic hashing with variable output length (GenericHash)
- Fast fixed‑length hashing (CryptoSha256 & CryptoSha512)
- SipHash‑based keyed hash for short inputs (ShortHash)
- Password hashing and key derivation using Argon2 (CryptoPasswordHash)
- All methods are allocation‑free,
Span‑based, and deterministic (except password hash, which is randomized) - Stream and async support for large input hashing (GenericHash, CryptoSha256, CryptoSha512)
- Incremental (multi-part) hashing (GenericHash, CryptoSha256, CryptoSha512)
🗝️ Key Management
Some hash functions accept a key (e.g., GenericHash, ShortHash), while others produce one as output (e.g., Argon2, Scrypt). This section explains how to pass and store keys safely.
Keys can be provided or stored using the following types:
SecureMemory<byte>— most secure option, with memory protection and automatic zeroing.Span<byte>/ReadOnlySpan<byte>— fast and stack-allocated. Ideal for synchronous use.byte[]— interoperable and usable in both sync and async contexts.Memory<byte>/ReadOnlyMemory<byte>— for use with async methods.
📝 Use
Span<T>for high-performance local operations, andSecureMemory<byte>to protect secrets in memory.
When using key derivation functions (e.g., Argon2, Scrypt):
Examples:
// SecureMemory<byte>
using var key = new SecureMemory<byte>(GenericHash.KeyLen);
RandomGenerator.Fill(key);
key.ProtectReadOnly();
// Span<byte>
Span<byte> key = stackalloc byte[GenericHash.KeyLen];
RandomGenerator.Fill(key);
// byte[]
var key = new byte[GenericHash.KeyLen];
RandomGenerator.Fill(key);
Tips:
- Store the derived key in
SecureMemory<byte>, mark it as read-only using.ProtectReadOnly(), and dispose it properly. - Never reuse keys across different algorithms or protocols. Even if the key size is compatible, doing so weakens isolation and security boundaries.
- Use a strong, random salt and a context-specific derivation strategy.
- Generate a fresh random key with
RandomGenerator.Fill()and store it securely (e.g., Azure Key Vault, environment variable, HSM). - Rotate keys periodically.
✨ GenericHash — BLAKE2b
BLAKE2b is a cryptographic hash function designed as a faster and safer alternative to SHA‑2. It provides high‑performance hashing with optional key support, making it suitable for:
- Cryptographic checksums (fingerprints)
- Message authentication codes (MACs)
- Deriving identifiers or integrity tags
- Hashing files or streams of arbitrary size
- Unique deterministic identifiers
- Pseudorandom functions (PRF) when keyed
By default, it produces 32‑byte output, but can be configured to return between 16 and 64 bytes. It supports keyed hashing for MAC‑like or PRF behavior, using a key of 32 bytes by default (configurable between 16 and 64 bytes), or unkeyed hashing for general‑purpose use.
📏 Constants
| Name | Value | Description |
|---|---|---|
HashLen |
32 | Default output length |
MinHashLen |
16 | Minimum output length |
MaxHashLen |
64 | Maximum output length |
KeyLen |
32 | Default key length |
MinKeyLen |
16 | Minimum key length |
MaxKeyLen |
64 | Maximum key length |
đź“‹ Hashing with GenericHash
With optional key:
Span<byte> hash = stackalloc byte[CryptoGenericHash.HashLen];
CryptoGenericHash.ComputeHash(hash, message); // unkeyed
CryptoGenericHash.ComputeHash(hash, message, key); // keyed
from a stream:
using var stream = File.OpenRead("large-input.dat");
CryptoGenericHash.ComputeHash(hash, stream);
Async stream support:
using var stream = File.OpenRead("large-input.dat");
await CryptoGenericHash.ComputeHashAsync(hash, stream, key);
✨ CryptoSha256 — SHA‑256
CryptoSha256 offers a high‑speed, fixed‑length (32‑byte) SHA‑256 implementation built directly on libsodium’s crypto_hash_sha256 API. Use it when you need interoperability with existing SHA‑256 digests (e.g., digital signatures, blockchain, TLS certificate fingerprints) or whenever a fixed 32‑byte checksum is required.
📏 Constants
| Name | Value | Description |
|---|---|---|
HashLen |
32 | Output length (32Â bytes) |
đź“‹ Hashing with CryptoSha256
Hash a byte array:
Span<byte> hash = stackalloc byte[CryptoSha256.HashLen];
CryptoSha256.ComputeHash(hash, message);
Hash a stream (buffered, sync):
using var stream = File.OpenRead("video.mp4");
CryptoSha256.ComputeHash(hash, stream);
Async stream hashing:
await CryptoSha256.ComputeHashAsync(hash, stream);
✨ CryptoSha512 — SHA‑512
CryptoSha512 is a fixed‑length (64‑byte) implementation of SHA‑512 via libsodium’s crypto_hash_sha512. It is usually faster than SHA‑256 on modern 64‑bit CPUs and provides a larger security margin.
📏 Constants
| Name | Value | Description |
|---|---|---|
HashLen |
64 | Output length (64Â bytes) |
đź“‹ Hashing with CryptoSha512
Hash a Span
Span<byte> hash = stackalloc byte[CryptoSha512.HashLen];
CryptoSha512.ComputeHash(hash, message);
Hash a stream (buffered, sync):
using var stream = File.OpenRead("backup.tar");
CryptoSha512.ComputeHash(hash, stream);
Async stream hashing:
await CryptoSha512.ComputeHashAsync(hash, stream);
✨ Incremental Hashing
In some scenarios, data to be hashed is not available as a single contiguous buffer — for example, when you want to compute hash(a || b || c) from multiple inputs. LibSodium.Net offers incremental hashing for this purpose.
The following classes support incremental hashing:
CryptoGenericHash(BLAKE2b, optionally keyed)CryptoSha256(SHA-256)CryptoSha512(SHA-512)
These types expose an incremental API via the ICryptoIncrementalHash interface.
Compute hash from multiple parts:
Span<byte> hash = stackalloc byte[CryptoSha256.HashLen];
using var hasher = CryptoSha256.CreateIncrementalHash();
hasher.Update(Encoding.UTF8.GetBytes("header"));
hasher.Update(Encoding.UTF8.GetBytes("payload"));
hasher.Update(Encoding.UTF8.GetBytes("footer"));
hasher.Final(hash);
This pattern ensures correctness and efficiency when you want to hash logically grouped inputs without allocating or copying them into a single buffer.
With a keyed BLAKE2b hash
Span<byte> key = stackalloc byte[CryptoGenericHash.KeyLen];
RandomGenerator.Fill(key);
Span<byte> hash = stackalloc byte[32];
var part1 = Encoding.UTF8.GetBytes("hello");
var part2 = Encoding.UTF8.GetBytes("world");
using var hasher = CryptoGenericHash.CreateIncrementalHash(key, hash.Length);
hasher.Update(part1);
hasher.Update(part2);
hasher.Final(hash);
ℹ️ The
Final()method may only be called once per hash instance. You must create a new instance for each new computation.
✨ ShortHash — SipHash‑2‑4
⚠️ ShortHash is not a cryptographic hash. Do not use it for fingerprinting, content integrity, password hashing, or digital signatures.
SipHash is a fast keyed hash function optimized for short inputs. It is designed to mitigate hash‑flooding attacks in hash tables and similar data structures where untrusted input might lead to performance degradation.
It should be used for:
- Hash table key protection
- Fast authentication of short data
- Use cases where speed and DoS‑resistance are more important than collision resistance
SipHash is always keyed, and its output is always 8Â bytes.
📏 Constants
| Name | Value | Description |
|---|---|---|
HashLen |
8 | Output length (8Â bytes) |
KeyLen |
16 | Key length (16Â bytes) |
đź“‹ Hashing with ShortHash
ℹ️ key is required
Span<byte> hash = stackalloc byte[CryptoShortHash.HashLen];
CryptoShortHash.ComputeHash(hash, message, key);
✨ PasswordHashArgon
Secure password hashing and key derivation using Argon2 (Argon2id / Argon2i13). This algorithm is specifically designed to defend against brute‑force attacks by requiring significant computational work and memory. It is ideal for storing passwords, deriving keys from passphrases, or implementing authentication mechanisms.
Unlike fast cryptographic hash functions (like SHA‑256 or BLAKE2b), Argon2 is deliberately slow and memory‑intensive, which drastically increases the cost of large‑scale password cracking (e.g., GPU attacks). LibSodium.Net exposes both Argon2id (recommended) and Argon2i.
The cost parameters (iterations and memory) can be tuned to balance security and performance depending on the context:
- Interactive – suitable for login forms.
- Moderate – for higher‑value secrets.
- Sensitive – for long‑term or critical secrets.
📏 Constants
| Name | Value | Description |
|---|---|---|
SaltLen |
16 | Length of the salt in bytes |
MinKeyLen |
16 | Minimum key length for derivation |
EncodedLen |
128 | Length of the encoded hash string |
Prefix |
"$argon2id$" | Prefix for Argon2id encoded hash |
MinMemoryLen |
8Â KiB | Minimum acceptable memory for hashing |
MinIterations |
1 | Minimum acceptable iterations |
InteractiveIterations |
2 | Iteration count for interactive targets |
InteractiveMemoryLen |
64Â MiB | Memory usage for interactive targets |
ModerateIterations |
3 | For app secrets or backup keys |
ModerateMemoryLen |
256 MiB | For app secrets or backup keys |
SensitiveIterations |
4 | Iteration count for sensitive targets |
SensitiveMemoryLen |
1Â GiB | Memory usage for sensitive targets |
đź“‹ Working with PasswordHashArgon
Hash a password (encoded, random salt):
string hash = CryptoPasswordHash.HashPassword("my password");
Verify a password:
bool valid = CryptoPasswordHash.VerifyPassword(hash, "my password");
Derive a secret key from a password (e.g., for encryption):
using var key = new SecureMemory(32);
Span<byte> salt = stackalloc byte[CryptoPasswordHash.SaltLen];
RandomGenerator.Fill(salt);
CryptoPasswordHash.DeriveKey(key, "password", salt);
You can customise the computational cost:
CryptoPasswordHash.DeriveKey(
key, "password", salt,
iterations: CryptoPasswordHash.SensitiveIterations,
requiredMemoryLen: CryptoPasswordHash.SensitiveMemoryLen);
✨ PasswordHashScrypt
Password hashing and key derivation using scrypt, a memory-hard function introduced before Argon2. Though not side-channel resistant, it is still widely used and interoperable.
LibSodium.Net improves over libsodium by offering consistent tuning options (Min, Interactive, Moderate, Sensitive) and full validation coverage.
📏 Constants
| Name | Value | Description |
|---|---|---|
SaltLen |
32 | Length of the salt in bytes |
MinKeyLen |
16 | Minimum key length for derivation |
EncodedLen |
102 | Length of the encoded hash string |
Prefix |
"$7$" | Prefix for scrypt encoded hash |
MinIterations |
1024 (2^10) | Minimum recommended iterations |
MinMemoryLen |
32 KiB (2^15) | Minimum recommended memory |
InteractiveIterations |
524288 (2^19) | For login/password use |
InteractiveMemoryLen |
16 MiB (2^24) | For login/password use |
ModerateIterations |
4194304 (2^22) | For app secrets or backup keys |
ModerateMemoryLen |
128 MiB (2^27) | For app secrets or backup keys |
SensitiveIterations |
33554432 (2^25) | For long-term or high-value secrets |
SensitiveMemoryLen |
1 GiB (2^30) | For long-term or high-value secrets |
đź“‹ Working with PasswordHashScrypt
Hash and verify:
string hash = CryptoPasswordHashScrypt.HashPassword("my password");
bool valid = CryptoPasswordHashScrypt.VerifyPassword(hash, "my password");
Deriving a key from a password:
using var key = new SecureMemory<byte>(32);
Span<byte> salt = stackalloc byte[CryptoPasswordHashScrypt.SaltLen];
RandomGenerator.Fill(salt);
CryptoPasswordHashScrypt.DeriveKey(key, "password", salt,
iterations: CryptoPasswordHashScrypt.ModerateIterations,
requiredMemoryLen: CryptoPasswordHashScrypt.ModerateMemoryLen);
⚠️ Error Handling
ArgumentException — when input or key lengths are invalidArgumentOutOfRangeException — when iterations or memory limits are too lowLibSodiumException — if the underlying native function fails
📝 Notes
GenericHashis based on BLAKE2b and supports variable‑length output and optional keys.CryptoSha256andCryptoSha512provide interoperable SHA‑2 digests and are the best choice when you need a fixed‑length checksum or compatibility with external systems.ShortHashis based on SipHash‑2‑4 — not a general‑purpose cryptographic hash, but a keyed primitive for protecting hash tables.CryptoPasswordHashArgonuses Argon2id/Argon2i13 with computational and memory hardness.- All hash functions are deterministic: same input and key produce same output — except
CryptoPasswordHash.HashPassword, which includes a random salt and produces a different hash each time. Scryptis not side-channel resistant. UseArgon2i13orArgon2id13for high-security or shared-host scenarios.- Use
ShortHashonly when you can keep the key secret.
đź§ Choosing the Right Hash API
| Scenario | Recommended API |
|---|---|
| Variable‑length cryptographic checksum | GenericHash |
| Fixed‑length 32‑byte digest (e.g., TLS cert fingerprint) | CryptoSha256 |
| Fixed‑length 64‑byte digest, higher speed on x64 | CryptoSha512 |
| MAC (Message Authentication Code) or PRF (Pseudo Random Function) | GenericHash (with key) |
| Hashing short keys in tables | ShortHash |
| Password storage / passphrase‑derived keys | CryptoPasswordHashArgon |
| Legacy Password storage / passphrase‑derived keys | CryptoPasswordHashScrypt |
đź‘€ See Also
- ℹ️ API Reference: CryptoGenericHash
- ℹ️ API Reference: CryptoSha256
- ℹ️ API Reference: CryptoSha512
- ℹ️ API Reference: CryptoShortHash
- ℹ️ API Reference: CryptoPasswordHashArgon
- ℹ️ API Reference: CryptoPasswordHashScrypt
- 🧂 libsodium Hashing
- 🧂 libsodium Password Hashing
- đź§‚ libsodium SHA-2