diff --git a/src/ScottBrady.IdentityModel/Tokens/EdDsa.cs b/src/ScottBrady.IdentityModel/Tokens/EdDsa.cs index 7594f51..ed59500 100644 --- a/src/ScottBrady.IdentityModel/Tokens/EdDsa.cs +++ b/src/ScottBrady.IdentityModel/Tokens/EdDsa.cs @@ -40,31 +40,44 @@ public static EdDsa Create(EdDsaParameters parameters) public new static EdDsa Create(string curve) { if (string.IsNullOrWhiteSpace(curve)) throw new ArgumentNullException(nameof(curve)); - - IAsymmetricCipherKeyPairGenerator generator; + if (curve == ExtendedSecurityAlgorithms.Curves.Ed25519) { - generator = new Ed25519KeyPairGenerator(); + var generator = new Ed25519KeyPairGenerator(); generator.Init(new Ed25519KeyGenerationParameters(new SecureRandom())); + var keyPair = generator.GenerateKeyPair(); + return new EdDsa + { + Parameters = new EdDsaParameters(curve) + { + D = ((Ed25519PrivateKeyParameters) keyPair.Private).GetEncoded(), + X = ((Ed25519PublicKeyParameters) keyPair.Public).GetEncoded() + }, + PrivateKeyParameter = keyPair.Private, + PublicKeyParameter = keyPair.Public + }; } - else if (curve == ExtendedSecurityAlgorithms.Curves.Ed448) + + if (curve == ExtendedSecurityAlgorithms.Curves.Ed448) { - generator = new Ed448KeyPairGenerator(); + var generator = new Ed448KeyPairGenerator(); generator.Init(new Ed448KeyGenerationParameters(new SecureRandom())); + var keyPair = generator.GenerateKeyPair(); + + return new EdDsa + { + Parameters = new EdDsaParameters(curve) + { + D = ((Ed448PrivateKeyParameters) keyPair.Private).GetEncoded(), + X = ((Ed448PublicKeyParameters) keyPair.Public).GetEncoded() + }, + PrivateKeyParameter = keyPair.Private, + PublicKeyParameter = keyPair.Public + }; } - else - { - throw new NotSupportedException("Unsupported EdDSA curve"); - } - - var keyPair = generator.GenerateKeyPair(); - return new EdDsa - { - Parameters = new EdDsaParameters(keyPair, curve), - PrivateKeyParameter = keyPair.Private, - PublicKeyParameter = keyPair.Public - }; + + throw new NotSupportedException("Unsupported EdDSA curve"); } public override string KeyExchangeAlgorithm => null; @@ -91,7 +104,6 @@ public byte[] Sign(byte[] input) public bool Verify(byte[] input, int inputOffset, int inputLength, byte[] signature, int signatureOffset, int signatureLength) { - if (input == null) throw new ArgumentNullException(nameof(input)); if (signature == null) throw new ArgumentNullException(nameof(signature)); if (inputLength <= 0) throw new ArgumentException($"{nameof(inputLength)} must be greater than 0"); diff --git a/src/ScottBrady.IdentityModel/Tokens/EdDsaParameters.cs b/src/ScottBrady.IdentityModel/Tokens/EdDsaParameters.cs index 805e408..2e5ea62 100644 --- a/src/ScottBrady.IdentityModel/Tokens/EdDsaParameters.cs +++ b/src/ScottBrady.IdentityModel/Tokens/EdDsaParameters.cs @@ -1,7 +1,5 @@ using System; using System.Security.Cryptography; -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Parameters; using ScottBrady.IdentityModel.Crypto; namespace ScottBrady.IdentityModel.Tokens; @@ -15,25 +13,7 @@ public EdDsaParameters(string curve) Curve = curve; } - internal EdDsaParameters(AsymmetricCipherKeyPair keyPair, string curve) : this(curve) - { - if (keyPair == null) throw new ArgumentNullException(nameof(keyPair)); - - if (curve == ExtendedSecurityAlgorithms.Curves.Ed25519) - { - D = ((Ed25519PrivateKeyParameters) keyPair.Private).GetEncoded(); - X = ((Ed25519PublicKeyParameters) keyPair.Public).GetEncoded(); - } - else if (curve == ExtendedSecurityAlgorithms.Curves.Ed448) - { - D = ((Ed448PrivateKeyParameters) keyPair.Private).GetEncoded(); - X = ((Ed448PublicKeyParameters) keyPair.Public).GetEncoded(); - } - else - { - throw new NotSupportedException("Unsupported EdDSA curve"); - } - } + // TODO: ctor for signing key? 64 bytes, concatenation of private and public key? https://github.com/openssl/openssl/issues/6357 public byte[] D { get; init; } public byte[] X { get; init; } diff --git a/src/ScottBrady.IdentityModel/Tokens/EdDsaSecurityKey.cs b/src/ScottBrady.IdentityModel/Tokens/EdDsaSecurityKey.cs index b8cc3ab..fc705de 100644 --- a/src/ScottBrady.IdentityModel/Tokens/EdDsaSecurityKey.cs +++ b/src/ScottBrady.IdentityModel/Tokens/EdDsaSecurityKey.cs @@ -1,6 +1,5 @@ using System; using Microsoft.IdentityModel.Tokens; -using Org.BouncyCastle.Crypto.Parameters; using ScottBrady.IdentityModel.Crypto; namespace ScottBrady.IdentityModel.Tokens; @@ -11,30 +10,12 @@ namespace ScottBrady.IdentityModel.Tokens; public class EdDsaSecurityKey : AsymmetricSecurityKey { public EdDsa EdDsa { get; } - - private EdDsaSecurityKey() - { - CryptoProviderFactory.CustomCryptoProvider = new ExtendedCryptoProvider(); - } - public EdDsaSecurityKey(EdDsa edDsa) : this() + public EdDsaSecurityKey(EdDsa edDsa) { + CryptoProviderFactory.CustomCryptoProvider = new ExtendedCryptoProvider(); EdDsa = edDsa ?? throw new ArgumentNullException(nameof(edDsa)); } - - [Obsolete("Deprecated in favor of EdDsa constructor")] - public EdDsaSecurityKey(Ed25519PrivateKeyParameters keyParameters) : this() - { - if (keyParameters == null) throw new ArgumentNullException(nameof(keyParameters)); - EdDsa = EdDsa.Create(new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) {D = keyParameters.GetEncoded()}); - } - - [Obsolete("Deprecated in favor of EdDsa constructor")] - public EdDsaSecurityKey(Ed25519PublicKeyParameters keyParameters) : this() - { - if (keyParameters == null) throw new ArgumentNullException(nameof(keyParameters)); - EdDsa = EdDsa.Create(new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) {X = keyParameters.GetEncoded()}); - } public override int KeySize => EdDsa.KeySize; diff --git a/test/ScottBrady.IdentityModel.Tests/Tokens/EdDSA/EdDsaParametersTests.cs b/test/ScottBrady.IdentityModel.Tests/Tokens/EdDSA/EdDsaParametersTests.cs index 0bdabe9..1350182 100644 --- a/test/ScottBrady.IdentityModel.Tests/Tokens/EdDSA/EdDsaParametersTests.cs +++ b/test/ScottBrady.IdentityModel.Tests/Tokens/EdDSA/EdDsaParametersTests.cs @@ -1,10 +1,6 @@ using System; using System.Security.Cryptography; using FluentAssertions; -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Generators; -using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Security; using ScottBrady.IdentityModel.Crypto; using ScottBrady.IdentityModel.Tokens; using Xunit; @@ -13,7 +9,6 @@ namespace ScottBrady.IdentityModel.Tests.Tokens.EdDSA; public class EdDsaParametersTests { - [Theory] [InlineData(null)] [InlineData("")] @@ -32,49 +27,6 @@ public void ctor_ExpectCorrectCurve() var parameters = new EdDsaParameters(curve); parameters.Curve.Should().Be(curve); } - - [Fact] - public void ctor_Parameters_WhenKeyPairIsNull_ExpectArgumentNullException() - => Assert.Throws(() => new EdDsaParameters(null, ExtendedSecurityAlgorithms.Curves.Ed448)); - - [Theory] - [InlineData(null)] - [InlineData("")] - [InlineData(" ")] - public void ctor_Parameters_WhenCurveIsNullOrWhitespace_ExpectArgumentNullException(string curve) - => Assert.Throws(() => new EdDsaParameters(GenerateEd448KeyPair(), curve)); - - [Fact] - public void ctor_Parameters_WhenUnsupportedAlgorithm_ExpectNotSupportedException() - => Assert.Throws(() => new EdDsaParameters(GenerateEd448KeyPair(), "P-256")); - - [Fact] - public void ctor_Parameters_WhenEd25519KeyPair_ExpectCorrectParameters() - { - var keyPair = GenerateEd25519KeyPair(); - var expectedPrivateKey = ((Ed25519PrivateKeyParameters) keyPair.Private).GetEncoded(); - var expectedPublicKey = ((Ed25519PublicKeyParameters) keyPair.Public).GetEncoded(); - - var parameters = new EdDsaParameters(keyPair, ExtendedSecurityAlgorithms.Curves.Ed25519); - - parameters.Curve.Should().Be(ExtendedSecurityAlgorithms.Curves.Ed25519); - parameters.D.Should().BeEquivalentTo(expectedPrivateKey); - parameters.X.Should().BeEquivalentTo(expectedPublicKey); - } - - [Fact] - public void ctor_Parameters_WhenEd448KeyPair_ExpectCorrectParameters() - { - var keyPair = GenerateEd448KeyPair(); - var expectedPrivateKey = ((Ed448PrivateKeyParameters) keyPair.Private).GetEncoded(); - var expectedPublicKey = ((Ed448PublicKeyParameters) keyPair.Public).GetEncoded(); - - var parameters = new EdDsaParameters(keyPair, ExtendedSecurityAlgorithms.Curves.Ed448); - - parameters.Curve.Should().Be(ExtendedSecurityAlgorithms.Curves.Ed448); - parameters.D.Should().BeEquivalentTo(expectedPrivateKey); - parameters.X.Should().BeEquivalentTo(expectedPublicKey); - } [Fact] public void Validate_WhenBothKeysAreMissing_ExpectCryptographicException() @@ -125,6 +77,13 @@ public void Validate_WhenEd25519PrivateKeyOnly_ExpectValid() parameters.Validate(); } + [Fact] + public void Validate_WhenEd25519SigningKey_ExpectValid() + { + var parameters = new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) {D = new byte[32 * 2], X = null}; + parameters.Validate(); + } + [Fact] public void Validate_WhenEd25519PublicKeyOnly_ExpectValid() { @@ -139,6 +98,13 @@ public void Validate_WhenEd448PrivateKeyOnly_ExpectValid() parameters.Validate(); } + [Fact] + public void Validate_WhenEd448SigningKey_ExpectValid() + { + var parameters = new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed448) {D = new byte[57 * 2], X = null}; + parameters.Validate(); + } + [Fact] public void Validate_WhenEd448PublicKeyOnly_ExpectValid() { @@ -159,18 +125,4 @@ public void Validate_WhenEd448Keys_ExpectValid() var parameters = new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed448) {D = new byte[57], X = new byte[57]}; parameters.Validate(); } - - private static AsymmetricCipherKeyPair GenerateEd25519KeyPair() - { - var keyPairGenerator = new Ed25519KeyPairGenerator(); - keyPairGenerator.Init(new Ed25519KeyGenerationParameters(new SecureRandom())); - return keyPairGenerator.GenerateKeyPair(); - } - - private static AsymmetricCipherKeyPair GenerateEd448KeyPair() - { - var keyPairGenerator = new Ed448KeyPairGenerator(); - keyPairGenerator.Init(new Ed448KeyGenerationParameters(new SecureRandom())); - return keyPairGenerator.GenerateKeyPair(); - } } \ No newline at end of file diff --git a/test/ScottBrady.IdentityModel.Tests/Tokens/EdDSA/EdDsaSecurityKeyTests.cs b/test/ScottBrady.IdentityModel.Tests/Tokens/EdDSA/EdDsaSecurityKeyTests.cs index 49f18de..e08ea05 100644 --- a/test/ScottBrady.IdentityModel.Tests/Tokens/EdDSA/EdDsaSecurityKeyTests.cs +++ b/test/ScottBrady.IdentityModel.Tests/Tokens/EdDSA/EdDsaSecurityKeyTests.cs @@ -16,24 +16,22 @@ public class EdDsaSecurityKeyTests [Fact] public void ctor_WhenKeyParametersAreNull_ExpectArgumentNullException() { -#pragma warning disable CS0618 - Assert.Throws(() => new EdDsaSecurityKey((Ed25519PublicKeyParameters) null)); -#pragma warning restore CS0618 + Assert.Throws(() => new EdDsaSecurityKey(null)); } [Fact] public void ctor_WhenEd25519PrivateKey_ExpectKeySetAndCorrectCurve() { var keyPair = GenerateEd25519KeyPair(); + var privateKeyParameters = (Ed25519PrivateKeyParameters)keyPair.Private; + var edDsa = EdDsa.Create(new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) { D = privateKeyParameters.GetEncoded() }); -#pragma warning disable CS0618 - var securityKey = new EdDsaSecurityKey((Ed25519PrivateKeyParameters) keyPair.Private); -#pragma warning restore CS0618 + var securityKey = new EdDsaSecurityKey(edDsa); securityKey.CryptoProviderFactory.CustomCryptoProvider.Should().BeOfType(); - securityKey.EdDsa.Parameters.D.Should().BeEquivalentTo(((Ed25519PrivateKeyParameters) keyPair.Private).GetEncoded()); - securityKey.EdDsa.Parameters.Curve.Should().Be(ExtendedSecurityAlgorithms.Curves.Ed25519); + securityKey.EdDsa.Should().Be(edDsa); securityKey.PrivateKeyStatus.Should().Be(PrivateKeyStatus.Exists); + securityKey.KeySize.Should().Be(32); #pragma warning disable 618 securityKey.HasPrivateKey.Should().BeTrue(); @@ -44,15 +42,15 @@ public void ctor_WhenEd25519PrivateKey_ExpectKeySetAndCorrectCurve() public void ctor_WhenEd25519PublicKey_ExpectKeySetAndCorrectCurve() { var keyPair = GenerateEd25519KeyPair(); - -#pragma warning disable CS0618 - var securityKey = new EdDsaSecurityKey((Ed25519PublicKeyParameters) keyPair.Public); -#pragma warning restore CS0618 - + var publicKeyParameters = (Ed25519PublicKeyParameters)keyPair.Public; + var edDsa = EdDsa.Create(new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) { X = publicKeyParameters.GetEncoded() }); + + var securityKey = new EdDsaSecurityKey(edDsa); + securityKey.CryptoProviderFactory.CustomCryptoProvider.Should().BeOfType(); - securityKey.EdDsa.Parameters.X.Should().BeEquivalentTo(((Ed25519PublicKeyParameters) keyPair.Public).GetEncoded()); - securityKey.EdDsa.Parameters.Curve.Should().Be(ExtendedSecurityAlgorithms.Curves.Ed25519); + securityKey.EdDsa.Should().Be(edDsa); securityKey.PrivateKeyStatus.Should().Be(PrivateKeyStatus.DoesNotExist); + securityKey.KeySize.Should().Be(32); #pragma warning disable 618 securityKey.HasPrivateKey.Should().BeFalse();