Skip to content

Commit

Permalink
src: Switch from DllImport to LibraryImport.
Browse files Browse the repository at this point in the history
  • Loading branch information
samuel-lucas6 committed Nov 10, 2024
1 parent ef2a93f commit 5e5eb66
Show file tree
Hide file tree
Showing 38 changed files with 418 additions and 500 deletions.
18 changes: 6 additions & 12 deletions src/Geralt/Crypto/AEGIS128L.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,24 @@ public static class AEGIS128L
public const int NonceSize = crypto_aead_aegis128l_NPUBBYTES;
public const int TagSize = crypto_aead_aegis128l_ABYTES;

public static unsafe void Encrypt(Span<byte> ciphertext, ReadOnlySpan<byte> plaintext, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> key, ReadOnlySpan<byte> associatedData = default)
public static void Encrypt(Span<byte> ciphertext, ReadOnlySpan<byte> plaintext, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> key, ReadOnlySpan<byte> associatedData = default)
{
Validation.EqualToSize(nameof(ciphertext), ciphertext.Length, plaintext.Length + TagSize);
Validation.EqualToSize(nameof(nonce), nonce.Length, NonceSize);
Validation.EqualToSize(nameof(key), key.Length, KeySize);
Sodium.Initialize();
fixed (byte* c = ciphertext, p = plaintext, n = nonce, k = key, ad = associatedData)
{
int ret = crypto_aead_aegis128l_encrypt(c, ciphertextLength: out _, p, (ulong)plaintext.Length, ad, (ulong)associatedData.Length, nsec: null, n, k);
if (ret != 0) { throw new CryptographicException("Error encrypting plaintext."); }
}
int ret = crypto_aead_aegis128l_encrypt(ciphertext, ciphertextLength: out _, plaintext, (ulong)plaintext.Length, associatedData, (ulong)associatedData.Length, nsec: null, nonce, key);
if (ret != 0) { throw new CryptographicException("Error encrypting plaintext."); }
}

public static unsafe void Decrypt(Span<byte> plaintext, ReadOnlySpan<byte> ciphertext, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> key, ReadOnlySpan<byte> associatedData = default)
public static void Decrypt(Span<byte> plaintext, ReadOnlySpan<byte> ciphertext, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> key, ReadOnlySpan<byte> associatedData = default)
{
Validation.NotLessThanMin(nameof(ciphertext), ciphertext.Length, TagSize);
Validation.EqualToSize(nameof(plaintext), plaintext.Length, ciphertext.Length - TagSize);
Validation.EqualToSize(nameof(nonce), nonce.Length, NonceSize);
Validation.EqualToSize(nameof(key), key.Length, KeySize);
Sodium.Initialize();
fixed (byte* p = plaintext, c = ciphertext, n = nonce, k = key, ad = associatedData)
{
int ret = crypto_aead_aegis128l_decrypt(p, plaintextLength: out _, nsec: null, c, (ulong)ciphertext.Length, ad, (ulong)associatedData.Length, n, k);
if (ret != 0) { throw new CryptographicException("Invalid authentication tag for the given inputs."); }
}
int ret = crypto_aead_aegis128l_decrypt(plaintext, plaintextLength: out _, nsec: null, ciphertext, (ulong)ciphertext.Length, associatedData, (ulong)associatedData.Length, nonce, key);
if (ret != 0) { throw new CryptographicException("Invalid authentication tag for the given inputs."); }
}
}
18 changes: 6 additions & 12 deletions src/Geralt/Crypto/AEGIS256.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,24 @@ public static class AEGIS256
public const int NonceSize = crypto_aead_aegis256_NPUBBYTES;
public const int TagSize = crypto_aead_aegis256_ABYTES;

public static unsafe void Encrypt(Span<byte> ciphertext, ReadOnlySpan<byte> plaintext, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> key, ReadOnlySpan<byte> associatedData = default)
public static void Encrypt(Span<byte> ciphertext, ReadOnlySpan<byte> plaintext, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> key, ReadOnlySpan<byte> associatedData = default)
{
Validation.EqualToSize(nameof(ciphertext), ciphertext.Length, plaintext.Length + TagSize);
Validation.EqualToSize(nameof(nonce), nonce.Length, NonceSize);
Validation.EqualToSize(nameof(key), key.Length, KeySize);
Sodium.Initialize();
fixed (byte* c = ciphertext, p = plaintext, n = nonce, k = key, ad = associatedData)
{
int ret = crypto_aead_aegis256_encrypt(c, ciphertextLength: out _, p, (ulong)plaintext.Length, ad, (ulong)associatedData.Length, nsec: null, n, k);
if (ret != 0) { throw new CryptographicException("Error encrypting plaintext."); }
}
int ret = crypto_aead_aegis256_encrypt(ciphertext, ciphertextLength: out _, plaintext, (ulong)plaintext.Length, associatedData, (ulong)associatedData.Length, nsec: null, nonce, key);
if (ret != 0) { throw new CryptographicException("Error encrypting plaintext."); }
}

