aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-04-26 20:33:29 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2023-04-26 20:33:29 -0400
commitb0df3871f71e9bafdde3808f81984ac871eef2d4 (patch)
tree058493d77c3a1556c19073690ce8f601c1adcb48
parent311f8cbb0ffe623134896c696b71339fb1ab3954 (diff)
Explicit Secp256k1 EC support for JWK and JWT
-rw-r--r--lib/Hashing.Portable/src/IdentityUtility/JsonWebKey.cs18
-rw-r--r--lib/Hashing.Portable/src/IdentityUtility/JwtExtensions.cs15
-rw-r--r--lib/Hashing.Portable/src/ManagedHash.cs30
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>