aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-12-01 21:00:49 -0500
committerLibravatar vnugent <public@vaughnnugent.com>2023-12-01 21:00:49 -0500
commit54984ef915a3bf640e06015bd294bd2186b3a588 (patch)
tree51bc8384138a5eca389186f178fa5fd669cf3916
parentc4205bfe23dc321c77e2ff032fcb355d16e5d6c0 (diff)
internal polish, minor refactors & manifest v3 progression
-rw-r--r--back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs91
-rw-r--r--back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs63
-rw-r--r--back-end/libs/NVault.Crypto.Secp256k1/src/Secp256HashFuncState.cs56
-rw-r--r--back-end/libs/NVault.Crypto.Secp256k1/src/Secp256k1Context.cs10
-rw-r--r--back-end/libs/NVault.Crypto.Secp256k1/src/Secp256k1SecretKey.cs58
-rw-r--r--back-end/plugins/nvault/src/Endpoints/Endpoint.cs4
-rw-r--r--back-end/plugins/nvault/src/INostrCryptoProvider.cs19
-rw-r--r--back-end/plugins/nvault/src/NativeSecp256k1Library.cs4
-rw-r--r--back-end/plugins/nvault/src/NostrOpProvider.cs21
-rw-r--r--extension/README.md61
-rw-r--r--extension/src/entries/background/serviceWorker.js (renamed from extension/src/entries/background/serviceWorker.ts)2
-rw-r--r--extension/src/entries/contentScript/primary/components/PromptPopup.vue7
-rw-r--r--extension/src/entries/contentScript/primary/main.js4
-rw-r--r--extension/src/entries/store/identity.ts1
-rw-r--r--extension/src/manifest.js6
-rw-r--r--extension/tsconfig.json2
16 files changed, 241 insertions, 168 deletions
diff --git a/back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs b/back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs
index 9931698..556bba7 100644
--- a/back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs
+++ b/back-end/libs/NVault.Crypto.Secp256k1/src/ContextExtensions.cs
@@ -26,69 +26,16 @@ using static NVault.Crypto.Secp256k1.LibSecp256k1;
namespace NVault.Crypto.Secp256k1
{
+ /// <summary>
+ /// The callback function signature required for ECDH hash functions
+ /// </summary>
+ /// <param name="state">The callback state</param>
+ /// <returns>The return value to be passed as a result of the operation</returns>
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>
- /// Creates a new <see cref="Secp256k1Context"/> from the current managed library
- /// </summary>
- /// <param name="Lib"></param>
- /// <returns>The new <see cref="Secp256k1Context"/> object from the library</returns>
- /// <exception cref="CryptographicException"></exception>
- public static Secp256k1Context CreateContext(this LibSecp256k1 Lib)
- {
- //Protect for released lib
- Lib.SafeLibHandle.ThrowIfClosed();
-
- //Create new context
- IntPtr context = Lib._create(1);
-
- if (context == IntPtr.Zero)
- {
- throw new CryptographicException("Failed to create the new Secp256k1 context");
- }
-
- return new Secp256k1Context(Lib, context);
- }
-
- /// <summary>
/// Signs a 32byte message digest with the specified secret key on the current context and writes the signature to the specified buffer
/// </summary>
/// <param name="context"></param>
@@ -108,13 +55,22 @@ namespace NVault.Crypto.Secp256k1
if (digest.Length != (int)HashAlg.SHA256)
{
return ERRNO.E_FAIL;
- }
+ }
+
+ //Secret key size must be exactly the size of the secret key struct
+ if(secretKey.Length != sizeof(Secp256k1SecretKey))
+ {
+ return ERRNO.E_FAIL;
+ }
//Stack allocated keypair
KeyPair keyPair = new();
+ //Init the secret key struct from key data
+ Secp256k1SecretKey secKeyStruct = MemoryMarshal.Read<Secp256k1SecretKey>(secretKey);
+
//Randomize the context and create the keypair
- if (!context.CreateKeyPair(&keyPair, secretKey))
+ if (!context.CreateKeyPair(&keyPair, &secKeyStruct))
{
return ERRNO.E_FAIL;
}
@@ -161,9 +117,9 @@ namespace NVault.Crypto.Secp256k1
/// <exception cref="CryptographicException"></exception>
public static ERRNO GeneratePubKeyFromSecret(this in Secp256k1Context context, ReadOnlySpan<byte> secretKey, Span<byte> pubKeyBuffer)
{
- if (secretKey.Length != SecretKeySize)
+ if (secretKey.Length != sizeof(Secp256k1SecretKey))
{
- throw new CryptographicException($"Your secret key must be exactly {SecretKeySize} bytes long");
+ throw new CryptographicException($"Your secret key must be exactly {sizeof(Secp256k1SecretKey)} bytes long");
}
if (pubKeyBuffer.Length < XOnlyPublicKeySize)
@@ -176,12 +132,13 @@ namespace NVault.Crypto.Secp256k1
//Stack allocated keypair and x-only public key
Secp256k1PublicKey xOnlyPubKey = new();
+ Secp256k1SecretKey secKeyStruct = MemoryMarshal.Read<Secp256k1SecretKey>(secretKey);
KeyPair keyPair = new();
try
{
//Init context and keypair
- if (!context.CreateKeyPair(&keyPair, secretKey))
+ if (!context.CreateKeyPair(&keyPair, &secKeyStruct))
{
return ERRNO.E_FAIL;
}
@@ -220,9 +177,9 @@ namespace NVault.Crypto.Secp256k1
/// <exception cref="CryptographicException"></exception>
public static bool VerifySecretKey(this in Secp256k1Context context, ReadOnlySpan<byte> secretKey)
{
- if (secretKey.Length != SecretKeySize)
+ if (secretKey.Length != sizeof(Secp256k1SecretKey))
{
- throw new CryptographicException($"Your secret key must be exactly {SecretKeySize} bytes long");
+ throw new CryptographicException($"Your secret key must be exactly {sizeof(Secp256k1SecretKey)} bytes long");
}
context.Lib.SafeLibHandle.ThrowIfClosed();
@@ -252,9 +209,9 @@ namespace NVault.Crypto.Secp256k1
/// <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)
+ if (secretKey.Length != sizeof(Secp256k1SecretKey))
{
- throw new ArgumentException($"Your secret key buffer must be exactly {SecretKeySize} bytes long");
+ throw new ArgumentException($"Your secret key buffer must be exactly {sizeof(Secp256k1SecretKey)} bytes long");
}
//Init callback state struct
diff --git a/back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs b/back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs
index f3afc33..907eaa4 100644
--- a/back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs
+++ b/back-end/libs/NVault.Crypto.Secp256k1/src/LibSecp256k1.cs
@@ -23,16 +23,17 @@ 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 SignatureSize = 64;
public const int RandomBufferSize = 32;
public const int XOnlyPublicKeySize = 32;
+ public static readonly int SecretKeySize = sizeof(Secp256k1SecretKey);
+
/*
* Unsafe structures that represent the native keypair and x-only public key
* structures. They hold character arrays
@@ -51,15 +52,14 @@ namespace NVault.Crypto.Secp256k1
{
public fixed byte data[64];
}
-
//Native methods
[SafeMethodName("secp256k1_context_create")]
- internal delegate IntPtr CreateContext(int flags);
+ internal delegate IntPtr ContextCreate(int flags);
[SafeMethodName("secp256k1_context_destroy")]
- internal delegate void DestroyContext(IntPtr context);
+ internal delegate void ContextDestroy(IntPtr context);
[SafeMethodName("secp256k1_context_randomize")]
internal delegate int RandomizeContext(IntPtr context, byte* seed32);
@@ -94,7 +94,6 @@ namespace NVault.Crypto.Secp256k1
EcdhHasFunc hashFunc,
void* dataPtr
);
-
/// <summary>
@@ -132,14 +131,32 @@ namespace NVault.Crypto.Secp256k1
}
/// <summary>
+ /// Loads the Secp256k1 library from the specified path and creates a wrapper class (loads methods from the library)
+ /// </summary>
+ /// <param name="handle">The handle to the shared library</param>
+ /// <param name="random">An optional random source to create random entropy and secrets from</param>
+ /// <returns>The <see cref="LibSecp256k1"/> library wrapper class</returns>
+ /// <exception cref="ArgumentNullException"></exception>
+ /// <exception cref="MissingMemberException"></exception>
+ /// <exception cref="EntryPointNotFoundException"></exception>
+ public static LibSecp256k1 FromHandle(SafeLibraryHandle handle, IRandomSource? random)
+ {
+ _ = handle ?? throw new ArgumentNullException(nameof(handle));
+ //setup fallback random source if null
+ random ??= new FallbackRandom();
+ //Create the lib
+ return new LibSecp256k1(handle, random);
+ }
+
+ /// <summary>
/// The underlying library handle
/// </summary>
public SafeLibraryHandle SafeLibHandle { get; }
internal readonly KeypairCreate _createKeyPair;
- internal readonly CreateContext _create;
+ internal readonly ContextCreate _create;
internal readonly RandomizeContext _randomize;
- internal readonly DestroyContext _destroy;
+ internal readonly ContextDestroy _destroy;
internal readonly KeypairXOnlyPub _createXonly;
internal readonly XOnlyPubkeySerialize _serializeXonly;
internal readonly SignHash _signHash;
@@ -165,10 +182,10 @@ namespace NVault.Crypto.Secp256k1
SafeLibHandle = handle ?? throw new ArgumentNullException(nameof(handle));
//Get all method handles and store them
- _create = handle.DangerousGetMethod<CreateContext>();
+ _create = handle.DangerousGetMethod<ContextCreate>();
_createKeyPair = handle.DangerousGetMethod<KeypairCreate>();
_randomize = handle.DangerousGetMethod<RandomizeContext>();
- _destroy = handle.DangerousGetMethod<DestroyContext>();
+ _destroy = handle.DangerousGetMethod<ContextDestroy>();
_createXonly = handle.DangerousGetMethod<KeypairXOnlyPub>();
_serializeXonly = handle.DangerousGetMethod<XOnlyPubkeySerialize>();
_signHash = handle.DangerousGetMethod<SignHash>();
@@ -205,9 +222,9 @@ namespace NVault.Crypto.Secp256k1
//Protect for released lib
SafeLibHandle.ThrowIfClosed();
- if(buffer.Length != SecretKeySize)
+ if(buffer.Length != sizeof(Secp256k1SecretKey))
{
- throw new ArgumentException($"Buffer must be exactly {SecretKeySize} bytes long", nameof(buffer));
+ throw new ArgumentException($"Buffer must be exactly {sizeof(Secp256k1SecretKey)} bytes long", nameof(buffer));
}
//Fill the buffer with random bytes
@@ -227,6 +244,28 @@ namespace NVault.Crypto.Secp256k1
_randomSource.GetRandomBytes(buffer);
}
+ /// <summary>
+ /// Creates a new <see cref="Secp256k1Context"/> from the current managed library
+ /// </summary>
+ /// <param name="Lib"></param>
+ /// <returns>The new <see cref="Secp256k1Context"/> object from the library</returns>
+ /// <exception cref="OutOfMemoryException"></exception>
+ public Secp256k1Context CreateContext()
+ {
+ //Protect for released lib
+ SafeLibHandle.ThrowIfClosed();
+
+ //Create new context
+ IntPtr context = _create(1);
+
+ if (context == IntPtr.Zero)
+ {
+ throw new OutOfMemoryException("Failed to create the new Secp256k1 context");
+ }
+
+ return new Secp256k1Context(this, context);
+ }
+
protected override void Free()
{
//Free native library
diff --git a/back-end/libs/NVault.Crypto.Secp256k1/src/Secp256HashFuncState.cs b/back-end/libs/NVault.Crypto.Secp256k1/src/Secp256HashFuncState.cs
new file mode 100644
index 0000000..4ee745c
--- /dev/null
+++ b/back-end/libs/NVault.Crypto.Secp256k1/src/Secp256HashFuncState.cs
@@ -0,0 +1,56 @@
+// Copyright (C) 2023 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 NVault.Crypto.Secp256k1
+{
+ [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);
+ }
+} \ No newline at end of file
diff --git a/back-end/libs/NVault.Crypto.Secp256k1/src/Secp256k1Context.cs b/back-end/libs/NVault.Crypto.Secp256k1/src/Secp256k1Context.cs
index 67f1d9f..f0a795a 100644
--- a/back-end/libs/NVault.Crypto.Secp256k1/src/Secp256k1Context.cs
+++ b/back-end/libs/NVault.Crypto.Secp256k1/src/Secp256k1Context.cs
@@ -14,7 +14,6 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
using System;
-using System.Runtime.InteropServices;
using VNLib.Utils.Extensions;
using VNLib.Utils.Memory;
@@ -54,15 +53,12 @@ namespace NVault.Crypto.Secp256k1
return result;
}
- internal unsafe readonly bool CreateKeyPair(KeyPair* keyPair, ReadOnlySpan<byte> secretKey)
+ internal unsafe readonly bool CreateKeyPair(KeyPair* keyPair, Secp256k1SecretKey* secretKey)
{
Lib.SafeLibHandle.ThrowIfClosed();
- fixed (byte* sk = &MemoryMarshal.GetReference(secretKey))
- {
- //Create the keypair from the secret key
- return Lib._createKeyPair(Context, keyPair, sk) == 1;
- }
+ //Create the keypair from the secret key
+ return Lib._createKeyPair(Context, keyPair, (byte*)secretKey) == 1;
}
/// <summary>
diff --git a/back-end/libs/NVault.Crypto.Secp256k1/src/Secp256k1SecretKey.cs b/back-end/libs/NVault.Crypto.Secp256k1/src/Secp256k1SecretKey.cs
new file mode 100644
index 0000000..7224720
--- /dev/null
+++ b/back-end/libs/NVault.Crypto.Secp256k1/src/Secp256k1SecretKey.cs
@@ -0,0 +1,58 @@
+// Copyright (C) 2023 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;
+
+using VNLib.Utils.Memory;
+
+namespace NVault.Crypto.Secp256k1
+{
+ /// <summary>
+ /// Represents a Secp256k1 secret key, the size is fixed, and should use
+ /// the sizeof() operator to get the size
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential, Size = 32)]
+ public unsafe struct Secp256k1SecretKey
+ {
+ private fixed byte data[32];
+
+ /// <summary>
+ /// Implict cast to a span of raw bytes
+ /// </summary>
+ /// <param name="key">The secret key to cast</param>
+ public static implicit operator Span<byte>(Secp256k1SecretKey key) => new(key.data, 32);
+
+ /// <summary>
+ /// Casts the secret key span to a <see cref="Secp256k1SecretKey"/> via a structure copy
+ /// </summary>
+ /// <param name="key">The key data to copy</param>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public static explicit operator Secp256k1SecretKey(ReadOnlySpan<byte> key) => FromSpan(key);
+
+ /// <summary>
+ /// Creates a new <see cref="Secp256k1SecretKey"/> from a span of bytes
+ /// by copying the bytes into the struct
+ /// </summary>
+ /// <param name="span">The secret key data to copy</param>
+ /// <returns>An initilaized <see cref="Secp256k1SecretKey"/></returns>
+ public static Secp256k1SecretKey FromSpan(ReadOnlySpan<byte> span)
+ {
+ Secp256k1SecretKey newKey = new();
+ MemoryUtil.CopyStruct(span, ref newKey);
+ return newKey;
+ }
+ }
+} \ No newline at end of file
diff --git a/back-end/plugins/nvault/src/Endpoints/Endpoint.cs b/back-end/plugins/nvault/src/Endpoints/Endpoint.cs
index bcebc63..4223a10 100644
--- a/back-end/plugins/nvault/src/Endpoints/Endpoint.cs
+++ b/back-end/plugins/nvault/src/Endpoints/Endpoint.cs
@@ -134,7 +134,7 @@ namespace NVault.Plugins.Vault.Endpoints
//Get the key metadata
NostrKeyMeta? keyMeta = await _publicKeyStore.GetSingleUserRecordAsync(nEvent.KeyId, entity.Session.UserID);
- if(webm.Assert(keyMeta != null, "Key not found"))
+ if(webm.Assert(keyMeta?.Value != null, "Key not found"))
{
return VirtualClose(entity, webm, HttpStatusCode.NotFound);
}
@@ -520,7 +520,7 @@ namespace NVault.Plugins.Vault.Endpoints
.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 == NostrOpProvider.MaxBase64EncodedSize)
+ .Must(ct => ct.AsSpan().SliceAfterParam("?iv=").Length == NostrOpProvider.IvMaxBase64EncodedSize)
.WithMessage("iv is not the correct size");
//Pubpkey must be 64 hex characters
diff --git a/back-end/plugins/nvault/src/INostrCryptoProvider.cs b/back-end/plugins/nvault/src/INostrCryptoProvider.cs
index d6c1e8a..b66757c 100644
--- a/back-end/plugins/nvault/src/INostrCryptoProvider.cs
+++ b/back-end/plugins/nvault/src/INostrCryptoProvider.cs
@@ -61,8 +61,27 @@ namespace NVault.Plugins.Vault
/// <returns>True if the operation succeeded, false otherwise</returns>
bool RecoverPublicKey(ReadOnlySpan<byte> privateKey, Span<byte> pubKey);
+ /// <summary>
+ /// Decrypts a Nostr encrypted message by the target's public key, and the local secret key.
+ /// Both keys will be used to compute the shared secret that will be used to decrypt the message.
+ /// </summary>
+ /// <param name="secretKey">The local secret key</param>
+ /// <param name="targetKey">The message's target public key for the shared secret</param>
+ /// <param name="aseIv">The initialization vector used to encrypt the message</param>
+ /// <param name="cyphterText">The cyphertext to decrypt</param>
+ /// <param name="outputBuffer">The output buffer to write plaintext data to</param>
+ /// <returns>The number of bytes written to the output, 0 or negative for an error</returns>
ERRNO DecryptMessage(ReadOnlySpan<byte> secretKey, ReadOnlySpan<byte> targetKey, ReadOnlySpan<byte> aseIv, ReadOnlySpan<byte> cyphterText, Span<byte> outputBuffer);
+ /// <summary>
+ /// Encrypts a message with the specified secret key, target public key, and initialization vector.
+ /// </summary>
+ /// <param name="secretKey"></param>
+ /// <param name="targetKey"></param>
+ /// <param name="aesIv">The initalization vector used by the AES cipher to encrypt data</param>
+ /// <param name="plainText">The plaintext data to encrypt</param>
+ /// <param name="cipherText">The ciphertext output buffer</param>
+ /// <returns>The number of bytes written to the output buffer, 0 or negative on error</returns>
ERRNO EncryptMessage(ReadOnlySpan<byte> secretKey, ReadOnlySpan<byte> targetKey, ReadOnlySpan<byte> aesIv, ReadOnlySpan<byte> plainText, Span<byte> cipherText);
/// <summary>
diff --git a/back-end/plugins/nvault/src/NativeSecp256k1Library.cs b/back-end/plugins/nvault/src/NativeSecp256k1Library.cs
index 0870156..2fcf447 100644
--- a/back-end/plugins/nvault/src/NativeSecp256k1Library.cs
+++ b/back-end/plugins/nvault/src/NativeSecp256k1Library.cs
@@ -76,7 +76,7 @@ namespace NVault.Plugins.Vault
finally
{
//Zero out buffers
- MemoryUtil.InitializeBlock(sharedKeyBuffer.AsSpan());
+ MemoryUtil.InitializeBlock(sharedKeyBuffer);
}
}
@@ -114,7 +114,7 @@ namespace NVault.Plugins.Vault
finally
{
//Zero out buffers
- MemoryUtil.InitializeBlock(sharedKeyBuffer.AsSpan());
+ MemoryUtil.InitializeBlock(sharedKeyBuffer);
}
}
diff --git a/back-end/plugins/nvault/src/NostrOpProvider.cs b/back-end/plugins/nvault/src/NostrOpProvider.cs
index aa4840e..5908e26 100644
--- a/back-end/plugins/nvault/src/NostrOpProvider.cs
+++ b/back-end/plugins/nvault/src/NostrOpProvider.cs
@@ -39,7 +39,7 @@ namespace NVault.Plugins.Vault
internal sealed class NostrOpProvider : INostrOperations
{
public const int AES_IV_SIZE = 16;
- public static int MaxBase64EncodedSize { get; } = Base64.GetMaxEncodedToUtf8Length(AES_IV_SIZE);
+ public static int IvMaxBase64EncodedSize { get; } = Base64.GetMaxEncodedToUtf8Length(AES_IV_SIZE);
private static JavaScriptEncoder _encoder { get; } = GetJsEncoder();
@@ -289,9 +289,7 @@ namespace NVault.Plugins.Vault
string? outText = null, ivText = null;
//Call decipher method
- bool result = Nip04Cipher(secret.ToReadOnlySpan(), nip04Ciphertext.AsSpan(), targetPubkey, ref outText, ref ivText, false);
-
- if (result)
+ if (Nip04Cipher(secret.ToReadOnlySpan(), nip04Ciphertext.AsSpan(), targetPubkey, ref outText, ref ivText, false))
{
return outText;
}
@@ -307,16 +305,13 @@ namespace NVault.Plugins.Vault
//Recover target public key
byte[] targetPubkey = Convert.FromHexString(targetPubKeyHex);
- //Get key data from the vault
- using PrivateString? secret = await _vault.GetSecretAsync(scope, keyMeta.Id, cancellation);
+ //Get key data from the vault (key should always exist, but may get out of sync if manually deleted)
+ using PrivateString? secret = await _vault.GetSecretAsync(scope, keyMeta.Id, cancellation) ?? throw new ArgumentException("Secret key not found in vault");
- string? outputText = null,
- ivText = null;
-
- //Call decipher method
- bool result = Nip04Cipher(secret.ToReadOnlySpan(), plainText, targetPubkey, ref outputText, ref ivText, true);
+ string? outputText = null, ivText = null;
- if (result)
+ //Call encipher method
+ if (Nip04Cipher(secret.ToReadOnlySpan(), plainText, targetPubkey, ref outputText, ref ivText, true))
{
return new()
{
@@ -391,7 +386,7 @@ namespace NVault.Plugins.Vault
ReadOnlySpan<char> cipherText = text.SliceBeforeParam("?iv=");
ReadOnlySpan<char> ivSegment = text.SliceAfterParam("?iv=");
- if (ivSegment.Length > MaxBase64EncodedSize)
+ if (ivSegment.Length > IvMaxBase64EncodedSize)
{
throw new ArgumentException("initialization vector is larger than allowed");
}
diff --git a/extension/README.md b/extension/README.md
index 36b26c2..a476f96 100644
--- a/extension/README.md
+++ b/extension/README.md
@@ -1,65 +1,20 @@
# @vnuge/nvault-extension
-This template should help get you started developing a vue web extension in Vite.
+This directory contains the source code for the NVault browser extension. Base template forked from [@samrum/vite-plugin-web-extension](https://github.com/samrum/vite-plugin-web-extension)
## Usage Notes
+The .env file contains build configuration variables. API variables are used as defaults on extension startup. Most settings such as server base url and endpoint urls are configurable from the extension options page.
-The extension manifest is defined in `src/manifest.js` and used by `@samrum/vite-plugin-web-extension` in the vite config.
+### Install dependencies
-Background, content scripts, options, and popup entry points exist in the `src/entries` directory.
-
-Content scripts are rendered by `src/entries/contentScript/renderContent.js` which renders content within a ShadowRoot
-and handles style injection for HMR and build modes.
-
-Otherwise, the project functions just like a regular Vite project.
-
-To switch between Manifest V2 and Manifest V3 builds, use the MANIFEST_VERSION environment variable defined in `.env`
-
-HMR during development in Manifest V3 requires Chromium version >= 110.0.5480.0.
-
-Refer to [@samrum/vite-plugin-web-extension](https://github.com/samrum/vite-plugin-web-extension) for more usage notes.
-
-## Customize configuration
-
-See [Vite Configuration Reference](https://vitejs.dev/config/).
-
-## Project Setup
-
-```sh
+```bash
npm install
```
-## Commands
-### Build
-#### Development, HMR
-
-Hot Module Reloading is used to load changes inline without requiring extension rebuilds and extension/page reloads
-Currently only works in Chromium based browsers.
-```sh
-npm run dev
-```
-
-#### Development, Watch
-
-Rebuilds extension on file changes. Requires a reload of the extension (and page reload if using content scripts)
-```sh
-npm run watch
-```
-
-#### Production
-
-Minifies and optimizes extension build
-```sh
+### Build the extension
+
+```bash
npm run build
```
-### Load extension in browser
-
-Loads the contents of the dist directory into the specified browser
-```sh
-npm run serve:chrome
-```
-
-```sh
-npm run serve:firefox
-```
+Built extension output will be in the `dist` directory. You can zip the contents of this directory and load it into your browser. \ No newline at end of file
diff --git a/extension/src/entries/background/serviceWorker.ts b/extension/src/entries/background/serviceWorker.js
index cb6f42a..b0211d1 100644
--- a/extension/src/entries/background/serviceWorker.ts
+++ b/extension/src/entries/background/serviceWorker.js
@@ -13,4 +13,4 @@
// 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/>.
-import "./main";
+import "./main.ts";
diff --git a/extension/src/entries/contentScript/primary/components/PromptPopup.vue b/extension/src/entries/contentScript/primary/components/PromptPopup.vue
index d019b5d..156dfb8 100644
--- a/extension/src/entries/contentScript/primary/components/PromptPopup.vue
+++ b/extension/src/entries/contentScript/primary/components/PromptPopup.vue
@@ -85,12 +85,13 @@
<script setup lang="ts">
import { ref } from 'vue'
-import { usePrompt, type UserPermissionRequest } from '../../util'
+import { debugLog } from '@vnuge/vnlib.browser';
+import { storeToRefs } from 'pinia';
import { computed } from 'vue';
import { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'
import { clone, first } from 'lodash';
+import { usePrompt, type UserPermissionRequest } from '../../util'
import { useStore } from '../../../store';
-import { storeToRefs } from 'pinia';
const store = useStore()
const { loggedIn, selectedKey, darkMode } = storeToRefs(store)
@@ -127,7 +128,7 @@ usePrompt((ev: UserPermissionRequest):Promise<boolean> => {
ev = clone(ev)
- console.log('[usePrompt] =>', ev)
+ debugLog('[usePrompt] =>', ev)
switch(ev.type){
case 'getPublicKey':
diff --git a/extension/src/entries/contentScript/primary/main.js b/extension/src/entries/contentScript/primary/main.js
index 16cc6fc..bbe5edf 100644
--- a/extension/src/entries/contentScript/primary/main.js
+++ b/extension/src/entries/contentScript/primary/main.js
@@ -51,12 +51,12 @@ renderContent([], (appRoot, shadowRoot) => {
//Add tailwind styles just to the shadow dom element
const style = document.createElement('style')
- style.innerHTML = tw.toString()
+ style.textContent = tw.toString()
shadowRoot.appendChild(style)
//Add local styles
const style2 = document.createElement('style')
- style2.innerHTML = localStyle.toString()
+ style2.textContent = localStyle.toString()
shadowRoot.appendChild(style2)
createApp(App)
diff --git a/extension/src/entries/store/identity.ts b/extension/src/entries/store/identity.ts
index b1635f2..ef1941e 100644
--- a/extension/src/entries/store/identity.ts
+++ b/extension/src/entries/store/identity.ts
@@ -25,7 +25,6 @@ export const identityPlugin = ({ store }: PiniaPluginContext) => {
const selectedKey = shallowRef<NostrPubKey | undefined>(undefined)
onWatchableChange(identity, async () => {
- console.log('Identity changed')
allKeys.value = await identity.getAllKeys();
selectedKey.value = await identity.getPublicKey();
}, { immediate:true })
diff --git a/extension/src/manifest.js b/extension/src/manifest.js
index 6c96f41..f4c38fc 100644
--- a/extension/src/manifest.js
+++ b/extension/src/manifest.js
@@ -41,20 +41,18 @@ const sharedManifest = {
'activeTab',
],
-
browser_specific_settings: {
"gecko": {
- "id": "{fdacee2c-bab4-490d-bc4b-ecdd03d5d68a}"
+ "id": "{d71bf2c0-7485-4572-b1a5-c5dd2c5f16d5}"
}
},
- "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';"
+ "content_security_policy": "script-src 'self'; object-src 'self';"
};
const browserAction = {
default_icon: {
16: "icons/16.png",
- 19: "icons/19.png",
32: "icons/32.png",
38: "icons/38.png",
},
diff --git a/extension/tsconfig.json b/extension/tsconfig.json
index ca3b4f0..ea75d8b 100644
--- a/extension/tsconfig.json
+++ b/extension/tsconfig.json
@@ -23,5 +23,5 @@
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
- "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
+ "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/entries/background/serviceWorker.js"],
}