diff options
-rw-r--r-- | lib/Hashing.Portable/src/IdentityUtility/JsonWebKey.cs | 18 | ||||
-rw-r--r-- | lib/Hashing.Portable/src/IdentityUtility/JwtExtensions.cs | 15 | ||||
-rw-r--r-- | lib/Hashing.Portable/src/ManagedHash.cs | 30 |
3 files changed, 52 insertions, 11 deletions
diff --git a/lib/Hashing.Portable/src/IdentityUtility/JsonWebKey.cs b/lib/Hashing.Portable/src/IdentityUtility/JsonWebKey.cs index ef85e5d..a741762 100644 --- a/lib/Hashing.Portable/src/IdentityUtility/JsonWebKey.cs +++ b/lib/Hashing.Portable/src/IdentityUtility/JsonWebKey.cs @@ -43,6 +43,7 @@ namespace VNLib.Hashing.IdentityUtility public const string ES256 = "ES256"; public const string ES384 = "ES384"; public const string ES512 = "ES512"; + public const string ES256K = "ES256K"; } public class EncryptionTypeNotSupportedException : NotSupportedException @@ -162,6 +163,11 @@ namespace VNLib.Hashing.IdentityUtility using ECDsa? eCDsa = GetECDsaPublicKey(jwk); return eCDsa != null && token.Verify(eCDsa, HashAlg.SHA512); } + case JWKAlgorithms.ES256K: + { + using ECDsa? eCDsa = GetECDsaPublicKey(jwk); + return eCDsa != null && token.Verify(eCDsa, HashAlg.SHA256); + } default: throw new EncryptionTypeNotSupportedException(); } @@ -259,6 +265,13 @@ namespace VNLib.Hashing.IdentityUtility token.Sign(eCDsa, HashAlg.SHA512); return; } + case JWKAlgorithms.ES256K: + { + using ECDsa? eCDsa = GetECDsaPrivateKey(jwk); + _ = eCDsa ?? throw new InvalidOperationException("JWK Does not contain an ECDsa private key"); + token.Sign(eCDsa, HashAlg.SHA512); + return; + } default: throw new EncryptionTypeNotSupportedException(); } @@ -337,7 +350,7 @@ namespace VNLib.Hashing.IdentityUtility /// </summary> /// <param name="jwk">The public key element</param> /// <returns>The <see cref="ECDsa"/> algorithm from the key if loaded, null if no key data was found</returns> - public static ECDsa? GetECDsaPublicKey<TKey>(this TKey jwk) where TKey: IJsonWebKey + public static ECDsa? GetECDsaPublicKey<TKey>(this TKey jwk) where TKey : IJsonWebKey { //Get the EC params ECParameters? ecParams = GetECParameters(in jwk, false); @@ -386,6 +399,9 @@ namespace VNLib.Hashing.IdentityUtility case "P-521": curve = ECCurve.NamedCurves.nistP521; break; + case "SECP256K1": + curve = ManagedHash.CurveSecp256k1; + break; default: return null; } diff --git a/lib/Hashing.Portable/src/IdentityUtility/JwtExtensions.cs b/lib/Hashing.Portable/src/IdentityUtility/JwtExtensions.cs index 34211e5..2177aac 100644 --- a/lib/Hashing.Portable/src/IdentityUtility/JwtExtensions.cs +++ b/lib/Hashing.Portable/src/IdentityUtility/JwtExtensions.cs @@ -501,7 +501,7 @@ namespace VNLib.Hashing.IdentityUtility /* * Simple ecdsa and rsa providers */ - private record struct ECDSASignatureProvider(ECDsa SigAlg, DSASignatureFormat Format) : IJwtSignatureProvider + private readonly record struct ECDSASignatureProvider(ECDsa SigAlg, DSASignatureFormat Format) : IJwtSignatureProvider { ///<inheritdoc/> public readonly int RequiredBufferSize { get; } = 512; @@ -513,7 +513,7 @@ namespace VNLib.Hashing.IdentityUtility } } - internal record struct RSASignatureProvider(RSA SigAlg, HashAlg Slg, RSASignaturePadding Padding) : IJwtSignatureProvider + internal readonly record struct RSASignatureProvider(RSA SigAlg, HashAlg Slg, RSASignaturePadding Padding) : IJwtSignatureProvider { ///<inheritdoc/> public readonly int RequiredBufferSize { get; } = 1024; @@ -528,19 +528,16 @@ namespace VNLib.Hashing.IdentityUtility /* * ECDSA and rsa verifiers */ - internal record struct ECDSASignatureVerifier(ECDsa Alg, DSASignatureFormat Format) : IJwtSignatureVerifier + internal readonly record struct ECDSASignatureVerifier(ECDsa Alg, DSASignatureFormat Format) : IJwtSignatureVerifier { - public readonly bool Verify(ReadOnlySpan<byte> messageHash, ReadOnlySpan<byte> signature) - { - return Alg.VerifyHash(messageHash, signature); - } + public readonly bool Verify(ReadOnlySpan<byte> messageHash, ReadOnlySpan<byte> signature) => Alg.VerifyHash(messageHash, signature); } - internal record struct RSASignatureVerifier(RSA Alg, HashAlg hashAlg, RSASignaturePadding Padding) : IJwtSignatureVerifier + internal readonly record struct RSASignatureVerifier(RSA Alg, HashAlg HashAlg, RSASignaturePadding Padding) : IJwtSignatureVerifier { public readonly bool Verify(ReadOnlySpan<byte> messageHash, ReadOnlySpan<byte> signature) { - return Alg.VerifyHash(messageHash, signature, hashAlg.GetAlgName(), Padding); + return Alg.VerifyHash(messageHash, signature, HashAlg.GetAlgName(), Padding); } } } diff --git a/lib/Hashing.Portable/src/ManagedHash.cs b/lib/Hashing.Portable/src/ManagedHash.cs index 70cc5c0..5a6aaba 100644 --- a/lib/Hashing.Portable/src/ManagedHash.cs +++ b/lib/Hashing.Portable/src/ManagedHash.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Vaughn Nugent +* Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: VNLib.Hashing.Portable @@ -92,6 +92,34 @@ namespace VNLib.Hashing private static readonly Encoding CharEncoding = Encoding.UTF8; /// <summary> + /// A .NET explicit ECCurve for the secp256k1 EC curve algorithm + /// </summary> + public static ECCurve CurveSecp256k1 { get; } = GetStaticCurve(); + + private static ECCurve GetStaticCurve() + { + //Curve parameters from https://www.secg.org/sec2-v2.pdf + return new() + { + CurveType = ECCurve.ECCurveType.PrimeShortWeierstrass, + + Prime = Convert.FromHexString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"), + + A = Convert.FromHexString("0000000000000000000000000000000000000000000000000000000000000000"), + B = Convert.FromHexString("0000000000000000000000000000000000000000000000000000000000000007"), + + G = new ECPoint() + { + X = Convert.FromHexString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"), + Y = Convert.FromHexString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8") + }, + + Order = Convert.FromHexString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"), + Cofactor = Convert.FromHexString("01") + }; + } + + /// <summary> /// Uses the UTF8 character encoding to encode the string, then /// attempts to compute the hash and store the results into the output buffer /// </summary> |