public static unsafe void Decrypt(Span<byte> plaintext, ReadOnlySpan<byte> ciphertext, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> key, ReadOnlySpan<byte> associatedData = default)
public static void Decrypt(Span<byte> plaintext, ReadOnlySpan<byte> ciphertext, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> key, ReadOnlySpan<byte> associatedData = default)
{
Validation.NotLessThanMin(nameof(ciphertext), ciphertext.Length, TagSize);
Validation.EqualToSize(nameof(plaintext), plaintext.Length, ciphertext.Length - TagSize);
Validation.EqualToSize(nameof(nonce), nonce.Length, NonceSize);
Validation.EqualToSize(nameof(key), key.Length, KeySize);
Sodium.Initialize();
fixed (byte* p = plaintext, c = ciphertext, n = nonce, k = key, ad = associatedData)
{
int ret = crypto_aead_aegis256_decrypt(p, plaintextLength: out _, nsec: null, c, (ulong)ciphertext.Length, ad, (ulong)associatedData.Length, n, k);
if (ret != 0) { throw new CryptographicException("Invalid authentication tag for the given inputs."); }
}
int ret = crypto_aead_aegis256_decrypt(plaintext, plaintextLength: out _, nsec: null, ciphertext, (ulong)ciphertext.Length, associatedData, (ulong)associatedData.Length, nonce, key);
if (ret != 0) { throw new CryptographicException("Invalid authentication tag for the given inputs."); }
}
}
32 changes: 11 additions & 21 deletions src/Geralt/Crypto/Argon2id.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,54 +14,44 @@ public static class Argon2id
public const int MaxHashSize = crypto_pwhash_STRBYTES;
private const string HashPrefix = crypto_pwhash_argon2id_STRPREFIX;

public static unsafe void DeriveKey(Span<byte> outputKeyingMaterial, ReadOnlySpan<byte> password, ReadOnlySpan<byte> salt, int iterations, int memorySize)
public static void DeriveKey(Span<byte> outputKeyingMaterial, ReadOnlySpan<byte> password, ReadOnlySpan<byte> salt, int iterations, int memorySize)
{
Validation.NotLessThanMin(nameof(outputKeyingMaterial), outputKeyingMaterial.Length, MinKeySize);
Validation.EqualToSize(nameof(salt), salt.Length, SaltSize);
Validation.NotLessThanMin(nameof(iterations), iterations, MinIterations);
Validation.NotLessThanMin(nameof(memorySize), memorySize, MinMemorySize);
Sodium.Initialize();
fixed (byte* okm = outputKeyingMaterial, p = password, s = salt)
{
int ret = crypto_pwhash(okm, (ulong)outputKeyingMaterial.Length, p, (ulong)password.Length, s, (ulong)iterations, (nuint)memorySize, crypto_pwhash_argon2id_ALG_ARGON2ID13);
if (ret != 0) { throw new InsufficientMemoryException("Insufficient memory to perform key derivation."); }
}
int ret = crypto_pwhash(outputKeyingMaterial, (ulong)outputKeyingMaterial.Length, password, (ulong)password.Length, salt, (ulong)iterations, (nuint)memorySize, crypto_pwhash_argon2id_ALG_ARGON2ID13);
if (ret != 0) { throw new InsufficientMemoryException("Insufficient memory to perform key derivation."); }
}

public static unsafe void ComputeHash(Span<byte> hash, ReadOnlySpan<byte> password, int iterations, int memorySize)
public static void ComputeHash(Span<byte> hash, ReadOnlySpan<byte> password, int iterations, int memorySize)
{
Validation.EqualToSize(nameof(hash), hash.Length, MaxHashSize);
Validation.NotLessThanMin(nameof(iterations), iterations, MinIterations);
Validation.NotLessThanMin(nameof(memorySize), memorySize, MinMemorySize);
Sodium.Initialize();
fixed (byte* h = hash, p = password)
{
int ret = crypto_pwhash_str_alg(h, p, (ulong)password.Length, (ulong)iterations, (nuint)memorySize, crypto_pwhash_argon2id_ALG_ARGON2ID13);
if (ret != 0) { throw new InsufficientMemoryException("Insufficient memory to perform password hashing."); }
}
int ret = crypto_pwhash_str_alg(hash, password, (ulong)password.Length, (ulong)iterations, (nuint)memorySize, crypto_pwhash_argon2id_ALG_ARGON2ID13);
if (ret != 0) { throw new InsufficientMemoryException("Insufficient memory to perform password hashing."); }
}

