aboutsummaryrefslogtreecommitdiff
path: root/back-end/libs
diff options
context:
space:
mode:
Diffstat (limited to 'back-end/libs')
-rw-r--r--back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs110
-rw-r--r--back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs45
-rw-r--r--back-end/libs/NVault.Crypto.Secp256k1/src/NVault.Crypto.Secp256k1.csproj4
-rw-r--r--back-end/libs/NVault.VaultExtensions/src/NVault.VaultExtensions.csproj2
-rw-r--r--back-end/libs/NVault.VaultExtensions/src/VaultClientExtensions.cs2
5 files changed, 146 insertions, 17 deletions
diff --git a/back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs b/back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs
index a89fce8..f5327df 100644
--- a/back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs
+++ b/back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs
@@ -24,9 +24,46 @@ using VNLib.Utils.Extensions;
using static NVault.Crypto.Secp256k1.LibSecp256k1;
-
namespace NVault.Crypto.Secp256k1
{
+ public delegate int Secp256k1EcdhHashFunc(in Secp256HashFuncState state);
+
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe readonly ref struct Secp256HashFuncState
+ {
+
+ /// <summary>
+ /// The opaque pointer passed to the hash function
+ /// </summary>
+ public readonly IntPtr Opaque { get; }
+
+ private readonly byte* _output;
+ private readonly byte* _xCoord;
+ private readonly int _outputLength;
+ private readonly int _xCoordLength;
+
+ internal Secp256HashFuncState(byte* output, int outputLength, byte* xCoord, int xCoordLength, IntPtr opaque)
+ {
+ Opaque = opaque;
+ _output = output;
+ _outputLength = outputLength;
+ _xCoord = xCoord;
+ _xCoordLength = xCoordLength;
+ }
+
+ /// <summary>
+ /// Gets the output buffer as a span
+ /// </summary>
+ /// <returns>The output buffer span</returns>
+ public readonly Span<byte> GetOutput() => new(_output, _outputLength);
+
+ /// <summary>
+ /// Gets the x coordinate argument as a span
+ /// </summary>
+ /// <returns>The xcoordinate buffer span</returns>
+ public readonly ReadOnlySpan<byte> GetXCoordArg() => new(_xCoord, _xCoordLength);
+ }
+
public static unsafe class ContextExtensions
{
/// <summary>
@@ -138,7 +175,7 @@ namespace NVault.Crypto.Secp256k1
context.Lib.SafeLibHandle.ThrowIfClosed();
//Stack allocated keypair and x-only public key
- XOnlyPubKey xOnlyPubKey = new();
+ Secp256k1PublicKey xOnlyPubKey = new();
KeyPair keyPair = new();
try
@@ -196,5 +233,74 @@ namespace NVault.Crypto.Secp256k1
return context.Lib._secKeyVerify.Invoke(context.Context, ptr) == 1;
}
}
+
+
+ [StructLayout(LayoutKind.Sequential)]
+ private readonly ref struct EcdhHashFuncState
+ {
+ public readonly IntPtr HashFunc { get; init; }
+ public readonly IntPtr Opaque { get; init; }
+ public readonly int OutLen { get; init; }
+ }
+
+ /// <summary>
+ /// Verifies that a given secret key is valid using the current context
+ /// </summary>
+ /// <param name="context"></param>
+ /// <param name="secretKey">The secret key to verify</param>
+ /// <returns>A boolean value that indicates if the secret key is valid or not</returns>
+ /// <exception cref="ArgumentException"></exception>
+ public static bool ComputeSharedKey(this in Secp256k1Context context, Span<byte> data, ReadOnlySpan<byte> xOnlyPubKey, ReadOnlySpan<byte> secretKey, Secp256k1EcdhHashFunc callback, IntPtr opaque)
+ {
+ if (secretKey.Length != SecretKeySize)
+ {
+ throw new ArgumentException($"Your public key buffer must be exactly {SecretKeySize} bytes long");
+ }
+
+ //Init callback state struct
+ EcdhHashFuncState state = new()
+ {
+ HashFunc = Marshal.GetFunctionPointerForDelegate(callback),
+ Opaque = opaque,
+ OutLen = data.Length
+ };
+
+ //Stack allocated keypair and x-only public key
+ Secp256k1PublicKey pubKeyStruct = new();
+ //Recover the x-only public key structure
+ MemoryUtil.CopyStruct(xOnlyPubKey, &pubKeyStruct);
+
+ context.Lib.SafeLibHandle.ThrowIfClosed();
+
+ fixed (byte* dataPtr = &MemoryMarshal.GetReference(data),
+ secKeyPtr = &MemoryMarshal.GetReference(secretKey))
+ {
+ return context.Lib._ecdh.Invoke(context.Context, dataPtr, &pubKeyStruct, secKeyPtr, UmanagedEcdhHashFuncCallback, &state) == 1;
+ }
+
+ /*
+ * Umanaged wrapper function for invoking the safe user callback
+ * from the unmanaged lib
+ */
+ static int UmanagedEcdhHashFuncCallback(byte* output, byte* x32, byte* y32, void* opaque)
+ {
+ //Recover the callback
+ if (opaque == null)
+ {
+ return 0;
+ }
+
+ EcdhHashFuncState* state = (EcdhHashFuncState*)opaque;
+
+ //Init user-state structure
+ Secp256HashFuncState userState = new(output, state->OutLen, x32, 32, new(opaque));
+
+ //Recover the function pointer
+ Secp256k1EcdhHashFunc callback = Marshal.GetDelegateForFunctionPointer<Secp256k1EcdhHashFunc>(state->HashFunc);
+
+ //Invoke the callback
+ return callback(in userState);
+ }
+ }
}
} \ No newline at end of file
diff --git a/back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs b/back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs
index 80d6eb8..5aeed00 100644
--- a/back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs
+++ b/back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs
@@ -23,33 +23,37 @@ using VNLib.Utils.Extensions;
namespace NVault.Crypto.Secp256k1
{
+
+ internal unsafe delegate int EcdhHasFunc(byte* output, byte* x32, byte* y32, void* data);
public unsafe class LibSecp256k1 : VnDisposeable
{
public const int SecretKeySize = 32;
- public const int XOnlyPublicKeySize = 32;
public const int SignatureSize = 64;
- public const int KeyPairSize = 96;
public const int RandomBufferSize = 32;
+ public const int XOnlyPublicKeySize = 32;
/*
* Unsafe structures that represent the native keypair and x-only public key
* structures. They hold character arrays
*/
- [StructLayout(LayoutKind.Sequential)]
+ [StructLayout(LayoutKind.Sequential, Size = 96)]
internal struct KeyPair
{
- public fixed byte data[Length];
- public const int Length = KeyPairSize;
+ public fixed byte data[96];
}
- [StructLayout(LayoutKind.Sequential)]
- internal struct XOnlyPubKey
+ /// <summary>
+ /// 1:1 with the secp256k1_pubkey structure
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential, Size = 64)]
+ internal struct Secp256k1PublicKey
{
- public fixed byte data[Length];
- public const int Length = 64;
+ public fixed byte data[64];
}
+
+
//Native methods
[SafeMethodName("secp256k1_context_create")]
internal delegate IntPtr CreateContext(int flags);
@@ -64,10 +68,10 @@ namespace NVault.Crypto.Secp256k1
internal delegate int KeypairCreate(IntPtr context, KeyPair* keyPair, byte* secretKey);
[SafeMethodName("secp256k1_keypair_xonly_pub")]
- internal delegate int KeypairXOnlyPub(IntPtr ctx, XOnlyPubKey* pubkey, int pk_parity, KeyPair* keypair);
+ internal delegate int KeypairXOnlyPub(IntPtr ctx, Secp256k1PublicKey* pubkey, int pk_parity, KeyPair* keypair);
[SafeMethodName("secp256k1_xonly_pubkey_serialize")]
- internal delegate int XOnlyPubkeySerialize(IntPtr ctx, byte* output32, XOnlyPubKey* pubkey);
+ internal delegate int XOnlyPubkeySerialize(IntPtr ctx, byte* output32, Secp256k1PublicKey* pubkey);
[SafeMethodName("secp256k1_schnorrsig_sign32")]
internal delegate int SignHash(IntPtr ctx, byte* sig64, byte* msg32, KeyPair* keypair, byte* aux_rand32);
@@ -75,6 +79,21 @@ namespace NVault.Crypto.Secp256k1
[SafeMethodName("secp256k1_ec_seckey_verify")]
internal delegate int SecKeyVerify(IntPtr ctx, in byte* seckey);
+ [SafeMethodName("secp256k1_ec_pubkey_serialize")]
+ internal delegate int PubKeySerialize(IntPtr ctx, byte* outPubKey, ulong* outLen, Secp256k1PublicKey* pubKey, uint flags);
+
+ [SafeMethodName("secp256k1_ecdh")]
+ internal delegate int Ecdh(
+ IntPtr ctx,
+ byte* output,
+ Secp256k1PublicKey* pubkey,
+ byte* scalar,
+ EcdhHasFunc hashFunc,
+ void* dataPtr
+ );
+
+
+
/// <summary>
/// Loads the Secp256k1 library from the specified path and creates a wrapper class (loads methods from the library)
/// </summary>
@@ -122,6 +141,8 @@ namespace NVault.Crypto.Secp256k1
internal readonly XOnlyPubkeySerialize _serializeXonly;
internal readonly SignHash _signHash;
internal readonly SecKeyVerify _secKeyVerify;
+ internal readonly PubKeySerialize _pubKeySerialize;
+ internal readonly Ecdh _ecdh;
private readonly IRandomSource _randomSource;
/// <summary>
@@ -148,6 +169,8 @@ namespace NVault.Crypto.Secp256k1
_serializeXonly = handle.DangerousGetMethod<XOnlyPubkeySerialize>();
_signHash = handle.DangerousGetMethod<SignHash>();
_secKeyVerify = handle.DangerousGetMethod<SecKeyVerify>();
+ _pubKeySerialize = handle.DangerousGetMethod<PubKeySerialize>();
+ _ecdh = handle.DangerousGetMethod<Ecdh>();
//Store random source
_randomSource = randomSource;
diff --git a/back-end/libs/NVault.Crypto.Secp256k1/src/NVault.Crypto.Secp256k1.csproj b/back-end/libs/NVault.Crypto.Secp256k1/src/NVault.Crypto.Secp256k1.csproj
index 7fa738d..22a7e38 100644
--- a/back-end/libs/NVault.Crypto.Secp256k1/src/NVault.Crypto.Secp256k1.csproj
+++ b/back-end/libs/NVault.Crypto.Secp256k1/src/NVault.Crypto.Secp256k1.csproj
@@ -20,8 +20,8 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="VNLib.Hashing.Portable" Version="0.1.0-ci0088" />
- <PackageReference Include="VNLib.Utils" Version="0.1.0-ci0088" />
+ <PackageReference Include="VNLib.Hashing.Portable" Version="0.1.0-ci0096" />
+ <PackageReference Include="VNLib.Utils" Version="0.1.0-ci0096" />
</ItemGroup>
</Project>
diff --git a/back-end/libs/NVault.VaultExtensions/src/NVault.VaultExtensions.csproj b/back-end/libs/NVault.VaultExtensions/src/NVault.VaultExtensions.csproj
index 49d3dc6..d6af22d 100644
--- a/back-end/libs/NVault.VaultExtensions/src/NVault.VaultExtensions.csproj
+++ b/back-end/libs/NVault.VaultExtensions/src/NVault.VaultExtensions.csproj
@@ -21,7 +21,7 @@
<ItemGroup>
<PackageReference Include="VaultSharp" Version="1.13.0.1" />
- <PackageReference Include="VNLib.Plugins.Extensions.Loading" Version="0.1.0-ci0037" />
+ <PackageReference Include="VNLib.Plugins.Extensions.Loading" Version="0.1.0-ci0042" />
</ItemGroup>
</Project>
diff --git a/back-end/libs/NVault.VaultExtensions/src/VaultClientExtensions.cs b/back-end/libs/NVault.VaultExtensions/src/VaultClientExtensions.cs
index 5a7c637..9ea9d24 100644
--- a/back-end/libs/NVault.VaultExtensions/src/VaultClientExtensions.cs
+++ b/back-end/libs/NVault.VaultExtensions/src/VaultClientExtensions.cs
@@ -54,7 +54,7 @@ namespace NVault.VaultExtensions
string? value = result.Data.Data.GetValueOrDefault(property)?.ToString();
//Return the secret value as a private string
- return value == null ? null : new PrivateString(value);
+ return value == null ? null : PrivateString.ToPrivateString(value, true);
}
/// <summary>