// 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 . using System; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using VNLib.Utils.Extensions; using VNLib.Utils.Cryptography.Noscrypt.@internal; using static VNLib.Utils.Cryptography.Noscrypt.NoscryptLibrary; using NCResult = System.Int64; namespace VNLib.Utils.Cryptography.Noscrypt { /// /// Contains utility methods for working with nostr keys /// public static unsafe class NCKeyUtil { /// /// Gets a span of bytes from the current secret key /// structure /// /// /// The secret key data span public unsafe static Span AsSpan(this ref NCSecretKey key) { //Safe to cast secret key to bytes, then we can make a span to its memory ref byte asBytes = ref Unsafe.As(ref key); return MemoryMarshal.CreateSpan(ref asBytes, sizeof(NCSecretKey)); } /// /// Gets a span of bytes from the current public key /// structure /// /// /// The public key data as a data span public unsafe static Span AsSpan(this ref NCPublicKey key) { //Safe to cast secret key to bytes, then we can make a span to its memory ref byte asBytes = ref Unsafe.As(ref key); return MemoryMarshal.CreateSpan(ref asBytes, sizeof(NCPublicKey)); } /// /// Casts a span of bytes to a secret key reference. Note that /// the new structure reference will point to the same memory /// as the span. /// /// The secret key data /// A mutable secret key reference /// public unsafe static ref NCSecretKey AsSecretKey(Span span) { ArgumentOutOfRangeException.ThrowIfLessThan(span.Length, sizeof(NCSecretKey), nameof(span)); ref byte asBytes = ref MemoryMarshal.GetReference(span); return ref Unsafe.As(ref asBytes); } /// /// Casts a span of bytes to a public key reference. Note that /// the new structure reference will point to the same memory /// as the span. /// /// The public key data span /// A mutable reference to the public key structure /// public unsafe static ref NCPublicKey AsPublicKey(Span span) { ArgumentOutOfRangeException.ThrowIfLessThan(span.Length, sizeof(NCPublicKey), nameof(span)); ref byte asBytes = ref MemoryMarshal.GetReference(span); return ref Unsafe.As(ref asBytes); } /// /// Casts a read-only span of bytes to a secret key reference. Note that /// the new structure reference will point to the same memory as the span. /// /// The secret key data span /// A readonly refernce to the secret key structure /// public unsafe static ref readonly NCSecretKey AsSecretKey(ReadOnlySpan span) { ArgumentOutOfRangeException.ThrowIfLessThan(span.Length, sizeof(NCSecretKey), nameof(span)); ref byte asBytes = ref MemoryMarshal.GetReference(span); return ref Unsafe.As(ref asBytes); } /// /// Casts a read-only span of bytes to a public key reference. Note that /// the new structure reference will point to the same memory as the span. /// /// The public key data span /// A readonly reference to the public key structure /// public unsafe static ref readonly NCPublicKey AsPublicKey(ReadOnlySpan span) { ArgumentOutOfRangeException.ThrowIfLessThan(span.Length, sizeof(NCPublicKey), nameof(span)); ref byte asBytes = ref MemoryMarshal.GetReference(span); return ref Unsafe.As(ref asBytes); } /// /// Gets a nostr public key from a secret key. /// /// A reference to the secret key to get the public key from /// A reference to the public key structure to write the recovered key to /// /// public static void GetPublicKey( NCContext context, ref readonly NCSecretKey secretKey, ref NCPublicKey publicKey ) { Check(context); fixed (NCSecretKey* pSecKey = &secretKey) fixed (NCPublicKey* pPubKey = &publicKey) { NCResult result = GetTable(context).NCGetPublicKey( context.DangerousGetHandle(), pSecKey, pPubKey ); NCUtil.CheckResult(result, raiseOnFailure: true); } } /// /// Validates a secret key is in a valid format. /// /// A readonly reference to key structure to validate /// True if the key is consiered valid against the secp256k1 curve /// /// public static bool ValidateSecretKey( NCContext context, ref readonly NCSecretKey secretKey ) { Check(context); fixed (NCSecretKey* pSecKey = &secretKey) { NCResult result = GetTable(context).NCValidateSecretKey( context.DangerousGetHandle(), pSecKey ); NCUtil.CheckResult(result, raiseOnFailure: false); return result == NC_SUCCESS; } } private static void Check(NCContext? context) { ArgumentNullException.ThrowIfNull(context); context.ThrowIfClosed(); } private static ref readonly FunctionTable GetTable(NCContext ctx) => ref ctx.Library.Functions; } }