public static unsafe bool VerifyHash(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> password)
public static bool VerifyHash(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> password)
{
Validation.SizeBetween(nameof(hash), hash.Length, MinHashSize, MaxHashSize);
ThrowIfInvalidHashPrefix(hash);
Sodium.Initialize();
fixed (byte* h = hash, p = password)
return crypto_pwhash_str_verify(h, p, (ulong)password.Length) == 0;
return crypto_pwhash_str_verify(hash, password, (ulong)password.Length) == 0;
}

public static unsafe bool NeedsRehash(ReadOnlySpan<byte> hash, int iterations, int memorySize)
public static bool NeedsRehash(ReadOnlySpan<byte> hash, int iterations, int memorySize)
{
Validation.SizeBetween(nameof(hash), hash.Length, MinHashSize, MaxHashSize);
Validation.NotLessThanMin(nameof(iterations), iterations, MinIterations);
Validation.NotLessThanMin(nameof(memorySize), memorySize, MinMemorySize);
ThrowIfInvalidHashPrefix(hash);
Sodium.Initialize();
fixed (byte* h = hash)
{
int ret = crypto_pwhash_str_needs_rehash(h, (ulong)iterations, (nuint)memorySize);
return ret == -1 ? throw new FormatException("Invalid encoded password hash.") : ret == 1;
}
int ret = crypto_pwhash_str_needs_rehash(hash, (ulong)iterations, (nuint)memorySize);
return ret == -1 ? throw new FormatException("Invalid encoded password hash.") : ret == 1;
}

private static void ThrowIfInvalidHashPrefix(ReadOnlySpan<byte> hash)
Expand Down
27 changes: 9 additions & 18 deletions src/Geralt/Crypto/BLAKE2b.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,12 @@ public static class BLAKE2b
public const int MaxKeySize = crypto_generichash_KEYBYTES_MAX;
private const int StreamBufferSize = 4096;

public static unsafe void ComputeHash(Span<byte> hash, ReadOnlySpan<byte> message)
public static void ComputeHash(Span<byte> hash, ReadOnlySpan<byte> message)
{
Validation.SizeBetween(nameof(hash), hash.Length, MinHashSize, MaxHashSize);
Sodium.Initialize();
fixed (byte* h = hash, m = message)
{
int ret = crypto_generichash_blake2b(h, (nuint)hash.Length, m, (ulong)message.Length, key: null, keyLength: 0);
if (ret != 0) { throw new CryptographicException("Error computing hash."); }
}
int ret = crypto_generichash_blake2b(hash, (nuint)hash.Length, message, (ulong)message.Length, key: null, keyLength: 0);
if (ret != 0) { throw new CryptographicException("Error computing hash."); }
}

public static void ComputeHash(Span<byte> hash, Stream message)
Expand All @@ -43,16 +40,13 @@ public static void ComputeHash(Span<byte> hash, Stream message)
blake2b.Finalize(hash);
}

public static unsafe void ComputeTag(Span<byte> tag, ReadOnlySpan<byte> message, ReadOnlySpan<byte> key)
public static void ComputeTag(Span<byte> tag, ReadOnlySpan<byte> message, ReadOnlySpan<byte> key)
{
Validation.SizeBetween(nameof(tag), tag.Length, MinTagSize, MaxTagSize);
Validation.SizeBetween(nameof(key), key.Length, MinKeySize, MaxKeySize);
Sodium.Initialize();
fixed (byte* t = tag, m = message, k = key)
{
int ret = crypto_generichash_blake2b(t, (nuint)tag.Length, m, (ulong)message.Length, k, (nuint)key.Length);
if (ret != 0) { throw new CryptographicException("Error computing tag."); }
}
int ret = crypto_generichash_blake2b(tag, (nuint)tag.Length, message, (ulong)message.Length, key, (nuint)key.Length);
if (ret != 0) { throw new CryptographicException("Error computing tag."); }
}

public static bool VerifyTag(ReadOnlySpan<byte> tag, ReadOnlySpan<byte> message, ReadOnlySpan<byte> key)
Expand All @@ -66,17 +60,14 @@ public static bool VerifyTag(ReadOnlySpan<byte> tag, ReadOnlySpan<byte> message,
return equal;
}

