aboutsummaryrefslogtreecommitdiff
path: root/back-end
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-11-23 12:44:53 -0500
committerLibravatar vnugent <public@vaughnnugent.com>2023-11-23 12:44:53 -0500
commit8434d8b8ecf54c6038a7e9ad7d57084a0865500c (patch)
tree719f5ee3beb9ea99c8d9e3d8e6279092f98e11ac /back-end
parente272adcc3f32e31fe7668551453b8e34bc823c3e (diff)
fixed signing and working note encryption!
Diffstat (limited to 'back-end')
-rw-r--r--back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs23
-rw-r--r--back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs5
-rw-r--r--back-end/plugins/nvault/src/Endpoints/Endpoint.cs6
-rw-r--r--back-end/plugins/nvault/src/NativeSecp256k1Library.cs9
-rw-r--r--back-end/plugins/nvault/src/NostrOpProvider.cs24
5 files changed, 48 insertions, 19 deletions
diff --git a/back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs b/back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs
index f5327df..9931698 100644
--- a/back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs
+++ b/back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs
@@ -254,7 +254,7 @@ namespace NVault.Crypto.Secp256k1
{
if (secretKey.Length != SecretKeySize)
{
- throw new ArgumentException($"Your public key buffer must be exactly {SecretKeySize} bytes long");
+ throw new ArgumentException($"Your secret key buffer must be exactly {SecretKeySize} bytes long");
}
//Init callback state struct
@@ -265,17 +265,28 @@ namespace NVault.Crypto.Secp256k1
OutLen = data.Length
};
+ context.Lib.SafeLibHandle.ThrowIfClosed();
+
//Stack allocated keypair and x-only public key
- Secp256k1PublicKey pubKeyStruct = new();
- //Recover the x-only public key structure
- MemoryUtil.CopyStruct(xOnlyPubKey, &pubKeyStruct);
+ Secp256k1PublicKey peerPubKey = new();
- context.Lib.SafeLibHandle.ThrowIfClosed();
+ //Parse the public key from the buffer
+ fixed (byte* pubkeyPtr = &MemoryMarshal.GetReference(xOnlyPubKey))
+ {
+ context.Lib._xOnlyPubkeyParse(context.Context, &peerPubKey, pubkeyPtr);
+ }
fixed (byte* dataPtr = &MemoryMarshal.GetReference(data),
secKeyPtr = &MemoryMarshal.GetReference(secretKey))
{
- return context.Lib._ecdh.Invoke(context.Context, dataPtr, &pubKeyStruct, secKeyPtr, UmanagedEcdhHashFuncCallback, &state) == 1;
+ return context.Lib._ecdh.Invoke(
+ context.Context,
+ dataPtr,
+ &peerPubKey,
+ secKeyPtr,
+ UmanagedEcdhHashFuncCallback,
+ &state
+ ) == 1;
}
/*
diff --git a/back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs b/back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs
index 5aeed00..f3afc33 100644
--- a/back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs
+++ b/back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs
@@ -82,6 +82,9 @@ namespace NVault.Crypto.Secp256k1
[SafeMethodName("secp256k1_ec_pubkey_serialize")]
internal delegate int PubKeySerialize(IntPtr ctx, byte* outPubKey, ulong* outLen, Secp256k1PublicKey* pubKey, uint flags);
+ [SafeMethodName("secp256k1_xonly_pubkey_parse")]
+ internal delegate int XOnlyPubkeyParse(IntPtr ctx, Secp256k1PublicKey* pubkey, byte* input32);
+
[SafeMethodName("secp256k1_ecdh")]
internal delegate int Ecdh(
IntPtr ctx,
@@ -143,6 +146,7 @@ namespace NVault.Crypto.Secp256k1
internal readonly SecKeyVerify _secKeyVerify;
internal readonly PubKeySerialize _pubKeySerialize;
internal readonly Ecdh _ecdh;
+ internal readonly XOnlyPubkeyParse _xOnlyPubkeyParse;
private readonly IRandomSource _randomSource;
/// <summary>
@@ -171,6 +175,7 @@ namespace NVault.Crypto.Secp256k1
_secKeyVerify = handle.DangerousGetMethod<SecKeyVerify>();
_pubKeySerialize = handle.DangerousGetMethod<PubKeySerialize>();
_ecdh = handle.DangerousGetMethod<Ecdh>();
+ _xOnlyPubkeyParse = handle.DangerousGetMethod<XOnlyPubkeyParse>();
//Store random source
_randomSource = randomSource;
diff --git a/back-end/plugins/nvault/src/Endpoints/Endpoint.cs b/back-end/plugins/nvault/src/Endpoints/Endpoint.cs
index f718c2f..bcebc63 100644
--- a/back-end/plugins/nvault/src/Endpoints/Endpoint.cs
+++ b/back-end/plugins/nvault/src/Endpoints/Endpoint.cs
@@ -517,9 +517,11 @@ namespace NVault.Plugins.Vault.Endpoints
.NotEmpty()
.Length(0, 10000)
//Make sure iv exists
- .Must(ct => ct.Contains("iv?=", StringComparison.OrdinalIgnoreCase))
+ .Must(ct => ct.Contains("?iv=", StringComparison.OrdinalIgnoreCase))
+ .WithMessage("iv not found in ciphertext")
//Check iv is not too long
- .Must(ct => ct.AsSpan().SliceAfterParam("iv?=").Length < 28);
+ .Must(ct => ct.AsSpan().SliceAfterParam("?iv=").Length == NostrOpProvider.MaxBase64EncodedSize)
+ .WithMessage("iv is not the correct size");
//Pubpkey must be 64 hex characters
validationRules.RuleFor(p => p.OtherPubKey)
diff --git a/back-end/plugins/nvault/src/NativeSecp256k1Library.cs b/back-end/plugins/nvault/src/NativeSecp256k1Library.cs
index 55cf2de..0870156 100644
--- a/back-end/plugins/nvault/src/NativeSecp256k1Library.cs
+++ b/back-end/plugins/nvault/src/NativeSecp256k1Library.cs
@@ -71,7 +71,7 @@ namespace NVault.Plugins.Vault
aes.Key = sharedKeyBuffer;
aes.Mode = CipherMode.CBC;
- return aes.DecryptCbc(ciphterText, aesIv, outputBuffer, PaddingMode.None);
+ return aes.DecryptCbc(ciphterText, aesIv, outputBuffer, PaddingMode.Zeros);
}
finally
{
@@ -99,14 +99,17 @@ namespace NVault.Plugins.Vault
try
{
//Get the Secp256k1 shared key
- context.ComputeSharedKey(sharedKeyBuffer, targetKey, secretKey, HashFuncCallback, IntPtr.Zero);
+ if(!context.ComputeSharedKey(sharedKeyBuffer, targetKey, secretKey, HashFuncCallback, IntPtr.Zero))
+ {
+ return ERRNO.E_FAIL;
+ }
//Init the AES cipher
using Aes aes = Aes.Create();
aes.Key = sharedKeyBuffer;
aes.Mode = CipherMode.CBC;
- return aes.EncryptCbc(plainText, aesIv, cipherText, PaddingMode.None);
+ return aes.EncryptCbc(plainText, aesIv, cipherText, PaddingMode.Zeros);
}
finally
{
diff --git a/back-end/plugins/nvault/src/NostrOpProvider.cs b/back-end/plugins/nvault/src/NostrOpProvider.cs
index eed64b7..aa4840e 100644
--- a/back-end/plugins/nvault/src/NostrOpProvider.cs
+++ b/back-end/plugins/nvault/src/NostrOpProvider.cs
@@ -34,12 +34,12 @@ using VNLib.Plugins.Extensions.Loading;
using NVault.Plugins.Vault.Model;
-
namespace NVault.Plugins.Vault
{
internal sealed class NostrOpProvider : INostrOperations
{
- const int NIP04_RANDOM_IV_SIZE = 16;
+ public const int AES_IV_SIZE = 16;
+ public static int MaxBase64EncodedSize { get; } = Base64.GetMaxEncodedToUtf8Length(AES_IV_SIZE);
private static JavaScriptEncoder _encoder { get; } = GetJsEncoder();
@@ -350,7 +350,7 @@ namespace NVault.Plugins.Vault
//Small buffers for private key and raw iv
Span<byte> privKeyBytes = stackalloc byte[keyBufSize];
- Span<byte> ivBuffer = stackalloc byte[encipher ? NIP04_RANDOM_IV_SIZE : 64];
+ Span<byte> ivBuffer = stackalloc byte[encipher ? AES_IV_SIZE : 64];
try
{
@@ -391,14 +391,15 @@ namespace NVault.Plugins.Vault
ReadOnlySpan<char> cipherText = text.SliceBeforeParam("?iv=");
ReadOnlySpan<char> ivSegment = text.SliceAfterParam("?iv=");
- if (ivSegment.Length > 128)
+ if (ivSegment.Length > MaxBase64EncodedSize)
{
throw new ArgumentException("initialization vector is larger than allowed");
}
//Decode initialziation vector
ERRNO ivSize= VnEncoding.TryFromBase64Chars(ivSegment, ivBuffer);
- if (ivSize < 1)
+ //Must be exactly the size of the AES block s
+ if (ivSize != AES_IV_SIZE)
{
return false;
}
@@ -412,7 +413,7 @@ namespace NVault.Plugins.Vault
//Decrypt the message
ERRNO outputSize = _cryptoProvider.DecryptMessage(
- privKeyBytes,
+ privKeyBytes[..(int)keySize],
pubKey,
ivBuffer.Slice(0, ivSize),
ctBuffer.AsSpan(0, ctSize),
@@ -424,6 +425,13 @@ namespace NVault.Plugins.Vault
return false;
}
+ Span<byte> output = outputBuffer.Span;
+ //trim trailing zeros
+ while (outputSize > 0 && output[outputSize - 1] == 0)
+ {
+ outputSize--;
+ }
+
//Store the output text (deciphered text)
outputText = Encoding.UTF8.GetString(outputBuffer.AsSpan(0, outputSize));
@@ -433,8 +441,8 @@ namespace NVault.Plugins.Vault
finally
{
//Zero the key buffer and key
- MemoryUtil.InitializeBlock(ctBuffer.Span);
- MemoryUtil.InitializeBlock(outputBuffer.Span);
+ MemoryUtil.InitializeBlock(ref ctBuffer.GetReference(), outputBuffer.IntLength);
+ MemoryUtil.InitializeBlock(ref outputBuffer.GetReference(), outputBuffer.IntLength);
MemoryUtil.InitializeBlock(privKeyBytes);
MemoryUtil.InitializeBlock(ivBuffer);
}