aboutsummaryrefslogtreecommitdiff
path: root/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt
diff options
context:
space:
mode:
Diffstat (limited to 'wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt')
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NCUtilCipher.cs128
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NoscryptCipher.cs227
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NoscryptCipherFlags.cs60
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NoscryptCipherVersion.cs (renamed from wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCNip44EncryptionVersion.cs)23
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/INostrCrypto.cs96
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/INostrEncryptionVersion.cs43
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCContext.cs2
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCNip04EncryptionVersion.cs40
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCUtil.cs17
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Nip04Util.cs50
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Nip44MessageSegments.cs36
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Nip44Util.cs190
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptExtensions.cs162
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptLibrary.cs39
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptSigner.cs2
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NostrCrypto.cs159
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NostrMessageCipher.cs423
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Random/IRandomSource.cs (renamed from wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/IRandomSource.cs)2
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Random/NcFallbackRandom.cs (renamed from wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NcFallbackRandom.cs)6
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Random/UnmanagedRandomSource.cs (renamed from wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/UnmanagedRandomSource.cs)3
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/VNLib.Utils.Cryptography.Noscrypt.csproj4
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/internal/FunctionTable.cs74
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/internal/NCEncryptionArgs.cs31
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/internal/NCMacVerifyArgs.cs34
-rw-r--r--wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/tests/LibNoscryptTests.cs170
25 files changed, 573 insertions, 1448 deletions
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NCUtilCipher.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NCUtilCipher.cs
new file mode 100644
index 0000000..72bb75a
--- /dev/null
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NCUtilCipher.cs
@@ -0,0 +1,128 @@
+// Copyright (C) 2024 Vaughn Nugent
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+using System;
+using System.Diagnostics;
+using VNLib.Utils.Cryptography.Noscrypt.@internal;
+
+using NCResult = System.Int64;
+
+namespace VNLib.Utils.Cryptography.Noscrypt.Encryption
+{
+ internal static class NCUtilCipher
+ {
+ /*
+ * This class wraps the low-level cipher functions provided by
+ * the Noscrypt utility side-car library.
+ */
+
+ public static nint Alloc(NCContext ctx, uint version, uint flags)
+ {
+ nint cipher = GetTable(ctx).NCUtilCipherAlloc(version, flags);
+
+ if (cipher == nint.Zero)
+ {
+ throw new OutOfMemoryException("Failed to allocate cipher context");
+ }
+
+ //Ensure flags are identical to those set during allocation
+ Debug.Assert(GetFlags(ctx, cipher) == flags);
+
+ return cipher;
+ }
+
+ public static uint GetFlags(NCContext ctx, nint cipher)
+ {
+ NCResult result = GetTable(ctx).NCUtilCipherGetFlags(cipher);
+
+ NCUtil.CheckResult<FunctionTable.NCUtilCipherGetFlagsDelegate>(result, raiseOnFailure: true);
+
+ return (uint)result;
+ }
+
+ public static void Free(NCContext ctx, nint cipher) => GetTable(ctx).NCUtilCipherFree(cipher);
+
+ public static int GetIvSize(NCContext ctx, nint cipher)
+ {
+ NCResult result = GetTable(ctx).NCUtilCipherGetIvSize(cipher);
+
+ NCUtil.CheckResult<FunctionTable.NCUtilCipherGetIvSizeDelegate>(result, raiseOnFailure: true);
+
+ return checked((int)result);
+ }
+
+ public static unsafe void SetProperty(NCContext ctx, nint cipher, uint property, ref readonly byte value, uint valueLen)
+ {
+ fixed (byte* valPtr = &value)
+ {
+ NCResult result = GetTable(ctx).NCUtilCipherSetProperty(cipher, property, valPtr, valueLen);
+
+ NCUtil.CheckResult<FunctionTable.NCUtilCipherSetPropertyDelegate>(result, raiseOnFailure: true);
+ }
+ }
+
+ public static uint GetOutputSize(NCContext ctx, nint cipher)
+ {
+ NCResult result = GetTable(ctx).NCUtilCipherGetOutputSize(cipher);
+
+ NCUtil.CheckResult<FunctionTable.NCUtilCipherGetOutputSizeDelegate>(result, raiseOnFailure: true);
+
+ return (uint)result;
+ }
+
+ public static unsafe uint ReadOutput(NCContext ctx, nint cipher, ref byte outputData, uint outLen)
+ {
+ fixed (byte* outPtr = &outputData)
+ {
+ NCResult result = GetTable(ctx).NCUtilCipherReadOutput(cipher, outPtr, outLen);
+
+ NCUtil.CheckResult<FunctionTable.NCUtilCipherReadOutputDelegate>(result, raiseOnFailure: true);
+
+ return (uint)result;
+ }
+ }
+
+ public static unsafe void InitCipher(NCContext ctx, nint cipher, byte* inputPtr, uint inputSize)
+ {
+ NCResult result = GetTable(ctx).NCUtilCipherInit(cipher, inputPtr, inputSize);
+
+ NCUtil.CheckResult<FunctionTable.NCUtilCipherInitDelegate>(result, raiseOnFailure: true);
+ }
+
+ public static unsafe void Update(
+ NCContext ctx,
+ nint cipher,
+ ref readonly NCSecretKey localKey,
+ ref readonly NCPublicKey remoteKey
+ )
+ {
+ fixed (NCSecretKey* sk = &localKey)
+ fixed (NCPublicKey* pk = &remoteKey)
+ {
+ NCResult result = GetTable(ctx).NCUtilCipherUpdate(
+ cipher: cipher,
+ libContext: ctx.DangerousGetHandle(),
+ secKey: sk,
+ pubKey: pk
+ );
+
+ NCUtil.CheckResult<FunctionTable.NCUtilCipherInitDelegate>(result, raiseOnFailure: true);
+ }
+ }
+
+ private static ref readonly FunctionTable GetTable(NCContext ctx) => ref ctx.Library.Functions;
+ }
+
+}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NoscryptCipher.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NoscryptCipher.cs
new file mode 100644
index 0000000..b30ea44
--- /dev/null
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NoscryptCipher.cs
@@ -0,0 +1,227 @@
+// Copyright (C) 2024 Vaughn Nugent
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+using System;
+using System.Threading;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+using VNLib.Utils.Memory;
+using VNLib.Utils.Cryptography.Noscrypt.Random;
+using static VNLib.Utils.Cryptography.Noscrypt.NoscryptLibrary;
+
+namespace VNLib.Utils.Cryptography.Noscrypt.Encryption
+{
+ /// <summary>
+ /// The noscrypt util cipher wapper
+ /// </summary>
+ /// <param name="ctx"></param>
+ /// <param name="flags">Cipher creation flags</param>
+ /// <param name="version">The cipher specification version</param>
+ public sealed class NoscryptCipher(NCContext ctx, NoscryptCipherVersion version, NoscryptCipherFlags flags) : VnDisposeable
+ {
+ private IMemoryHandle<byte>? _ivBuffer;
+ private readonly nint _cipher = NCUtilCipher.Alloc(ctx, (uint)version, (uint)flags);
+
+ /// <summary>
+ /// The cipher standard version used by this instance
+ /// </summary>
+ public NoscryptCipherVersion Version => version;
+
+ /// <summary>
+ /// Gets the flags set for the cipher instance
+ /// </summary>
+ public uint GetFlags() => NCUtilCipher.GetFlags(ctx, _cipher);
+
+ /// <summary>
+ /// Gets the cipher's initilaization vector size (or nonce)
+ /// </summary>
+ /// <returns>The size of the IV in bytes</returns>
+ public int GetIvSize() => NCUtilCipher.GetIvSize(ctx, _cipher);
+
+ /// <summary>
+ /// Gets the internal heap buffer that holds the cipher's initalization
+ /// vector.
+ /// </summary>
+ /// <returns>The mutable span of the cipher's IV buffer</returns>
+ public Span<byte> IvBuffer
+ {
+ get => LazyInitializer.EnsureInitialized(ref _ivBuffer, AllocIvBuffer).Span;
+ }
+
+ /// <summary>
+ /// Sets the cipher's initialization vector to a random value using
+ /// the specified random source
+ /// </summary>
+ /// <param name="rng">The random source</param>
+ public void SetRandomIv(IRandomSource rng)
+ {
+ ArgumentNullException.ThrowIfNull(rng);
+ rng.GetRandomBytes(IvBuffer);
+ }
+
+ /// <summary>
+ /// Performs the cipher operation on the input data using the specified
+ /// local and remote keys.
+ /// </summary>
+ /// <param name="localKey">The secret key of the local user</param>
+ /// <param name="remoteKey">The public key of the remote user</param>
+ /// <param name="inputData">A pointer to the first byte in the buffer sequence</param>
+ /// <param name="inputSize">The size of the input buffer in bytes</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ /// <remarks>
+ /// If the <see cref="NoscryptCipherFlags.Reusable"/> flag is
+ /// set, this function may be considered independent and called repeatedly.
+ /// </remarks>
+ public unsafe void Update(
+ ref readonly NCSecretKey localKey,
+ ref readonly NCPublicKey remoteKey,
+ ref readonly byte inputData,
+ uint inputSize
+ )
+ {
+ if (Unsafe.IsNullRef(in localKey))
+ {
+ throw new ArgumentNullException(nameof(localKey));
+ }
+
+ if (Unsafe.IsNullRef(in remoteKey))
+ {
+ throw new ArgumentNullException(nameof(remoteKey));
+ }
+
+ if (Unsafe.IsNullRef(in inputData))
+ {
+ throw new ArgumentNullException(nameof(inputData));
+ }
+
+ /*
+ * Initializing the cipher requires the context holding a pointer
+ * to the input data, so it has to be pinned in a fixed statment
+ * for the duration of the update operation.
+ *
+ * So init and update must be done as an atomic operation.
+ *
+ * If ciphers have the Reusable flag set this function may be called
+ * repeatedly. The results of this operation can be considered
+ * independent.
+ */
+
+ fixed (byte* inputPtr = &inputData)
+ {
+ NCUtilCipher.InitCipher(ctx, _cipher, inputPtr, inputSize);
+
+ NCUtilCipher.Update(ctx, _cipher, in localKey, in remoteKey);
+ }
+ }
+
+ /// <summary>
+ /// Performs the cipher operation on the input data using the specified
+ /// local and remote keys.
+ /// </summary>
+ /// <param name="localKey">The secret key of the local user</param>
+ /// <param name="remoteKey">The public key of the remote user</param>
+ /// <param name="input">The buffer sequence to read the input data from</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ public void Update(
+ ref readonly NCSecretKey localKey,
+ ref readonly NCPublicKey remoteKey,
+ ReadOnlySpan<byte> input
+ )
+ {
+ Update(
+ in localKey,
+ in remoteKey,
+ inputData: ref MemoryMarshal.GetReference(input), //If empty, null ref will throw
+ inputSize: (uint)input.Length
+ );
+ }
+
+ /// <summary>
+ /// Gets the size of the output buffer required to read the cipher output
+ /// </summary>
+ /// <returns>The size of the output in bytes</returns>
+ public int GetOutputSize() => checked((int)NCUtilCipher.GetOutputSize(ctx, _cipher));
+
+ /// <summary>
+ /// Reads the output data from the cipher into the specified buffer
+ /// </summary>
+ /// <param name="outputData">A reference to the first byte in the buffer sequence</param>
+ /// <param name="size">The size of the buffer sequence</param>
+ /// <returns>The number of bytes written to the buffer</returns>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public int ReadOutput(ref byte outputData, int size)
+ {
+ ArgumentOutOfRangeException.ThrowIfLessThan(size, GetOutputSize());
+
+ return checked((int)NCUtilCipher.ReadOutput(ctx, _cipher, ref outputData, (uint)size));
+ }
+
+ /// <summary>
+ /// Reads the output data from the cipher into the specified buffer
+ /// </summary>
+ /// <param name="buffer">The buffer sequence to write output data to</param>
+ /// <returns>The number of bytes written to the buffer</returns>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public int ReadOutput(Span<byte> buffer)
+ {
+ return ReadOutput(
+ ref MemoryMarshal.GetReference(buffer),
+ buffer.Length
+ );
+ }
+
+ private IMemoryHandle<byte> AllocIvBuffer()
+ {
+ //Use the context heap to allocate the internal iv buffer
+ MemoryHandle<byte> buffer = MemoryUtil.SafeAlloc<byte>(ctx.Heap, GetIvSize(), zero: true);
+
+ try
+ {
+ /*
+ * Assign the buffer reference to the cipher context
+ *
+ * NOTE: This pointer will be held as long as the cipher
+ * context is allocated. So the buffer must be held until
+ * the cipher is freed. Because of this an umnanaged heap
+ * buffer is required so we don't need to pin managed memory
+ * nor worry about the GC moving the buffer.
+ */
+ NCUtilCipher.SetProperty(
+ ctx,
+ _cipher,
+ NC_ENC_SET_IV,
+ ref buffer.GetReference(),
+ (uint)buffer.Length
+ );
+ }
+ catch
+ {
+ buffer.Dispose();
+ throw;
+ }
+
+ return buffer;
+ }
+
+ ///<inheritdoc/>
+ protected override void Free()
+ {
+ NCUtilCipher.Free(ctx, _cipher);
+ _ivBuffer?.Dispose();
+ }
+ }
+
+}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NoscryptCipherFlags.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NoscryptCipherFlags.cs
new file mode 100644
index 0000000..275c90c
--- /dev/null
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NoscryptCipherFlags.cs
@@ -0,0 +1,60 @@
+// Copyright (C) 2024 Vaughn Nugent
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+using System;
+
+namespace VNLib.Utils.Cryptography.Noscrypt.Encryption
+{
+ /// <summary>
+ /// Cipher specific flags that control the behavior of a cipher
+ /// instance
+ /// </summary>
+ [Flags]
+ public enum NoscryptCipherFlags : uint
+ {
+ /// <summary>
+ /// Puts the cipher into encryption mode
+ /// </summary>
+ ModeEncryption = 0x00u,
+
+ /// <summary>
+ /// Puts the cipher into decryption mode
+ /// </summary>
+ ModeDecryption = 0x01u,
+
+ /// <summary>
+ /// Forces all internal memory to be freed when
+ /// the cipher is freed
+ /// </summary>
+ ZeroOnFree = 0x02u,
+
+ /// <summary>
+ /// Disables mac verification during decryption operations,
+ /// by default nip44 macs are verified before the decryption
+ /// operation.
+ /// </summary>
+ MacNoVerify = 0x04u,
+
+ /// <summary>
+ /// Allows allocated cipher instances to be reused multiple
+ /// times. Otherwise the cipher may only be used once after
+ /// allocation.
+ /// </summary>
+ Reusable = 0x08u,
+
+ EncryptDefault = ModeEncryption | Reusable | ZeroOnFree,
+ DecryptDefault = ModeDecryption | Reusable | ZeroOnFree
+ }
+}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCNip44EncryptionVersion.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NoscryptCipherVersion.cs
index 0d5907a..763a5f4 100644
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCNip44EncryptionVersion.cs
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Encryption/NoscryptCipherVersion.cs
@@ -15,25 +15,22 @@
using static VNLib.Utils.Cryptography.Noscrypt.NoscryptLibrary;
-namespace VNLib.Utils.Cryptography.Noscrypt
+namespace VNLib.Utils.Cryptography.Noscrypt.Encryption
{
/// <summary>
- /// The NIP44 encryption version used by the Nostr protocol
+ /// The Noscrypt utility cipher encryption
+ /// standard version
/// </summary>
- public sealed class NCNip44EncryptionVersion : INostrEncryptionVersion
+ public enum NoscryptCipherVersion : uint
{
/// <summary>
- /// A static nip44 encryption version instance
+ /// Tells the cipher to use the NIP04 encryption standard
/// </summary>
- public static readonly NCNip44EncryptionVersion Instance = new();
+ Nip04 = NC_ENC_VERSION_NIP04,
- ///<inheritdoc/>
- uint INostrEncryptionVersion.Version => NC_ENC_VERSION_NIP44;
-
- int INostrEncryptionVersion.GetMessageBufferSize(int dataSize) => Nip44Util.CalcFinalBufferSize(dataSize);
-
- ///<inheritdoc/>
- int INostrEncryptionVersion.GetPayloadBufferSize(int dataSize) => Nip44Util.CalcBufferSize(dataSize);
+ /// <summary>
+ /// Tells the cipher to use the NIP44 encryption standard
+ /// </summary>
+ Nip44 = NC_ENC_VERSION_NIP44
}
-
}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/INostrCrypto.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/INostrCrypto.cs
index 49c0cc0..9b4d36c 100644
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/INostrCrypto.cs
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/INostrCrypto.cs
@@ -15,6 +15,8 @@
using System;
+using VNLib.Utils.Cryptography.Noscrypt.Encryption;
+
namespace VNLib.Utils.Cryptography.Noscrypt
{
public interface INostrCrypto
@@ -39,6 +41,14 @@ namespace VNLib.Utils.Cryptography.Noscrypt
bool ValidateSecretKey(ref readonly NCSecretKey secretKey);
/// <summary>
+ /// Allocates a new cipher instance with the supplied options.
+ /// </summary>
+ /// <param name="version">The cipher specification version</param>
+ /// <param name="flags">The cipher initialziation flags</param>
+ /// <returns>The cipher instance</returns>
+ NoscryptCipher AllocCipher(NoscryptCipherVersion version, NoscryptCipherFlags flags);
+
+ /// <summary>
/// Signs the supplied data with the secret key and random32 nonce, then writes
/// the message signature to the supplied sig64 buffer.
/// </summary>
@@ -74,91 +84,5 @@ namespace VNLib.Utils.Cryptography.Noscrypt
uint dataSize,
ref readonly byte sig64
);
-
- /// <summary>
- /// Computes a nip44 message authentication code (MAC) using the supplied key and payload.
- /// </summary>
- /// <param name="hmacKey32">The key returned during a
- /// <see cref="Encrypt(ref readonly NCSecretKey, ref readonly NCPublicKey, ref readonly byte, ref readonly byte, ref byte, uint, ref byte)"/>
- /// </param>
- /// <param name="payload">A pointer to a buffer </param>
- /// <param name="payloadSize">The size of the buffer to compute the mac of, in bytes</param>
- /// <param name="hmacOut32">A pointer to the 32byte buffer to write the mac to</param>
- /// <exception cref="ArgumentException"></exception>
- /// <exception cref="ArgumentNullException"></exception>
- void ComputeMac(
- ref readonly byte hmacKey32,
- ref readonly byte payload,
- uint payloadSize,
- ref byte hmacOut32
- );
-
- /// <summary>
- /// Verifies a nip44 message authentication code (MAC) against the supplied key and payload.
- /// </summary>
- /// <param name="secretKey">A pointer to the receiver's secret key</param>
- /// <param name="publicKey">A pointer to senders the public key</param>
- /// <param name="nonce32">A pointer to the 32byte nonce buffer</param>
- /// <param name="mac32">A pointer to the 32byte message buffer</param>
- /// <param name="payload">A pointer to the message buffer</param>
- /// <param name="payloadSize">The size in bytes of the payload buffer</param>
- /// <returns>True if the message authentication code (MAC) matches, false otherwise </returns>
- /// <exception cref="ArgumentException"></exception>
- /// <exception cref="ArgumentNullException"></exception>
- bool VerifyMac(
- ref readonly NCSecretKey secretKey,
- ref readonly NCPublicKey publicKey,
- ref readonly byte nonce32,
- ref readonly byte mac32,
- ref readonly byte payload,
- uint payloadSize
- );
-
- /// <summary>
- /// Encrypts a message using the supplied secret key, public key, and nonce. When this function
- /// returns, the cipherText buffer will contain the encrypted message, and the hmacKeyOut32 buffer
- /// will contain the key used to compute the message authentication code (MAC).
- /// <para>
- /// NOTE: The cipherText buffer must be at least as large as the plaintext buffer. The
- /// size parameter must be the size of the number of bytes to encrypt.
- /// </para>
- /// </summary>
- /// <param name="secretKey">A pointer to the receiver's secret key</param>
- /// <param name="publicKey">A pointer to senders the public key</param>
- /// <param name="nonce32">A pointer to the 32byte nonce used for message encryption</param>
- /// <param name="plainText">A pointer to the plaintext buffer to encrypt</param>
- /// <param name="cipherText">A pointer to the cyphertext buffer to write encrypted data to (must be as large or larger than the plaintext buffer)</param>
- /// <param name="size">The size of the data to encrypt</param>
- /// <param name="hmacKeyOut32"></param>
- /// <exception cref="ArgumentException"></exception>
- /// <exception cref="ArgumentNullException"></exception>
- void EncryptNip44(
- ref readonly NCSecretKey secretKey,
- ref readonly NCPublicKey publicKey,
- ref readonly byte nonce32,
- ref readonly byte plainText,
- ref byte cipherText,
- uint size,
- ref byte hmacKeyOut32
- );
-
- /// <summary>
- /// Decrypts a message using the supplied secret key, public key, and the original message
- /// nonce.
- /// </summary>
- /// <param name="secretKey">A pointer to the receiver's secret key</param>
- /// <param name="publicKey">A pointer to senders the public key</param>
- /// <param name="nonce32">A pointer to the 32byte nonce used for message encryption</param>
- /// <param name="plainText">A pointer to the plaintext buffer to write plaintext data to (must be as large or larger than the ciphertext buffer)</param>
- /// <param name="cipherText">A pointer to the cyphertext buffer to read encrypted data from</param>
- /// <param name="size">The size of the buffer to decrypt</param>
- void DecryptNip44(
- ref readonly NCSecretKey secretKey,
- ref readonly NCPublicKey publicKey,
- ref readonly byte nonce32,
- ref readonly byte cipherText,
- ref byte plainText,
- uint size
- );
}
}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/INostrEncryptionVersion.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/INostrEncryptionVersion.cs
deleted file mode 100644
index 3a26466..0000000
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/INostrEncryptionVersion.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (C) 2024 Vaughn Nugent
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-namespace VNLib.Utils.Cryptography.Noscrypt
-{
- /// <summary>
- /// Represents a message encryption version used by the Nostr protocol
- /// </summary>
- public interface INostrEncryptionVersion
- {
- /// <summary>
- /// The noscrypt compatible encryption version
- /// </summary>
- internal uint Version { get; }
-
- /// <summary>
- /// Calculates the required payload buffer size for the specified data size
- /// </summary>
- /// <param name="dataSize">The size of the input data</param>
- /// <returns>The estimated size of the buffer required to complete the opeation</returns>
- internal int GetPayloadBufferSize(int dataSize);
-
- /// <summary>
- /// Calculates the required message buffer size for the specified data size
- /// </summary>
- /// <param name="dataSize">Plain text data size</param>
- /// <returns>The estimated size of the buffer required to complete the opeation</returns>
- internal int GetMessageBufferSize(int dataSize);
- }
-
-}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCContext.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCContext.cs
index 8f8c6b4..61128eb 100644
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCContext.cs
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCContext.cs
@@ -33,7 +33,7 @@ namespace VNLib.Utils.Cryptography.Noscrypt
/// </summary>
public sealed class NCContext : SafeHandleZeroOrMinusOneIsInvalid
{
- private readonly IUnmangedHeap Heap;
+ internal readonly IUnmangedHeap Heap;
/// <summary>
/// The library this context was created from
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCNip04EncryptionVersion.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCNip04EncryptionVersion.cs
deleted file mode 100644
index beb21c2..0000000
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCNip04EncryptionVersion.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2024 Vaughn Nugent
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-using static VNLib.Utils.Cryptography.Noscrypt.NoscryptLibrary;
-
-namespace VNLib.Utils.Cryptography.Noscrypt
-{
- /// <summary>
- /// The NIP04 encryption version used by the Nostr protocol
- /// </summary>
- public sealed class NCNip04EncryptionVersion : INostrEncryptionVersion
- {
- /// <summary>
- /// A static nip04 encryption version instance
- /// </summary>
- public static readonly NCNip04EncryptionVersion Instance = new();
-
- ///<inheritdoc/>
- uint INostrEncryptionVersion.Version => NC_ENC_VERSION_NIP04;
-
- ///<inheritdoc/>
- int INostrEncryptionVersion.GetMessageBufferSize(int dataSize) => Nip04Util.CalcBufferSize(dataSize);
-
- ///<inheritdoc/>
- int INostrEncryptionVersion.GetPayloadBufferSize(int dataSize) => Nip04Util.CalcBufferSize(dataSize);
- }
-
-}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCUtil.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCUtil.cs
index 49c66c1..307bbc1 100644
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCUtil.cs
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NCUtil.cs
@@ -127,35 +127,34 @@ namespace VNLib.Utils.Cryptography.Noscrypt
// Error code are only 8 bits, if an argument error occured, the
// argument number will be in the next upper 8 bits
- byte errorCode = (byte)(asPositive & 0xFF);
+ NCErrorCodes errorCode = (NCErrorCodes)(asPositive & 0xFF);
byte argNumber = (byte)((asPositive >> 8) & 0xFF);
switch (errorCode)
{
- case E_NULL_PTR:
+ case NCErrorCodes.E_NULL_PTR:
RaiseNullArgExceptionForArgumentNumber<T>(argNumber);
break;
- case E_INVALID_ARG:
+ case NCErrorCodes.E_INVALID_ARG:
RaiseArgExceptionForArgumentNumber<T>(argNumber);
break;
- case E_ARGUMENT_OUT_OF_RANGE:
+ case NCErrorCodes.E_ARGUMENT_OUT_OF_RANGE:
RaiseOORExceptionForArgumentNumber<T>(argNumber);
break;
- case E_INVALID_CTX:
+ case NCErrorCodes.E_INVALID_CTX:
throw new InvalidOperationException("The library context object is null or invalid");
- case E_OPERATION_FAILED:
+ case NCErrorCodes.E_OPERATION_FAILED:
RaiseOperationFailedException(raiseOnFailure);
break;
- case E_VERSION_NOT_SUPPORTED:
+ case NCErrorCodes.E_VERSION_NOT_SUPPORTED:
throw new NotSupportedException("The requested version is not supported");
default:
if(raiseOnFailure)
{
- throw new InvalidOperationException($"The operation failed for an unknown reason, code: {errorCode:x}");
+ throw new InvalidOperationException($"The operation failed with error, code: {errorCode} for arugment {argNumber:x}");
}
break;
-
}
}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Nip04Util.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Nip04Util.cs
deleted file mode 100644
index c1906f0..0000000
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Nip04Util.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2024 Vaughn Nugent
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-using System;
-using System.Buffers.Text;
-
-using VNLib.Utils.Extensions;
-
-namespace VNLib.Utils.Cryptography.Noscrypt
-{
- public static class Nip04Util
- {
- public static bool IsValidPayload(ReadOnlySpan<char> payload)
- {
- /* Iv is base64 encoded so it should be 33% larger than 16 byte iv */
- ReadOnlySpan<char> iv = payload.SliceAfterParam("?iv=");
- return iv.Length > 20 && iv.Length <= 26;
- }
-
- public static ReadOnlySpan<char> GetIV(ReadOnlySpan<char> payload) => payload.SliceAfterParam("?iv=");
-
- public static ReadOnlySpan<char> GetCipherText(ReadOnlySpan<char> payload) => payload.SliceBeforeParam("?iv=");
-
- public static int CalcBufferSize(int dataSize)
- {
- throw new NotImplementedException();
- }
-
- static readonly int MaxEncodedIvLength = Base64.GetMaxEncodedToUtf8Length(16);
-
- public static int CalcMessageBufferSize(int dataSize)
- {
- int bufSize = CalcBufferSize(dataSize);
- return bufSize + "?iv=".Length + MaxEncodedIvLength;
- }
- }
-
-}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Nip44MessageSegments.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Nip44MessageSegments.cs
deleted file mode 100644
index ddc2d68..0000000
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Nip44MessageSegments.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2024 Vaughn Nugent
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-using System;
-
-namespace VNLib.Utils.Cryptography.Noscrypt
-{
- public readonly ref struct Nip44MessageSegments(ReadOnlySpan<byte> payload)
- {
- readonly ReadOnlySpan<byte> _payload = payload;
-
- public ReadOnlySpan<byte> Payload => _payload;
-
- public ReadOnlySpan<byte> Nonce => Nip44Util.GetNonceFromPayload(_payload);
-
- public ReadOnlySpan<byte> Ciphertext => Nip44Util.GetCiphertextFromPayload(_payload);
-
- public ReadOnlySpan<byte> Mac => Nip44Util.GetMacFromPayload(_payload);
-
- public ReadOnlySpan<byte> NonceAndCiphertext => Nip44Util.GetNonceAndCiphertext(_payload);
-
- public byte Version => Nip44Util.GetMessageVersion(_payload);
- }
-}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Nip44Util.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Nip44Util.cs
deleted file mode 100644
index 2aebee1..0000000
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Nip44Util.cs
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright (C) 2024 Vaughn Nugent
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-using System;
-using System.Buffers.Binary;
-using System.Runtime.InteropServices;
-
-using VNLib.Utils.Memory;
-
-using static VNLib.Utils.Cryptography.Noscrypt.NoscryptLibrary;
-
-namespace VNLib.Utils.Cryptography.Noscrypt
-{
-
- /// <summary>
- /// Provides a set of utility methods for working with the Noscrypt library
- /// </summary>
- public static class Nip44Util
- {
- /// <summary>
- /// Calculates the required NIP44 encryption buffer size for
- /// the specified input data size
- /// </summary>
- /// <param name="dataSize">The size (in bytes) of the encoded data to encrypt</param>
- /// <returns>The exact size of the padded buffer output</returns>
- public static int CalcBufferSize(int dataSize)
- {
- /*
- * Taken from https://github.com/nostr-protocol/nips/blob/master/44.md
- *
- * Not gonna lie, kinda dumb branches. I guess they want to save space
- * with really tiny messages... Dunno, but whatever RTFM
- */
-
- //Min message size is 32 bytes
- int minSize = Math.Max(dataSize, 32);
-
- //find the next power of 2 that will fit the min size
- int nexPower = 1 << ((int)Math.Log2(minSize - 1)) + 1;
-
- int chunk = nexPower <= 256 ? 32 : nexPower / 8;
-
- return (chunk * ((int)Math.Floor((double)((minSize - 1) / chunk)) + 1)) + sizeof(ushort);
- }
-
- /// <summary>
- /// Calculates the final buffer size required to hold the encrypted data
- /// </summary>
- /// <param name="dataSize">The size (in bytes) of plaintext data to encrypt</param>
- /// <returns>The number of bytes required to store the final nip44 message</returns>
- public static int CalcFinalBufferSize(int dataSize)
- {
- /* version + nonce + payload + mac */
- return CalcBufferSize(dataSize) + NC_ENCRYPTION_NONCE_SIZE + NC_ENCRYPTION_MAC_SIZE + 1;
- }
-
- /// <summary>
- /// Formats the plaintext data into a buffer that can be properly encrypted.
- /// The output buffer must be zeroed, or can be zeroed using the
- /// <paramref name="zeroOutput"/> parameter. Use <see cref="CalcBufferSize(uint)"/>
- /// to determine the required output buffer size.
- /// </summary>
- /// <param name="plaintextData">A buffer containing plaintext data to copy to the output</param>
- /// <param name="output">The output data buffer to format</param>
- /// <param name="zeroOutput">A value that indicates if the buffer should be zeroed before use</param>
- public static void FormatBuffer(ReadOnlySpan<byte> plaintextData, Span<byte> output, bool zeroOutput)
- {
- //First zero out the buffer
- if (zeroOutput)
- {
- MemoryUtil.InitializeBlock(output);
- }
-
- //Make sure the output buffer is large enough so we dont overrun it
- ArgumentOutOfRangeException.ThrowIfLessThan(output.Length, plaintextData.Length + sizeof(ushort), nameof(output));
-
- //Write the data size to the first 2 bytes
- ushort dataSize = (ushort)plaintextData.Length;
- BinaryPrimitives.WriteUInt16BigEndian(output, dataSize);
-
- //Copy the plaintext data to the output buffer after the data size
- MemoryUtil.Memmove(
- src: in MemoryMarshal.GetReference(plaintextData),
- srcOffset: 0,
- dst: ref MemoryMarshal.GetReference(output),
- dstOffset: sizeof(ushort),
- elementCount: (uint)plaintextData.Length
- );
-
- //We assume the remaining buffer is zeroed out
- }
-
- public static void WriteNip44Message(
- ReadOnlySpan<byte> payloadBuffer,
- byte version,
- ReadOnlySpan<byte> mac,
- Span<byte> outBuffer
- )
- {
- int requiredBufferSize = CalcFinalBufferSize(payloadBuffer.Length);
-
- //Make sure the output buffer is large enough so we dont overrun it
- ArgumentOutOfRangeException.ThrowIfLessThan(outBuffer.Length, requiredBufferSize, nameof(outBuffer));
- ArgumentOutOfRangeException.ThrowIfLessThan(mac.Length, NC_ENCRYPTION_MAC_SIZE, nameof(mac));
-
- //Write the version number to the first byte
- outBuffer[0] = version;
-
- //Copy the payload buffer to the output buffer after the version number
- MemoryUtil.Memmove(
- src: in MemoryMarshal.GetReference(payloadBuffer),
- srcOffset: 0,
- dst: ref MemoryMarshal.GetReference(outBuffer),
- dstOffset: 1,
- elementCount: (uint)payloadBuffer.Length
- );
-
- //Copy the mac to the end of the output buffer
- MemoryUtil.Memmove(
- src: in MemoryMarshal.GetReference(mac),
- srcOffset: 0,
- dst: ref MemoryMarshal.GetReference(outBuffer),
- dstOffset: (uint)(requiredBufferSize - NC_ENCRYPTION_MAC_SIZE),
- elementCount: NC_ENCRYPTION_MAC_SIZE
- );
- }
-
- public static ReadOnlySpan<byte> GetNonceFromPayload(ReadOnlySpan<byte> message)
- {
- //The nonce is 32 bytes following the 1st byte version number of the message
- return message.Slice(1, NC_ENCRYPTION_NONCE_SIZE);
- }
-
- public static ReadOnlySpan<byte> GetCiphertextFromPayload(ReadOnlySpan<byte> message)
- {
- //Message is between the nonce and the trailing mac
- int payloadSize = message.Length - (1 + NC_ENCRYPTION_NONCE_SIZE + NC_ENCRYPTION_MAC_SIZE);
- return message.Slice(1 + NC_ENCRYPTION_NONCE_SIZE, payloadSize);
- }
-
- public static ReadOnlySpan<byte> GetMacFromPayload(ReadOnlySpan<byte> message)
- {
- //The mac is the last 32 bytes of the message
- return message[^NC_ENCRYPTION_MAC_SIZE..];
- }
-
- public static ReadOnlySpan<byte> GetNonceAndCiphertext(ReadOnlySpan<byte> message)
- {
- //The nonce is 32 bytes following the 1st byte version number of the message
- return message.Slice(1, NC_ENCRYPTION_NONCE_SIZE + GetCiphertextFromPayload(message).Length);
- }
-
- public static byte GetMessageVersion(ReadOnlySpan<byte> message)
- {
- //The first byte is the message version
- return message[0];
- }
-
- public static ReadOnlySpan<byte> GetPlaintextMessage(ReadOnlySpan<byte> plaintextPayload)
- {
- ushort ptLength = BinaryPrimitives.ReadUInt16BigEndian(plaintextPayload);
- return plaintextPayload.Slice(sizeof(ushort), ptLength);
- }
-
- public static bool IsValidPlaintextMessage(ReadOnlySpan<byte> plaintextPayload)
- {
- ushort ptLength = BinaryPrimitives.ReadUInt16BigEndian(plaintextPayload);
- return ptLength == plaintextPayload.Length - sizeof(ushort);
- }
-
- public static Range GetPlaintextRange(ReadOnlySpan<byte> plaintextPayload)
- {
- ushort ptLength = BinaryPrimitives.ReadUInt16BigEndian(plaintextPayload);
- return new Range(sizeof(ushort), ptLength);
- }
- }
-
-}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptExtensions.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptExtensions.cs
index ccae190..e96ff96 100644
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptExtensions.cs
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptExtensions.cs
@@ -24,168 +24,6 @@ namespace VNLib.Utils.Cryptography.Noscrypt
public static class NoscryptExtensions
{
- public static void EncryptNip44(
- this INostrCrypto lib,
- ref readonly NCSecretKey secretKey,
- ref readonly NCPublicKey publicKey,
- ReadOnlySpan<byte> nonce32,
- ReadOnlySpan<byte> plainText,
- Span<byte> hmackKeyOut32,
- Span<byte> cipherText
- )
- {
- ArgumentNullException.ThrowIfNull(lib);
-
- //Chacha requires the output buffer to be at-least the size of the input buffer
- ArgumentOutOfRangeException.ThrowIfGreaterThan(plainText.Length, cipherText.Length, nameof(plainText));
-
- //Nonce must be exactly 32 bytes
- ArgumentOutOfRangeException.ThrowIfNotEqual(nonce32.Length, NC_ENCRYPTION_NONCE_SIZE, nameof(nonce32));
-
- ArgumentOutOfRangeException.ThrowIfNotEqual(hmackKeyOut32.Length, NC_HMAC_KEY_SIZE, nameof(hmackKeyOut32));
-
- //Encrypt data, use the plaintext buffer size as the data size
- lib.EncryptNip44(
- secretKey: in secretKey,
- publicKey: in publicKey,
- nonce32: in MemoryMarshal.GetReference(nonce32),
- plainText: in MemoryMarshal.GetReference(plainText),
- cipherText: ref MemoryMarshal.GetReference(cipherText),
- size: (uint)plainText.Length,
- hmacKeyOut32: ref MemoryMarshal.GetReference(hmackKeyOut32)
- );
- }
-
- public static unsafe void EncryptNip44(
- this INostrCrypto lib,
- ref NCSecretKey secretKey,
- ref NCPublicKey publicKey,
- void* nonce32,
- void* hmacKeyOut32,
- void* plainText,
- void* cipherText,
- uint size
- )
- {
- ArgumentNullException.ThrowIfNull(plainText);
- ArgumentNullException.ThrowIfNull(cipherText);
- ArgumentNullException.ThrowIfNull(nonce32);
-
- //Spans are easer to forward references from pointers without screwing up arguments
- lib.EncryptNip44(
- secretKey: in secretKey,
- publicKey: in publicKey,
- nonce32: in Unsafe.AsRef<byte>(nonce32),
- plainText: in Unsafe.AsRef<byte>(plainText),
- cipherText: ref Unsafe.AsRef<byte>(cipherText),
- size: size,
- hmacKeyOut32: ref Unsafe.AsRef<byte>(hmacKeyOut32)
- );
- }
-
-
- public static void DecryptNip44(
- this INostrCrypto lib,
- ref readonly NCSecretKey secretKey,
- ref readonly NCPublicKey publicKey,
- ReadOnlySpan<byte> nonce32,
- ReadOnlySpan<byte> cipherText,
- Span<byte> plainText
- )
- {
- ArgumentNullException.ThrowIfNull(lib);
-
- //Chacha requires the output buffer to be at-least the size of the input buffer
- ArgumentOutOfRangeException.ThrowIfGreaterThan(cipherText.Length, plainText.Length, nameof(cipherText));
-
- //Nonce must be exactly 32 bytes
- ArgumentOutOfRangeException.ThrowIfNotEqual(nonce32.Length, 32, nameof(nonce32));
-
- //Decrypt data, use the ciphertext buffer size as the data size
- lib.DecryptNip44(
- secretKey: in secretKey,
- publicKey: in publicKey,
- nonce32: in MemoryMarshal.GetReference(nonce32),
- cipherText: in MemoryMarshal.GetReference(cipherText),
- plainText: ref MemoryMarshal.GetReference(plainText),
- size: (uint)cipherText.Length
- );
- }
-
- public static unsafe void DecryptNip44(
- this INostrCrypto lib,
- ref readonly NCSecretKey secretKey,
- ref readonly NCPublicKey publicKey,
- void* nonce32,
- void* cipherText,
- void* plainText,
- uint size
- )
- {
- ArgumentNullException.ThrowIfNull(nonce32);
- ArgumentNullException.ThrowIfNull(cipherText);
- ArgumentNullException.ThrowIfNull(plainText);
-
- //Spans are easer to forward references from pointers without screwing up arguments
- DecryptNip44(
- lib: lib,
- secretKey: in secretKey,
- publicKey: in publicKey,
- nonce32: new Span<byte>(nonce32, NC_ENCRYPTION_NONCE_SIZE),
- cipherText: new Span<byte>(cipherText, (int)size),
- plainText: new Span<byte>(plainText, (int)size)
- );
- }
-
- public static bool VerifyMac(
- this INostrCrypto lib,
- ref readonly NCSecretKey secretKey,
- ref readonly NCPublicKey publicKey,
- ReadOnlySpan<byte> nonce32,
- ReadOnlySpan<byte> mac32,
- ReadOnlySpan<byte> payload
- )
- {
- ArgumentNullException.ThrowIfNull(lib);
- ArgumentOutOfRangeException.ThrowIfZero(payload.Length, nameof(payload));
- ArgumentOutOfRangeException.ThrowIfNotEqual(nonce32.Length, NC_ENCRYPTION_NONCE_SIZE, nameof(nonce32));
- ArgumentOutOfRangeException.ThrowIfNotEqual(mac32.Length, NC_ENCRYPTION_MAC_SIZE, nameof(mac32));
-
- //Verify the HMAC
- return lib.VerifyMac(
- secretKey: in secretKey,
- publicKey: in publicKey,
- nonce32: in MemoryMarshal.GetReference(nonce32),
- mac32: in MemoryMarshal.GetReference(mac32),
- payload: in MemoryMarshal.GetReference(payload),
- payloadSize: (uint)payload.Length
- );
- }
-
- public static unsafe bool VerifyMac(
- this INostrCrypto lib,
- ref readonly NCSecretKey secretKey,
- ref readonly NCPublicKey publicKey,
- void* nonce32,
- void* mac32,
- void* payload,
- uint payloadSize
- )
- {
- ArgumentNullException.ThrowIfNull(nonce32);
- ArgumentNullException.ThrowIfNull(mac32);
- ArgumentNullException.ThrowIfNull(payload);
-
- return lib.VerifyMac(
- secretKey: in secretKey,
- publicKey: in publicKey,
- nonce32: in Unsafe.AsRef<byte>(nonce32),
- mac32: in Unsafe.AsRef<byte>(mac32),
- payload: in Unsafe.AsRef<byte>(payload),
- payloadSize: payloadSize
- );
- }
-
public static void SignData(
this INostrCrypto lib,
ref readonly NCSecretKey secKey,
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptLibrary.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptLibrary.cs
index 108a713..35c6a49 100644
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptLibrary.cs
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptLibrary.cs
@@ -16,10 +16,12 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
+
using VNLib.Utils.Memory;
using VNLib.Utils.Native;
using VNLib.Utils.Extensions;
+using VNLib.Utils.Cryptography.Noscrypt.Random;
using VNLib.Utils.Cryptography.Noscrypt.@internal;
using NCResult = System.Int64;
@@ -39,7 +41,6 @@ namespace VNLib.Utils.Cryptography.Noscrypt
//Constant values match the noscrypt.h header
public const int NC_SEC_KEY_SIZE = 0x20;
public const int NC_SEC_PUBKEY_SIZE = 0x20;
- public const int NC_ENCRYPTION_NONCE_SIZE = 0x20;
public const int NC_PUBKEY_SIZE = 0x20;
public const int NC_SIGNATURE_SIZE = 0x40;
public const int NC_CONV_KEY_SIZE = 0x20;
@@ -54,19 +55,37 @@ namespace VNLib.Utils.Cryptography.Noscrypt
public const uint NC_ENC_VERSION_NIP44 = 0x00000002c;
public const uint NC_ENC_SET_VERSION = 0x01u;
- public const uint NC_ENC_SET_NIP44_NONCE = 0x02u;
+ public const uint NC_ENC_SET_IV = 0x02u;
public const uint NC_ENC_SET_NIP44_MAC_KEY = 0x03u;
public const uint NC_ENC_SET_NIP04_KEY = 0x04u;
- public const uint NC_ENC_SET_NIP04_IV = 0x05u;
- //Noscrypt error codes
public const NCResult NC_SUCCESS = 0x00;
- public const byte E_NULL_PTR = 0x01;
- public const byte E_INVALID_ARG = 0x02;
- public const byte E_INVALID_CTX = 0x03;
- public const byte E_ARGUMENT_OUT_OF_RANGE = 0x04;
- public const byte E_OPERATION_FAILED = 0x05;
- public const byte E_VERSION_NOT_SUPPORTED = 0x06;
+
+ public enum NCErrorCodes : long
+ {
+ NC_SUCCESS = 0,
+
+ //Generic argument related errors
+ E_NULL_PTR = 1,
+ E_INVALID_ARG = 2,
+ E_INVALID_CTX = 3,
+ E_ARGUMENT_OUT_OF_RANGE = 4,
+ E_OPERATION_FAILED = 5,
+ E_VERSION_NOT_SUPPORTED = 6,
+
+ //Cipher errors
+ E_CIPHER_INVALID_FORMAT = 11,
+ E_CIPHER_BAD_NONCE = 12,
+ E_CIPHER_MAC_INVALID = 13,
+ E_CIPHER_NO_OUTPUT = 14,
+ E_CIPHER_BAD_INPUT = 15,
+ E_CIPHER_BAD_INPUT_SIZE = 16
+ }
+
+ //Cipher flags
+ public const uint NC_UTIL_CIPHER_MODE = 0x01u;
+
+
private readonly FunctionTable _functions = FunctionTable.BuildFunctionTable(Library);
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptSigner.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptSigner.cs
index 586fa46..c81790b 100644
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptSigner.cs
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NoscryptSigner.cs
@@ -14,7 +14,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
using System;
-
+using VNLib.Utils.Cryptography.Noscrypt.Random;
using VNLib.Utils.Extensions;
using VNLib.Utils.Memory;
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NostrCrypto.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NostrCrypto.cs
index 36e2381..1e833d2 100644
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NostrCrypto.cs
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NostrCrypto.cs
@@ -18,13 +18,13 @@ using System.Runtime.CompilerServices;
using System.Diagnostics.CodeAnalysis;
using VNLib.Utils.Cryptography.Noscrypt.@internal;
+using VNLib.Utils.Cryptography.Noscrypt.Encryption;
using static VNLib.Utils.Cryptography.Noscrypt.NoscryptLibrary;
using NCResult = System.Int64;
namespace VNLib.Utils.Cryptography.Noscrypt
{
-
/// <summary>
/// A default implementation of the <see cref="INostrCrypto"/> interface
/// </summary>
@@ -39,78 +39,7 @@ namespace VNLib.Utils.Cryptography.Noscrypt
private ref readonly FunctionTable Functions => ref context.Library.Functions;
///<inheritdoc/>
- public void DecryptNip44(
- ref readonly NCSecretKey secretKey,
- ref readonly NCPublicKey publicKey,
- ref readonly byte nonce32,
- ref readonly byte cipherText,
- ref byte plainText,
- uint size
- )
- {
- Check();
-
- ThrowIfNullRef(in nonce32, nameof(nonce32));
-
- fixed (NCSecretKey* pSecKey = &secretKey)
- fixed (NCPublicKey* pPubKey = &publicKey)
- fixed (byte* pCipherText = &cipherText, pTextPtr = &plainText, pNonce = &nonce32)
- {
- NCEncryptionArgs data = new();
-
- //Version set first otherwise errors will occur
- SetEncProperty(&data, NC_ENC_SET_VERSION, NC_ENC_VERSION_NIP44);
- //Only the nonce must be set, the hmac key is not needed for decryption
- SetEncPropertyEx(&data, NC_ENC_SET_NIP44_NONCE, pNonce, NC_ENCRYPTION_NONCE_SIZE);
- SetEncData(&data, pTextPtr, pCipherText, size);
-
- NCResult result = Functions.NCDecrypt.Invoke(context.DangerousGetHandle(), pSecKey, pPubKey, &data);
- NCUtil.CheckResult<FunctionTable.NCDecryptDelegate>(result, true);
- }
- }
-
- ///<inheritdoc/>
- public void EncryptNip44(
- ref readonly NCSecretKey secretKey,
- ref readonly NCPublicKey publicKey,
- ref readonly byte nonce32,
- ref readonly byte plainText,
- ref byte cipherText,
- uint size,
- ref byte hmackKeyOut32
- )
- {
- Check();
-
- ThrowIfNullRef(in nonce32, nameof(nonce32));
-
- fixed (NCSecretKey* pSecKey = &secretKey)
- fixed (NCPublicKey* pPubKey = &publicKey)
- fixed (byte* pCipherText = &cipherText,
- pTextPtr = &plainText,
- pHmacKeyOut = &hmackKeyOut32,
- pNonce = &nonce32
- )
- {
- NCEncryptionArgs data = new();
-
- /*
- * Use the extended api to set properties correctly and validate them.
- *
- * The version MUST be set before continuing to set properties
- *
- * Since pointers are used, they must be only be set/accessed inside
- * this fixed statement.
- */
- SetEncProperty(&data, NC_ENC_SET_VERSION, NC_ENC_VERSION_NIP44);
- SetEncPropertyEx(&data, NC_ENC_SET_NIP44_MAC_KEY, pHmacKeyOut, NC_HMAC_KEY_SIZE);
- SetEncPropertyEx(&data, NC_ENC_SET_NIP44_NONCE, pNonce, NC_ENCRYPTION_NONCE_SIZE);
- SetEncData(&data, pTextPtr, pCipherText, size);
-
- NCResult result = Functions.NCEncrypt.Invoke(context.DangerousGetHandle(), pSecKey, pPubKey, &data);
- NCUtil.CheckResult<FunctionTable.NCEncryptDelegate>(result, true);
- }
- }
+ public NoscryptCipher AllocCipher(NoscryptCipherVersion version, NoscryptCipherFlags flags) => new (context, version, flags);
///<inheritdoc/>
public void GetPublicKey(ref readonly NCSecretKey secretKey, ref NCPublicKey publicKey)
@@ -192,63 +121,6 @@ namespace VNLib.Utils.Cryptography.Noscrypt
}
}
- ///<inheritdoc/>
- public bool VerifyMac(
- ref readonly NCSecretKey secretKey,
- ref readonly NCPublicKey publicKey,
- ref readonly byte nonce32,
- ref readonly byte mac32,
- ref readonly byte payload,
- uint payloadSize
- )
- {
- Check();
-
- //Check pointers we need to use
- ThrowIfNullRef(in nonce32, nameof(nonce32));
- ThrowIfNullRef(in mac32, nameof(mac32));
- ThrowIfNullRef(in payload, nameof(payload));
-
- fixed (NCSecretKey* pSecKey = &secretKey)
- fixed (NCPublicKey* pPubKey = &publicKey)
- fixed (byte* pPayload = &payload, pMac = &mac32, pNonce = &nonce32)
- {
-
- NCMacVerifyArgs args = new()
- {
- payloadSize = payloadSize,
- payload = pPayload,
- mac32 = pMac,
- nonce32 = pNonce
- };
-
- //Exec and bypass failure
- NCResult result = Functions.NCVerifyMac.Invoke(context.DangerousGetHandle(), pSecKey, pPubKey, &args);
- NCUtil.CheckResult<FunctionTable.NCVerifyMacDelegate>(result, false);
-
- //Result should be success if the hmac is valid
- return result == NC_SUCCESS;
- }
- }
-
- ///<inheritdoc/>
- public void ComputeMac(
- ref readonly byte hmacKey32,
- ref readonly byte payload,
- uint payloadSize,
- ref byte hmacOut32
- )
- {
- Check();
-
- //Library will check for null pointers, since they are all arguments
- fixed (byte* pKey = &hmacKey32, pPayload = &payload, pOut = &hmacOut32)
- {
- NCResult result = Functions.NCComputeMac.Invoke(context.DangerousGetHandle(), pKey, pPayload, payloadSize, pOut);
- NCUtil.CheckResult<FunctionTable.NCComputeMacDelegate>(result, true);
- }
- }
-
#if DEBUG
/// <summary>
@@ -275,33 +147,6 @@ namespace VNLib.Utils.Cryptography.Noscrypt
}
#endif
-
-
- private void SetEncPropertyEx(NCEncryptionArgs* args, uint prop, byte* value, uint valueLen)
- {
- NCResult result = Functions.NCSetEncryptionPropertyEx(args, prop, value, valueLen);
- NCUtil.CheckResult<FunctionTable.NCSetEncryptionPropertyExDelegate>(result, true);
- }
-
- private void SetEncProperty(NCEncryptionArgs* args, uint prop, uint value)
- {
- NCResult result = Functions.NCSetEncryptionProperty(args, prop, value);
- NCUtil.CheckResult<FunctionTable.NCSetEncryptionPropertyExDelegate>(result, true);
- }
-
- private void SetEncData(NCEncryptionArgs* args, byte* input, byte* output, uint dataLen)
- {
- /*
- * WARNING:
- * For now this a short-cut for setting the input and output data pointers
- * technically this still works and avoids the PInvoke call, but this may
- * change in the future.
- */
- args->dataSize = dataLen;
- args->inputData = input;
- args->outputData = output;
- }
-
///<inheritdoc/>
protected override void Free()
{
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NostrMessageCipher.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NostrMessageCipher.cs
deleted file mode 100644
index 918d196..0000000
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NostrMessageCipher.cs
+++ /dev/null
@@ -1,423 +0,0 @@
-// Copyright (C) 2024 Vaughn Nugent
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-using System;
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Security.Authentication;
-
-using VNLib.Utils.Memory;
-
-using static VNLib.Utils.Cryptography.Noscrypt.NoscryptLibrary;
-
-namespace VNLib.Utils.Cryptography.Noscrypt
-{
-
- public sealed class NostrMessageCipher(INostrCrypto lib, INostrEncryptionVersion version) : VnDisposeable
- {
- const int Nip44MaxMessageSize = 65603;
-
- private readonly INostrCrypto library = lib;
-
- private NCSecretKey _fromKey;
- private NCPublicKey _toKey;
- private Buffer32 _nonce32;
- private Buffer32 _mac32;
-
- /// <summary>
- /// The message encryption version used by this instance
- /// </summary>
- public uint Version { get; } = version.Version;
-
- /// <summary>
- /// The message nonce created during encryption event
- /// </summary>
- public unsafe Span<byte> Nonce => MemoryMarshal.CreateSpan(ref GetNonceRef(), sizeof(Buffer32));
-
- /// <summary>
- /// The message MAC set during encryption, and required for decryption
- /// </summary>
- public unsafe Span<byte> Mac => MemoryMarshal.CreateSpan(ref GetMacRef(), sizeof(Buffer32));
-
- /// <summary>
- /// Gets the size of the buffer required to encrypt the specified data size
- /// </summary>
- /// <param name="dataSize">The size of the message raw plaintext message to send</param>
- /// <returns>The minimum number of bytes required for message encryption output</returns>
- /// <exception cref="NotSupportedException"></exception>
- public int GetPayloadBufferSize(int dataSize)
- => version.GetPayloadBufferSize(dataSize);
-
- /// <summary>
- /// Gets the size of the buffer required to hold the full encrypted message data
- /// for the encryption version used
- /// </summary>
- /// <param name="dataSize">The plaintext data size</param>
- /// <returns>The estimated size of the output buffer</returns>
- public int GetMessageBufferSize(int dataSize)
- => version.GetMessageBufferSize(dataSize);
-
- /// <summary>
- /// Sets the encryption secret key for the message
- /// </summary>
- /// <param name="secKey">The secret key buffer</param>
- /// <returns>The current instance for chaining</returns>
- /// <exception cref="ArgumentException"></exception>
- public NostrMessageCipher SetSecretKey(ReadOnlySpan<byte> secKey)
- => SetSecretKey(in NCUtil.AsSecretKey(secKey));
-
- /// <summary>
- /// Sets the encryption secret key for the message
- /// </summary>
- /// <param name="secKey">The secret key structure to copy</param>
- /// <returns>The current instance for chaining</returns>
- /// <exception cref="ArgumentException"></exception>
- public NostrMessageCipher SetSecretKey(ref readonly NCSecretKey secKey)
- {
- MemoryUtil.CloneStruct(in secKey, ref _fromKey);
- return this;
- }
-
- /// <summary>
- /// Assigns the public key used to encrypt the message as the
- /// receiver of the message
- /// </summary>
- /// <param name="pubKey">The user's public key receiving the message</param>
- /// <returns>The current instance for chaining</returns>
- /// <exception cref="ArgumentException"></exception>
- public NostrMessageCipher SetPublicKey(ReadOnlySpan<byte> pubKey)
- => SetPublicKey(in NCUtil.AsPublicKey(pubKey));
-
- /// <summary>
- /// Assigns the public key used to encrypt the message as the
- /// receiver of the message
- /// </summary>
- /// <param name="pubKey">The user's public key receiving the message</param>
- /// <returns>The current instance for chaining</returns>
- /// <exception cref="ArgumentException"></exception>
- public NostrMessageCipher SetPublicKey(ref readonly NCPublicKey pubKey)
- {
- MemoryUtil.CloneStruct(in pubKey, ref _toKey);
- return this;
- }
-
- /// <summary>
- /// Assigns the nonce to the message. Must be <see cref="NC_ENCRYPTION_NONCE_SIZE"/>
- /// in length
- /// </summary>
- /// <param name="nonce">The nonce value to copy</param>
- /// <returns>The current instance for chaining</returns>
- /// <exception cref="ArgumentException"></exception>
- public NostrMessageCipher SetNonce(ReadOnlySpan<byte> nonce)
- {
- MemoryUtil.CopyStruct(nonce, ref _nonce32);
- return this;
- }
-
- /// <summary>
- /// Assigns a random nonce using the specified random source
- /// </summary>
- /// <param name="rng">The random source to genrate a random nonce from</param>
- /// <returns>The current instance for chaining</returns>
- public NostrMessageCipher SetRandomNonce(IRandomSource rng)
- {
- rng.GetRandomBytes(Nonce);
- return this;
- }
-
- /// <summary>
- /// Configures a 32 byte mac for the message for nip44 decryption
- /// </summary>
- /// <param name="mac">The message mac</param>
- /// <returns>The current instance for chaining</returns>
- public NostrMessageCipher SetMac(ReadOnlySpan<byte> mac)
- {
- MemoryUtil.CopyStruct(mac, ref _mac32);
- return this;
- }
-
- /// <summary>
- /// Decrypts a full nostr encrypted message and writes the plaintext
- /// data to the output buffer
- /// </summary>
- /// <param name="message">The nostr message buffer to decrypt</param>
- /// <param name="plaintext">The output plaintext buffer</param>
- /// <returns>The number of bytes written the the plaintext buffer</returns>
- /// <exception cref="FormatException"></exception>
- /// <exception cref="NotSupportedException"></exception>
- public int DecryptMessage(ReadOnlySpan<byte> message, Span<byte> plaintext)
- {
- return Version switch
- {
- NC_ENC_VERSION_NIP44 => DecryptNip44Message(message, plaintext),
- _ => throw new NotSupportedException("NIP04 encryption is not supported"),
- };
- }
-
- /// <summary>
- /// Encrypts the plaintext message and writes the encrypted message to the
- /// specified buffer. The output matches the format of the full nostr message
- /// for the specified encryption version
- /// </summary>
- /// <param name="plaintext">The plaintext data to be encrypted</param>
- /// <param name="message">The buffer to write the encrypted message data to</param>
- /// <returns>The number of bytes written to the message buffer</returns>
- /// <exception cref="NotSupportedException"></exception>
- public int EncryptMessage(ReadOnlySpan<byte> plaintext, Span<byte> message)
- {
- return Version switch
- {
- NC_ENC_VERSION_NIP44 => EncryptNip44Message(plaintext, message),
- _ => throw new NotSupportedException("NIP04 encryption is not supported"),
- };
- }
-
- private int EncryptNip44Message(ReadOnlySpan<byte> plaintext, Span<byte> message)
- {
- int minRequiredOutSize = Nip44Util.CalcFinalBufferSize(plaintext.Length);
-
- ArgumentOutOfRangeException.ThrowIfZero(plaintext.Length, nameof(plaintext));
- ArgumentOutOfRangeException.ThrowIfLessThan(message.Length, minRequiredOutSize, nameof(message));
-
- ForwardOnlyWriter<byte> messageWriter = new(message);
-
- // From spec -> concat(version, nonce, ciphertext, mac)
- messageWriter.Append(0x02); // Version
- messageWriter.Append<byte>(Nonce); // nonce
-
- //Encrypt plaintext and write directly the message buffer
- int written = EncryptPayload(plaintext, messageWriter.Remaining);
-
- messageWriter.Advance(written);
-
- //Append the message mac, it was writen after the encryption operation
- messageWriter.Append<byte>(Mac);
-
- return messageWriter.Written;
- }
-
- /// <summary>
- /// Encrypts the plaintext message and writes the encrypted message to the
- /// specified buffer, along with a 32 byte mac of the message
- /// </summary>
- /// <param name="plaintext">The plaintext data to encrypt</param>
- /// <param name="message">The message output buffer to write encrypted data to</param>
- /// <param name="macOut32">A buffer to write the computed message mac to</param>
- /// <returns>The number of bytes writtn to the message output buffer</returns>
- /// <remarks>
- /// The message buffer must be at-least the size of the output buffer, and it is not
- /// initialized before the encryption operation.
- /// </remarks>
- /// <exception cref="ArgumentOutOfRangeException"></exception>
- public int EncryptPayload(ReadOnlySpan<byte> plaintext, Span<byte> message)
- {
- return Version switch
- {
- NC_ENC_VERSION_NIP44 => EncryptNip44(plaintext, message),
- _ => throw new NotSupportedException("NIP04 encryption is not supported"),
- };
- }
-
- private int EncryptNip44(ReadOnlySpan<byte> plaintext, Span<byte> message)
- {
- int payloadSize = GetPayloadBufferSize(plaintext.Length);
-
- ArgumentOutOfRangeException.ThrowIfZero(plaintext.Length, nameof(plaintext));
- ArgumentOutOfRangeException.ThrowIfZero(message.Length, nameof(message));
- ArgumentOutOfRangeException.ThrowIfLessThan(message.Length, payloadSize, nameof(message));
-
- /*
- * Alloc temp buffer to copy formatted payload to data to for the encryption
- * operation. Encryption will write directly to the message buffer
- */
-
- using UnsafeMemoryHandle<byte> ptPayloadBuf = MemoryUtil.UnsafeAllocNearestPage<byte>(payloadSize, true);
- using UnsafeMemoryHandle<byte> hmacKeyBuf = MemoryUtil.UnsafeAlloc<byte>(NC_HMAC_KEY_SIZE, true);
-
- Debug.Assert(hmacKeyBuf.Length == NC_HMAC_KEY_SIZE);
-
- Nip44Util.FormatBuffer(plaintext, ptPayloadBuf.Span, false);
-
- library.EncryptNip44(
- secretKey: in _fromKey,
- publicKey: in _toKey,
- nonce32: in GetNonceRef(),
- plainText: in ptPayloadBuf.GetReference(),
- cipherText: ref MemoryMarshal.GetReference(message),
- size: (uint)payloadSize, //IMPORTANT: Format buffer will pad the buffer to the exact size
- hmacKeyOut32: ref hmacKeyBuf.GetReference() //Must set the hmac key buffer
- );
-
-
- //Compute message mac, key should be set by the encryption operation
- library.ComputeMac(
- hmacKey32: in hmacKeyBuf.GetReference(),
- payload: in MemoryMarshal.GetReference(message),
- payloadSize: (uint)payloadSize, //Again set exact playload size
- hmacOut32: ref GetMacRef()
- );
-
- //Clear buffers
- MemoryUtil.InitializeBlock(ref hmacKeyBuf.GetReference(), hmacKeyBuf.IntLength);
- MemoryUtil.InitializeBlock(ref ptPayloadBuf.GetReference(), ptPayloadBuf.IntLength);
-
- return payloadSize;
- }
-
- private int DecryptNip44Message(ReadOnlySpan<byte> message, Span<byte> plaintext)
- {
- //Full Nip44 messages must be at-least 99 bytes in length
- ArgumentOutOfRangeException.ThrowIfLessThan(message.Length, 99, nameof(message));
- ArgumentOutOfRangeException.ThrowIfGreaterThan(message.Length, Nip44MaxMessageSize, nameof(message));
-
- //Message decoder used to get the nip44 message segments
- Nip44MessageSegments msg = new(message);
-
- if (msg.Version != 0x02)
- {
- return 0;
- }
-
- SetNonce(msg.Nonce);
- SetMac(msg.Mac);
-
- //Temporary buffer to write decrypted plaintext data to
- using UnsafeMemoryHandle<byte> plaintextBuffer = MemoryUtil.UnsafeAllocNearestPage<byte>(msg.Ciphertext.Length, true);
-
- int written = DecryptPayload(msg.Ciphertext, plaintextBuffer.Span);
-
- Span<byte> ptOut = plaintextBuffer.AsSpan(0, written);
-
- //Must check message bounds before returning a range
- if (!Nip44Util.IsValidPlaintextMessage(ptOut))
- {
- throw new FormatException("Plaintext data was not properly encrypted because it was not properly formatted or decryption failed");
- }
-
- Range msgRange = Nip44Util.GetPlaintextRange(ptOut);
- Debug.Assert(msgRange.Start.Value > 0);
- Debug.Assert(msgRange.End.Value > 0);
-
- int ptLength = msgRange.End.Value - msgRange.Start.Value;
-
- Debug.Assert(ptLength > 0);
-
- //Write the wrapped plaintext (unpadded) to the output plaintext buffer
- MemoryUtil.Memmove(
- src: in plaintextBuffer.GetReference(),
- srcOffset: (uint)msgRange.Start.Value,
- dst: ref MemoryMarshal.GetReference(plaintext),
- dstOffset: 0,
- elementCount: (uint)ptLength
- );
-
- return ptLength;
- }
-
- /// <summary>
- /// Decrypts a nostr encrypted message in it's full binary from.
- /// </summary>
- /// <param name="payload"></param>
- /// <param name="plaintext"></param>
- /// <returns>The number of bytes written to the output buffer, or an error code if an error occured during the encryption</returns>
- /// <exception cref="NotSupportedException"></exception>
- public int DecryptPayload(ReadOnlySpan<byte> payload, Span<byte> plaintext)
- {
- return Version switch
- {
- NC_ENC_VERSION_NIP44 => DecryptNip44Payload(payload, plaintext),
- _ => throw new NotSupportedException("NIP04 encryption is not supported"),
- };
- }
-
- private int DecryptNip44Payload(ReadOnlySpan<byte> message, Span<byte> plaintext)
- {
- ArgumentOutOfRangeException.ThrowIfZero(message.Length, nameof(message));
- ArgumentOutOfRangeException.ThrowIfZero(plaintext.Length, nameof(plaintext));
-
- //Validate the incoming message for a nip44 message
- ArgumentOutOfRangeException.ThrowIfLessThan(message.Length, 32, nameof(message));
- ArgumentOutOfRangeException.ThrowIfGreaterThan(message.Length, Nip44MaxMessageSize, nameof(message));
-
- //Plaintext buffer must be large enough to hold the decrypted message
- ArgumentOutOfRangeException.ThrowIfLessThan(plaintext.Length, message.Length, nameof(plaintext));
-
- bool macValid = library.VerifyMac(
- in _fromKey,
- in _toKey,
- nonce32: in GetNonceRef(),
- mac32: in GetMacRef(),
- payload: ref MemoryMarshal.GetReference(message),
- (uint)message.Length
- );
-
- if (!macValid)
- {
- throw new AuthenticationException("Message MAC is invalid");
- }
-
- library.DecryptNip44(
- in _fromKey,
- in _toKey,
- nonce32: in GetNonceRef(),
- cipherText: in MemoryMarshal.GetReference(message),
- plainText: ref MemoryMarshal.GetReference(plaintext),
- (uint)message.Length
- );
-
- //Return the number of bytes written to the output buffer
- return message.Length;
- }
-
- private unsafe ref byte GetNonceRef()
- {
- Debug.Assert(NC_ENCRYPTION_NONCE_SIZE == sizeof(Buffer32));
- return ref Unsafe.As<Buffer32, byte>(ref _nonce32);
- }
-
- private unsafe ref byte GetMacRef()
- {
- Debug.Assert(NC_ENCRYPTION_MAC_SIZE == sizeof(Buffer32));
- return ref Unsafe.As<Buffer32, byte>(ref _mac32);
- }
-
- protected override void Free()
- {
- //Zero all internal memory
- MemoryUtil.ZeroStruct(ref _fromKey);
- MemoryUtil.ZeroStruct(ref _toKey);
- MemoryUtil.ZeroStruct(ref _nonce32);
- MemoryUtil.ZeroStruct(ref _mac32);
- }
-
- /// <summary>
- /// Initializes a new <see cref="NostrMessageCipher"/> with the nip44 encryption
- /// method.
- /// </summary>
- /// <param name="lib">The nostr crypto implementation instance to use</param>
- /// <returns>The intialzied message instance</returns>
- public static NostrMessageCipher CreateNip44Cipher(INostrCrypto lib)
- => new(lib, NCNip44EncryptionVersion.Instance);
-
-
- [StructLayout(LayoutKind.Sequential, Size = 32)]
- unsafe struct Buffer32
- {
- fixed byte value[32];
- }
- }
-
-}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/IRandomSource.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Random/IRandomSource.cs
index 5c5f2ac..84430a0 100644
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/IRandomSource.cs
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Random/IRandomSource.cs
@@ -15,7 +15,7 @@
using System;
-namespace VNLib.Utils.Cryptography.Noscrypt
+namespace VNLib.Utils.Cryptography.Noscrypt.Random
{
/// <summary>
/// Represents a generator for random data, that fills abinary buffer with random bytes
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NcFallbackRandom.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Random/NcFallbackRandom.cs
index 0949ad8..5e0675e 100644
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/NcFallbackRandom.cs
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Random/NcFallbackRandom.cs
@@ -17,18 +17,18 @@ using System;
using VNLib.Hashing;
-namespace VNLib.Utils.Cryptography.Noscrypt
+namespace VNLib.Utils.Cryptography.Noscrypt.Random
{
/// <summary>
/// A fallback crypographic random source used for default
/// rng if you wish
/// </summary>
- public sealed class NcFallbackRandom : IRandomSource
+ public sealed class NCFallbackRandom : IRandomSource
{
/// <summary>
/// Gets the shared instance of the fallback random source
/// </summary>
- public static NcFallbackRandom Shared { get; } = new NcFallbackRandom();
+ public static NCFallbackRandom Shared { get; } = new NCFallbackRandom();
/// <inheritdoc/>
public void GetRandomBytes(Span<byte> buffer) => RandomHash.GetRandomBytes(buffer);
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/UnmanagedRandomSource.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Random/UnmanagedRandomSource.cs
index 91ff64b..73ff374 100644
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/UnmanagedRandomSource.cs
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/Random/UnmanagedRandomSource.cs
@@ -16,11 +16,10 @@
using System;
using System.Runtime.InteropServices;
-using VNLib.Utils;
using VNLib.Utils.Native;
using VNLib.Utils.Extensions;
-namespace VNLib.Utils.Cryptography.Noscrypt
+namespace VNLib.Utils.Cryptography.Noscrypt.Random
{
/// <summary>
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/VNLib.Utils.Cryptography.Noscrypt.csproj b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/VNLib.Utils.Cryptography.Noscrypt.csproj
index 7e7f5de..4d1868c 100644
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/VNLib.Utils.Cryptography.Noscrypt.csproj
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/VNLib.Utils.Cryptography.Noscrypt.csproj
@@ -21,8 +21,8 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="VNLib.Hashing.Portable" Version="0.1.0-ci0122" />
- <PackageReference Include="VNLib.Utils" Version="0.1.0-ci0122" />
+ <PackageReference Include="VNLib.Hashing.Portable" Version="0.1.0-ci0124" />
+ <PackageReference Include="VNLib.Utils" Version="0.1.0-ci0124" />
</ItemGroup>
</Project>
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/internal/FunctionTable.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/internal/FunctionTable.cs
index 17b66b2..0cda5e2 100644
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/internal/FunctionTable.cs
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/internal/FunctionTable.cs
@@ -34,13 +34,16 @@ namespace VNLib.Utils.Cryptography.Noscrypt.@internal
public readonly NCValidateSecretKeyDelegate NCValidateSecretKey;
public readonly NCSignDataDelegate NCSignData;
public readonly NCVerifyDataDelegate NCVerifyData;
- public readonly NCEncryptDelegate NCEncrypt;
- public readonly NCDecryptDelegate NCDecrypt;
- public readonly NCVerifyMacDelegate NCVerifyMac;
- public readonly NCComputeMacDelegate NCComputeMac;
- public readonly NCSetEncryptionDataDelegate NCSetEncryptionData;
- public readonly NCSetEncryptionPropertyDelegate NCSetEncryptionProperty;
- public readonly NCSetEncryptionPropertyExDelegate NCSetEncryptionPropertyEx;
+ public readonly NCUtilCipherAllocDelegate NCUtilCipherAlloc;
+ public readonly NCUtilCipherFreeDelegate NCUtilCipherFree;
+ public readonly NCUtilCipherInitDelegate NCUtilCipherInit;
+ public readonly NCUtilCipherGetFlagsDelegate NCUtilCipherGetFlags;
+ public readonly NCUtilCipherGetOutputSizeDelegate NCUtilCipherGetOutputSize;
+ public readonly NCUtilCipherReadOutputDelegate NCUtilCipherReadOutput;
+ public readonly NCUtilCipherSetPropertyDelegate NCUtilCipherSetProperty;
+ public readonly NCUtilCipherUpdateDelegate NCUtilCipherUpdate;
+ public readonly NCUtilCipherGetIvSizeDelegate NCUtilCipherGetIvSize;
+
#if DEBUG
public readonly NCGetConversationKeyDelegate NCGetConversationKey;
@@ -59,13 +62,17 @@ namespace VNLib.Utils.Cryptography.Noscrypt.@internal
NCVerifyData = library.DangerousGetFunction<NCVerifyDataDelegate>();
NCSignData = library.DangerousGetFunction<NCSignDataDelegate>();
NCVerifyData = library.DangerousGetFunction<NCVerifyDataDelegate>();
- NCEncrypt = library.DangerousGetFunction<NCEncryptDelegate>();
- NCDecrypt = library.DangerousGetFunction<NCDecryptDelegate>();
- NCVerifyMac = library.DangerousGetFunction<NCVerifyMacDelegate>();
- NCComputeMac = library.DangerousGetFunction<NCComputeMacDelegate>();
- NCSetEncryptionData = library.DangerousGetFunction<NCSetEncryptionDataDelegate>();
- NCSetEncryptionProperty = library.DangerousGetFunction<NCSetEncryptionPropertyDelegate>();
- NCSetEncryptionPropertyEx = library.DangerousGetFunction<NCSetEncryptionPropertyExDelegate>();
+
+ //Cipher util library functions
+ NCUtilCipherAlloc = library.DangerousGetFunction<NCUtilCipherAllocDelegate>();
+ NCUtilCipherFree = library.DangerousGetFunction<NCUtilCipherFreeDelegate>();
+ NCUtilCipherInit = library.DangerousGetFunction<NCUtilCipherInitDelegate>();
+ NCUtilCipherGetFlags = library.DangerousGetFunction<NCUtilCipherGetFlagsDelegate>();
+ NCUtilCipherGetOutputSize = library.DangerousGetFunction<NCUtilCipherGetOutputSizeDelegate>();
+ NCUtilCipherReadOutput = library.DangerousGetFunction<NCUtilCipherReadOutputDelegate>();
+ NCUtilCipherSetProperty = library.DangerousGetFunction<NCUtilCipherSetPropertyDelegate>();
+ NCUtilCipherUpdate = library.DangerousGetFunction<NCUtilCipherUpdateDelegate>();
+ NCUtilCipherGetIvSize = library.DangerousGetFunction<NCUtilCipherGetIvSizeDelegate>();
#if DEBUG
NCGetConversationKey = library.DangerousGetFunction<NCGetConversationKeyDelegate>();
@@ -114,28 +121,35 @@ namespace VNLib.Utils.Cryptography.Noscrypt.@internal
[SafeMethodName("NCVerifyData")]
internal delegate NCResult NCVerifyDataDelegate(IntPtr ctx, NCPublicKey* sk, byte* data, uint dataSize, byte* sig64);
- [SafeMethodName("NCEncrypt")]
- internal delegate NCResult NCEncryptDelegate(IntPtr ctx, NCSecretKey* sk, NCPublicKey* pk, NCEncryptionArgs* data);
+ [SafeMethodName("NCGetConversationKey")]
+ internal delegate NCResult NCGetConversationKeyDelegate(IntPtr ctx, NCSecretKey* sk, NCPublicKey* pk, byte* keyOut32);
- [SafeMethodName("NCDecrypt")]
- internal delegate NCResult NCDecryptDelegate(IntPtr ctx, NCSecretKey* sk, NCPublicKey* pk, NCEncryptionArgs* data);
- [SafeMethodName("NCVerifyMac")]
- internal delegate NCResult NCVerifyMacDelegate(IntPtr ctx, NCSecretKey* sk, NCPublicKey* pk, NCMacVerifyArgs* args);
+ [SafeMethodName("NCUtilCipherAlloc")]
+ internal delegate IntPtr NCUtilCipherAllocDelegate(uint version, uint flags);
- [SafeMethodName("NCComputeMac")]
- internal delegate NCResult NCComputeMacDelegate(IntPtr ctx, byte* hmacKey32, byte* payload, uint payloadSize, byte* hmacOut32);
+ [SafeMethodName("NCUtilCipherFree")]
+ internal delegate void NCUtilCipherFreeDelegate(IntPtr cipher);
- [SafeMethodName("NCGetConversationKey")]
- internal delegate NCResult NCGetConversationKeyDelegate(nint ctx, NCSecretKey* sk, NCPublicKey* pk, byte* keyOut32);
+ [SafeMethodName("NCUtilCipherInit")]
+ internal delegate NCResult NCUtilCipherInitDelegate(IntPtr cipher, byte* inputData, uint inputLen);
+
+ [SafeMethodName("NCUtilCipherGetFlags")]
+ internal delegate NCResult NCUtilCipherGetFlagsDelegate(IntPtr cipher);
+
+ [SafeMethodName("NCUtilCipherGetOutputSize")]
+ internal delegate NCResult NCUtilCipherGetOutputSizeDelegate(IntPtr cipher);
+
+ [SafeMethodName("NCUtilCipherReadOutput")]
+ internal delegate NCResult NCUtilCipherReadOutputDelegate(IntPtr cipher, byte* outputData, uint outputLen);
- [SafeMethodName("NCSetEncryptionProperty")]
- internal delegate NCResult NCSetEncryptionPropertyDelegate(NCEncryptionArgs* args, uint property, uint value);
+ [SafeMethodName("NCUtilCipherSetProperty")]
+ internal delegate NCResult NCUtilCipherSetPropertyDelegate(IntPtr cipher, uint property, byte* value, uint valueLen);
- [SafeMethodName("NCSetEncryptionPropertyEx")]
- internal delegate NCResult NCSetEncryptionPropertyExDelegate(NCEncryptionArgs* args, uint property, byte* value, uint valueLen);
+ [SafeMethodName("NCUtilCipherUpdate")]
+ internal delegate NCResult NCUtilCipherUpdateDelegate(IntPtr cipher, IntPtr libContext, NCSecretKey* secKey, NCPublicKey* pubKey);
- [SafeMethodName("NCSetEncryptionData")]
- internal delegate NCResult NCSetEncryptionDataDelegate(NCEncryptionArgs* args, byte* input, byte* output, uint dataSize);
+ [SafeMethodName("NCUtilCipherGetIvSize")]
+ internal delegate NCResult NCUtilCipherGetIvSizeDelegate(IntPtr cipher);
}
}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/internal/NCEncryptionArgs.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/internal/NCEncryptionArgs.cs
deleted file mode 100644
index 91f0ff5..0000000
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/internal/NCEncryptionArgs.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2024 Vaughn Nugent
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace VNLib.Utils.Cryptography.Noscrypt.@internal
-{
- [StructLayout(LayoutKind.Sequential)]
- internal unsafe struct NCEncryptionArgs
- {
- public byte* nonceData;
- public byte* keyData;
- public byte* inputData;
- public byte* outputData;
- public uint dataSize;
- public uint version;
- }
-}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/internal/NCMacVerifyArgs.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/internal/NCMacVerifyArgs.cs
deleted file mode 100644
index 8a9ba1f..0000000
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/src/internal/NCMacVerifyArgs.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2024 Vaughn Nugent
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-using System;
-
-namespace VNLib.Utils.Cryptography.Noscrypt.@internal
-{
- internal unsafe struct NCMacVerifyArgs
- {
- /* The message authentication code certifying the Nip44 payload */
- public byte* mac32;
-
- /* The nonce used for the original message encryption */
- public byte* nonce32;
-
- /* The message payload data */
- public byte* payload;
-
- /* The size of the payload data */
- public uint payloadSize;
- }
-}
diff --git a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/tests/LibNoscryptTests.cs b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/tests/LibNoscryptTests.cs
index 73a62d9..25f382a 100644
--- a/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/tests/LibNoscryptTests.cs
+++ b/wrappers/dotnet/VNLib.Utils.Cryptography.Noscrypt/tests/LibNoscryptTests.cs
@@ -7,6 +7,8 @@ using System.Text.Json;
using VNLib.Hashing;
using VNLib.Utils.Memory;
using VNLib.Utils.Extensions;
+using VNLib.Utils.Cryptography.Noscrypt.Encryption;
+using VNLib.Utils.Cryptography.Noscrypt.Random;
namespace VNLib.Utils.Cryptography.Noscrypt.Tests
{
@@ -14,7 +16,7 @@ namespace VNLib.Utils.Cryptography.Noscrypt.Tests
public class LibNoscryptTests : IDisposable
{
- const string NoscryptLibWinDebug = @"../../../../../../../out/build/x64-debug/Debug/noscrypt.dll";
+ const string NoscryptLibWinDebug = @"../../../../../../../build/windows/Debug/noscrypt.dll";
//Keys generated using npx noskey package
@@ -134,32 +136,13 @@ namespace VNLib.Utils.Cryptography.Noscrypt.Tests
}
[TestMethod()]
- public void CalcPaddedLenTest()
- {
- //Get valid padding test vectors
- (int, int)[] paddedSizes = _testVectors.RootElement.GetProperty("v2")
- .GetProperty("valid")
- .GetProperty("calc_padded_len")
- .EnumerateArray()
- .Select(v =>
- {
- int[] testVals = v.Deserialize<int[]>()!;
- return (testVals[0], testVals[1]);
- }).ToArray();
-
-
- foreach ((int len, int paddedLen) in paddedSizes)
- {
- Assert.AreEqual<int>(paddedLen, Nip44Util.CalcBufferSize(len) - 2);
- }
- }
-
- [TestMethod()]
public void CorrectEncryptionTest()
{
using NostrCrypto nc = _testLib.InitializeCrypto(MemoryUtil.Shared, RandomHash.GetRandomBytes(32));
- using NostrMessageCipher cipher = NostrMessageCipher.CreateNip44Cipher(nc);
+ using NoscryptCipher cipher = nc.AllocCipher(NoscryptCipherVersion.Nip44, NoscryptCipherFlags.EncryptDefault);
+
+ using IMemoryHandle<byte> ctBuffer = MemoryUtil.SafeAllocNearestPage(1200, false);
foreach (EncryptionVector v in GetEncryptionVectors())
{
@@ -175,65 +158,74 @@ namespace VNLib.Utils.Cryptography.Noscrypt.Tests
//Recover public keys
nc.GetPublicKey(in NCUtil.AsSecretKey(secKey2), ref pub2);
- int outBufferSize = cipher.GetMessageBufferSize(plainText.Length);
+ //Assign existing nonce
+ nonce.CopyTo(cipher.IvBuffer);
- Span<byte> encryptedNote = new byte[outBufferSize];
+ cipher.Update(
+ in NCUtil.AsSecretKey(secKey1),
+ in pub2,
+ plainText
+ );
- cipher.SetSecretKey(secKey1)
- .SetPublicKey(in pub2)
- .SetNonce(nonce);
+ Span<byte> outputBuffer = ctBuffer.AsSpan(0, cipher.GetOutputSize());
- int written = cipher.EncryptMessage(plainText, encryptedNote);
- Assert.IsTrue(written > 0);
+ Assert.AreEqual<int>(cipher.ReadOutput(outputBuffer), message.Length);
- encryptedNote = encryptedNote[..written];
-
//Make sure the cipher text matches the expected payload
- if (!encryptedNote.SequenceEqual(message))
+ if (!outputBuffer.SequenceEqual(message))
{
Console.WriteLine($"Input data: {v.plaintext}");
- Console.WriteLine($" \n{Convert.ToHexString(encryptedNote)}\n{Convert.ToHexString(message)}");
+ Console.WriteLine($" \n{Convert.ToHexString(outputBuffer)}\n{Convert.ToHexString(message)}");
Assert.Fail($"Cipher text does not match expected message");
}
}
}
[TestMethod()]
- public void ValidateMessageMacs()
+ public void CorrectDecryptionTest()
{
- using NostrCrypto nc = _testLib.InitializeCrypto(MemoryUtil.Shared, RandomHash.GetRandomBytes(32));
+ using NostrCrypto nc = _testLib.InitializeCrypto(MemoryUtil.Shared, NCFallbackRandom.Shared);
- foreach (EncryptionVector v in GetEncryptionVectors())
- {
- ReadOnlySpan<byte> secKey1 = Convert.FromHexString(v.sec1);
- ReadOnlySpan<byte> secKey2 = Convert.FromHexString(v.sec2);
- ReadOnlySpan<byte> message = Convert.FromBase64String(v.payload);
+ using NoscryptCipher msgCipher = nc.AllocCipher(NoscryptCipherVersion.Nip44, NoscryptCipherFlags.DecryptDefault);
- Nip44MessageSegments nip44Message = new(message);
- Assert.AreEqual<byte>(nip44Message.Version, 0x02);
+ using IMemoryHandle<byte> ptBuffer = MemoryUtil.SafeAllocNearestPage(1200, false);
- NCPublicKey pub2;
+ foreach (EncryptionVector vector in GetEncryptionVectors())
+ {
+ ReadOnlySpan<byte> secKey1 = Convert.FromHexString(vector.sec1);
+ ReadOnlySpan<byte> secKey2 = Convert.FromHexString(vector.sec2);
+ ReadOnlySpan<byte> expectedPt = Encoding.UTF8.GetBytes(vector.plaintext);
+ ReadOnlySpan<byte> message = Convert.FromBase64String(vector.payload);
+
+ NCPublicKey pub2 = default;
- //Recover public key2
+ //Recover public keys
nc.GetPublicKey(in NCUtil.AsSecretKey(secKey2), ref pub2);
- bool success = nc.VerifyMac(
+ //update performs the decryption operation (mac is also verified by default)
+ msgCipher.Update(
in NCUtil.AsSecretKey(secKey1),
in pub2,
- nip44Message.Nonce,
- nip44Message.Mac,
- nip44Message.NonceAndCiphertext
+ message
);
- if (!success)
+ int outLen = msgCipher.GetOutputSize();
+ Assert.IsTrue(outLen == expectedPt.Length);
+
+ Span<byte> plaintext = ptBuffer.AsSpan(0, outLen);
+
+ msgCipher.ReadOutput(plaintext);
+
+ if (!plaintext.SequenceEqual(expectedPt))
{
- Console.WriteLine($"Failed to validate MAC for message: {v.payload}");
- Console.Write($"Mac hex value: {Convert.ToHexString(nip44Message.Mac)}");
- Assert.Fail("Failed to validate MAC for message");
+ Console.WriteLine($"Input data: {vector.plaintext}");
+ Console.WriteLine($" \n{Convert.ToHexString(plaintext)}\n{Convert.ToHexString(expectedPt)}");
+ Assert.Fail("Decrypted data does not match expected plaintext");
}
}
}
+
//Converstation key is only available in debug builds
#if DEBUG
@@ -266,77 +258,7 @@ namespace VNLib.Utils.Cryptography.Noscrypt.Tests
}
#endif
-
- [TestMethod()]
- public void CorrectDecryptionTest()
- {
- using NostrCrypto nc = _testLib.InitializeCrypto(MemoryUtil.Shared, NcFallbackRandom.Shared);
-
- using NostrMessageCipher msgCipher = NostrMessageCipher.CreateNip44Cipher(nc);
-
- using IMemoryHandle<byte> ptBuffer = MemoryUtil.SafeAllocNearestPage(1200, false);
-
- foreach (EncryptionVector vector in GetEncryptionVectors())
- {
- ReadOnlySpan<byte> secKey1 = Convert.FromHexString(vector.sec1);
- ReadOnlySpan<byte> secKey2 = Convert.FromHexString(vector.sec2);
- ReadOnlySpan<byte> expectedPt = Encoding.UTF8.GetBytes(vector.plaintext);
- ReadOnlySpan<byte> nonce = Convert.FromHexString(vector.nonce);
- ReadOnlySpan<byte> message = Convert.FromBase64String(vector.payload);
-
- NCPublicKey pub1 = default;
-
- //Recover public keys
- nc.GetPublicKey(in NCUtil.AsSecretKey(secKey1), ref pub1);
-
- msgCipher.SetPublicKey(in pub1)
- .SetSecretKey(secKey2);
-
- int outLen = msgCipher.DecryptMessage(message, ptBuffer.Span);
-
- Assert.IsTrue(outLen > 0);
-
- Span<byte> plaintext = ptBuffer.AsSpan(0, outLen);
-
- if (!plaintext.SequenceEqual(expectedPt))
- {
- Console.WriteLine($"Input data: {vector.plaintext}");
- Console.WriteLine($" \n{Convert.ToHexString(plaintext)}\n{Convert.ToHexString(expectedPt)}");
- Assert.Fail("Decrypted data does not match expected plaintext");
- }
- else
- {
- Assert.IsTrue(nonce.SequenceEqual(msgCipher.Nonce));
- }
- }
- }
-
-
- static byte[] CreateAndFormatPlaintextOutputBuffer(ReadOnlySpan<byte> plaintext)
- {
- //Compute the required plaintext buffer size
- int paddedSize = Nip44Util.CalcBufferSize(plaintext.Length);
-
- byte[] data = new byte[paddedSize];
-
- //Format the plaintext buffer
- Nip44Util.FormatBuffer(plaintext, data, true);
-
- return data;
- }
-
- static byte[] BuildMacData(ReadOnlySpan<byte> ciphertext, ReadOnlySpan<byte> nonce)
- {
- byte[] macData = new byte[ciphertext.Length + nonce.Length];
-
- //Nonce then cipher text
- nonce.CopyTo(macData);
- ciphertext.CopyTo(macData.AsSpan(nonce.Length));
-
- return macData;
- }
-
- EncryptionVector[] GetEncryptionVectors()
+ private EncryptionVector[] GetEncryptionVectors()
{
return _testVectors.RootElement.GetProperty("v2")
.GetProperty("valid")