public static unsafe void DeriveKey(Span<byte> outputKeyingMaterial, ReadOnlySpan<byte> inputKeyingMaterial, ReadOnlySpan<byte> personalization, ReadOnlySpan<byte> salt = default, ReadOnlySpan<byte> info = default)
public static void DeriveKey(Span<byte> outputKeyingMaterial, ReadOnlySpan<byte> inputKeyingMaterial, ReadOnlySpan<byte> personalization, ReadOnlySpan<byte> salt = default, ReadOnlySpan<byte> info = default)
{
Validation.SizeBetween(nameof(outputKeyingMaterial), outputKeyingMaterial.Length, MinKeySize, MaxKeySize);
Validation.SizeBetween(nameof(inputKeyingMaterial), inputKeyingMaterial.Length, MinKeySize, MaxKeySize);
Validation.EqualToSize(nameof(personalization), personalization.Length, PersonalSize);
if (salt.Length != 0) { Validation.EqualToSize(nameof(salt), salt.Length, SaltSize); }
Sodium.Initialize();
fixed (byte* okm = outputKeyingMaterial, ikm = inputKeyingMaterial, p = personalization, s = salt, i = info)
{
int ret = crypto_generichash_blake2b_salt_personal(okm, (nuint)outputKeyingMaterial.Length, i, (ulong)info.Length, ikm, (nuint)inputKeyingMaterial.Length, s, p);
if (ret != 0) { throw new CryptographicException("Error deriving key."); }
}
int ret = crypto_generichash_blake2b_salt_personal(outputKeyingMaterial, (nuint)outputKeyingMaterial.Length, info, (ulong)info.Length, inputKeyingMaterial, (nuint)inputKeyingMaterial.Length, salt.Length != 0 ? salt : new byte[SaltSize], personalization);
if (ret != 0) { throw new CryptographicException("Error deriving key."); }
}
}
27 changes: 9 additions & 18 deletions src/Geralt/Crypto/ChaCha20.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,45 +9,36 @@ public static class ChaCha20
public const int NonceSize = crypto_stream_chacha20_ietf_NONCEBYTES;
public const int BlockSize = 64;

public static unsafe void Fill(Span<byte> buffer, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> key)
public static void Fill(Span<byte> buffer, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> key)
{
Validation.NotEmpty(nameof(buffer), buffer.Length);
Validation.EqualToSize(nameof(nonce), nonce.Length, NonceSize);
Validation.EqualToSize(nameof(key), key.Length, KeySize);
Sodium.Initialize();
fixed (byte* b = buffer, n = nonce, k = key)
{
int ret = crypto_stream_chacha20_ietf(b, (ulong)buffer.Length, n, k);
if (ret != 0) { throw new CryptographicException("Error computing pseudorandom bytes."); }
}
int ret = crypto_stream_chacha20_ietf(buffer, (ulong)buffer.Length, nonce, key);
if (ret != 0) { throw new CryptographicException("Error computing pseudorandom bytes."); }
}

public static unsafe void Encrypt(Span<byte> ciphertext, ReadOnlySpan<byte> plaintext, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> key, uint counter = 0)
public static void Encrypt(Span<byte> ciphertext, ReadOnlySpan<byte> plaintext, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> key, uint counter = 0)
{
Validation.EqualToSize(nameof(ciphertext), ciphertext.Length, plaintext.Length);
Validation.EqualToSize(nameof(nonce), nonce.Length, NonceSize);
Validation.EqualToSize(nameof(key), key.Length, KeySize);
ThrowIfCounterOverflow(plaintext.Length, counter);
Sodium.Initialize();
fixed (byte* c = ciphertext, p = plaintext, n = nonce, k = key)
{
int ret = crypto_stream_chacha20_ietf_xor_ic(c, p, (ulong)plaintext.Length, n, counter, k);
if (ret != 0) { throw new CryptographicException("Error encrypting plaintext."); }
}
int ret = crypto_stream_chacha20_ietf_xor_ic(ciphertext, plaintext, (ulong)plaintext.Length, nonce, counter, key);
if (ret != 0) { throw new CryptographicException("Error encrypting plaintext."); }
}

public static unsafe void Decrypt(Span<byte> plaintext, ReadOnlySpan<byte> ciphertext, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> key, uint counter = 0)
public static void Decrypt(Span<byte> plaintext, ReadOnlySpan<byte> ciphertext, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> key, uint counter = 0)
{
Validation.EqualToSize(nameof(plaintext), plaintext.Length, ciphertext.Length);
Validation.EqualToSize(nameof(nonce), nonce.Length, NonceSize);
Validation.EqualToSize(nameof(key), key.Length, KeySize);
ThrowIfCounterOverflow(ciphertext.Length, counter);
Sodium.Initialize();
fixed (byte* p = plaintext, c = ciphertext, n = nonce, k = key)
{
int ret = crypto_stream_chacha20_ietf_xor_ic(p, c, (ulong)ciphertext.Length, n, counter, k);
if (ret != 0) { throw new CryptographicException("Error decrypting ciphertext."); }
}
int ret = crypto_stream_chacha20_ietf_xor_ic(plaintext, ciphertext, (ulong)ciphertext.Length, nonce, counter, key);
if (ret != 0) { throw new CryptographicException("Error decrypting ciphertext."); }
}

private static void ThrowIfCounterOverflow(int messageSize, uint counter)
Expand Down
Loading

0 comments on commit 5e5eb66

Please sign in to comment.