Skip to content

Commit

Permalink
Clean up and new signature provider tests
Browse files Browse the repository at this point in the history
  • Loading branch information
scottbrady91 committed Mar 31, 2024
1 parent 514de35 commit 9c54b20
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 78 deletions.
4 changes: 0 additions & 4 deletions .github/workflows/dotnetcore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ jobs:

steps:
- uses: actions/checkout@v4
- name: Setup .NET 6.0
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Setup .NET 8.0
uses: actions/setup-dotnet@v4
with:
Expand Down
4 changes: 2 additions & 2 deletions src/ScottBrady.IdentityModel/Tokens/EdDsa.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ public new static EdDsa Create(string curve)

public override KeySizes[] LegalKeySizes => Parameters.Curve switch
{
ExtendedSecurityAlgorithms.Curves.Ed25519 => new[] { new KeySizes(32, 32, 0) },
ExtendedSecurityAlgorithms.Curves.Ed448 => new[] { new KeySizes(57, 57, 0) },
ExtendedSecurityAlgorithms.Curves.Ed25519 => [new KeySizes(32, 32, 0)],
ExtendedSecurityAlgorithms.Curves.Ed448 => [new KeySizes(57, 57, 0)],
_ => throw new NotSupportedException()
};

Expand Down
8 changes: 4 additions & 4 deletions src/ScottBrady.IdentityModel/Tokens/EdDsaParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ internal EdDsaParameters(AsymmetricCipherKeyPair keyPair, string curve) : this(c
}
}

public byte[] D { get; set; }
public byte[] X { get; set; }
public byte[] D { get; init; }
public byte[] X { get; init; }
public string Curve { get; }

public void Validate()
Expand All @@ -45,8 +45,8 @@ public void Validate()

if (D != null)
{
if (Curve == ExtendedSecurityAlgorithms.Curves.Ed25519 && (D.Length != 32 && D.Length != 32*2)) throw new CryptographicException("Invalid key length. Must be 32 bytes.");
if (Curve == ExtendedSecurityAlgorithms.Curves.Ed448 && (D.Length != 57 && D.Length != 57*2)) throw new CryptographicException("Invalid key length. Must be 57 bytes.");
if (Curve == ExtendedSecurityAlgorithms.Curves.Ed25519 && D.Length != 32 && D.Length != 32*2) throw new CryptographicException("Invalid key length. Must be 32 bytes.");
if (Curve == ExtendedSecurityAlgorithms.Curves.Ed448 && D.Length != 57 && D.Length != 57*2) throw new CryptographicException("Invalid key length. Must be 57 bytes.");
}

if (X != null)
Expand Down
9 changes: 4 additions & 5 deletions src/ScottBrady.IdentityModel/Tokens/EdDsaSignatureProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ public EdDsaSignatureProvider(EdDsaSecurityKey key, string algorithm)
: base(key, algorithm)
{
edDsaKey = key;
WillCreateSignatures = key.PrivateKeyStatus == PrivateKeyStatus.Exists;
}

protected override void Dispose(bool disposing) { }
public override byte[] Sign(byte[] input) => edDsaKey.EdDsa.Sign(input);

public override bool Verify(byte[] input, byte[] signature) => edDsaKey.EdDsa.Verify(input, signature);
public override bool Verify(byte[] input, int inputOffset, int inputLength, byte[] signature, int signatureOffset, int signatureLength) => edDsaKey.EdDsa.Verify(input, inputOffset, inputLength, signature, signatureOffset, signatureLength);

public override bool Sign(ReadOnlySpan<byte> data, Span<byte> destination, out int bytesWritten)
{
var signature = edDsaKey.EdDsa.Sign(data.ToArray());
Expand All @@ -30,8 +33,4 @@ public override byte[] Sign(byte[] input, int offset, int count)
Buffer.BlockCopy(input, offset, data, 0, count);
return edDsaKey.EdDsa.Sign(data);
}

public override bool Verify(byte[] input, byte[] signature) => edDsaKey.EdDsa.Verify(input, signature);
public override bool Verify(byte[] input, int inputOffset, int inputLength, byte[] signature, int signatureOffset, int signatureLength)
=> edDsaKey.EdDsa.Verify(input, inputOffset, inputLength, signature, signatureOffset, signatureLength);
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Text;
using FluentAssertions;
using Microsoft.IdentityModel.Tokens;
Expand All @@ -9,83 +10,100 @@ namespace ScottBrady.IdentityModel.Tests.Tokens.EdDSA;

public class EdDsaSignatureProviderTests
{
// privateKey = "FU1F1QTjYwfB-xkO6aknnBifE_Ywa94U04xpd-XJfBs"

private readonly byte[] privateKey = Base64UrlEncoder.DecodeBytes("FU1F1QTjYwfB-xkO6aknnBifE_Ywa94U04xpd-XJfBs");
private readonly byte[] publicKey = Base64UrlEncoder.DecodeBytes("60mR98SQlHUSeLeIu7TeJBTLRG10qlcDLU4AJjQdqMQ");
private readonly byte[] plaintext = Encoding.UTF8.GetBytes("eyJraWQiOiIxMjMiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJhdWQiOiJ5b3UiLCJzdWIiOiJib2IiLCJpc3MiOiJtZSIsImV4cCI6MTU5MDg0MTg4N30");
private readonly byte[] validSignature = Base64UrlEncoder.DecodeBytes("OyBxBr344Ny-0vRCeEMLSnuEO1IecybvJBivrjum4d-dgN5WLnEAGAO43MlZeRGn1F3fRXO_xlYot68PtDuiAA");

[Fact]
public void ctor_ExpectPropertiesSet()
public void ctor_WithPrivateKey_ExpectPropertiesSet()
{
var expectedSecurityKey = new EdDsaSecurityKey(EdDsa.Create(ExtendedSecurityAlgorithms.Curves.Ed25519));
var expectedAlgorithm = ExtendedSecurityAlgorithms.EdDsa;
var securityKey = new EdDsaSecurityKey(EdDsa.Create(new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) { D = privateKey }));
var algorithm = ExtendedSecurityAlgorithms.EdDsa;

var provider = new EdDsaSignatureProvider(securityKey, algorithm);

var provider = new EdDsaSignatureProvider(expectedSecurityKey, expectedAlgorithm);
provider.Key.Should().Be(securityKey);
provider.Algorithm.Should().Be(algorithm);
provider.WillCreateSignatures.Should().BeTrue();
}
[Fact]
public void ctor_WithPublicKey_ExpectPropertiesSet()
{
var securityKey = new EdDsaSecurityKey(EdDsa.Create(new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) { X = publicKey }));
var algorithm = ExtendedSecurityAlgorithms.EdDsa;

provider.Key.Should().Be(expectedSecurityKey);
provider.Algorithm.Should().Be(expectedAlgorithm);
}
var provider = new EdDsaSignatureProvider(securityKey, algorithm);

provider.Key.Should().Be(securityKey);
provider.Algorithm.Should().Be(algorithm);
provider.WillCreateSignatures.Should().BeFalse();
}

[Fact]
public void Dispose_ExpectNoException()
{
new EdDsaSignatureProvider(new EdDsaSecurityKey(EdDsa.Create(ExtendedSecurityAlgorithms.Curves.Ed25519)), ExtendedSecurityAlgorithms.EdDsa).Dispose();
}

[Fact]
public void Sign_WhenSigningWithEd25519Curve_ExpectCorrectSignature()
{
const string plaintext =
"eyJraWQiOiIxMjMiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJhdWQiOiJ5b3UiLCJzdWIiOiJib2IiLCJpc3MiOiJtZSIsImV4cCI6MTU5MDg0MTg4N30";
const string expectedSignature =
"OyBxBr344Ny-0vRCeEMLSnuEO1IecybvJBivrjum4d-dgN5WLnEAGAO43MlZeRGn1F3fRXO_xlYot68PtDuiAA";

const string privateKey = "FU1F1QTjYwfB-xkO6aknnBifE_Ywa94U04xpd-XJfBs";
var edDsaSecurityKey = new EdDsaSecurityKey(EdDsa.Create(
new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) {D = Base64UrlEncoder.DecodeBytes(privateKey)}));

var signatureProvider = new EdDsaSignatureProvider(edDsaSecurityKey, ExtendedSecurityAlgorithms.EdDsa);

var signature = signatureProvider.Sign(Encoding.UTF8.GetBytes(plaintext));

signature.Should().BeEquivalentTo(Base64UrlEncoder.DecodeBytes(expectedSignature));
}
var edDsaSecurityKey = new EdDsaSecurityKey(EdDsa.Create(new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) { D = privateKey }));
var signatureProvider = new EdDsaSignatureProvider(edDsaSecurityKey, ExtendedSecurityAlgorithms.EdDsa);

var signature = signatureProvider.Sign(plaintext);

signature.Should().BeEquivalentTo(validSignature);
}

[Fact]
public void Verify_WhenJwtSignedWithEd25519Curve_ExpectTrue()
{
const string plaintext =
"eyJraWQiOiIxMjMiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJhdWQiOiJ5b3UiLCJzdWIiOiJib2IiLCJpc3MiOiJtZSIsImV4cCI6MTU5MDg0MTg4N30";
const string signature =
"OyBxBr344Ny-0vRCeEMLSnuEO1IecybvJBivrjum4d-dgN5WLnEAGAO43MlZeRGn1F3fRXO_xlYot68PtDuiAA";

const string publicKey = "60mR98SQlHUSeLeIu7TeJBTLRG10qlcDLU4AJjQdqMQ";
var edDsaSecurityKey = new EdDsaSecurityKey(EdDsa.Create(
new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) {X = Base64UrlEncoder.DecodeBytes(publicKey)}));

var signatureProvider = new EdDsaSignatureProvider(edDsaSecurityKey, ExtendedSecurityAlgorithms.EdDsa);

var isValidSignature = signatureProvider.Verify(
Encoding.UTF8.GetBytes(plaintext),
Base64UrlEncoder.DecodeBytes(signature));

isValidSignature.Should().BeTrue();
}
var edDsaSecurityKey = new EdDsaSecurityKey(EdDsa.Create(new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) { X = publicKey }));
var signatureProvider = new EdDsaSignatureProvider(edDsaSecurityKey, ExtendedSecurityAlgorithms.EdDsa);

var isValidSignature = signatureProvider.Verify(plaintext, validSignature);

isValidSignature.Should().BeTrue();
}

[Fact]
public void VerifyWithOffsets_WhenJwtSignedWithEd25519Curve_ExpectTrue()
public void Verify_WithOffsets_WhenJwtSignedWithEd25519Curve_ExpectTrue()
{
const string plaintext =
"eyJraWQiOiIxMjMiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJhdWQiOiJ5b3UiLCJzdWIiOiJib2IiLCJpc3MiOiJtZSIsImV4cCI6MTU5MDg0MTg4N30";
const string signature =
"OyBxBr344Ny-0vRCeEMLSnuEO1IecybvJBivrjum4d-dgN5WLnEAGAO43MlZeRGn1F3fRXO_xlYot68PtDuiAA";

const string publicKey = "60mR98SQlHUSeLeIu7TeJBTLRG10qlcDLU4AJjQdqMQ";
var edDsaSecurityKey = new EdDsaSecurityKey(EdDsa.Create(
new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) {X = Base64UrlEncoder.DecodeBytes(publicKey)}));

var signatureProvider = new EdDsaSignatureProvider(edDsaSecurityKey, ExtendedSecurityAlgorithms.EdDsa);

var inputBytes = Encoding.UTF8.GetBytes(plaintext);
var signatureBytes = Base64UrlEncoder.DecodeBytes(signature);

var isValidSignature = signatureProvider.Verify(
inputBytes,
0, inputBytes.Length,
signatureBytes, 0,signatureBytes.Length);

isValidSignature.Should().BeTrue();
}
var edDsaSecurityKey = new EdDsaSecurityKey(EdDsa.Create(new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) { X = publicKey }));
var signatureProvider = new EdDsaSignatureProvider(edDsaSecurityKey, ExtendedSecurityAlgorithms.EdDsa);

var isValidSignature = signatureProvider.Verify(plaintext, 0, plaintext.Length, validSignature, 0, validSignature.Length);

isValidSignature.Should().BeTrue();
}

[Fact]
public void Sign_WithSpan_WhenSigningWithEd25519Curve_ExpectCorrectSignature()
{
var edDsaSecurityKey = new EdDsaSecurityKey(EdDsa.Create(new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) { D = privateKey }));
var signatureProvider = new EdDsaSignatureProvider(edDsaSecurityKey, ExtendedSecurityAlgorithms.EdDsa);

Span<byte> signature = stackalloc byte[64];
var isSuccess = signatureProvider.Sign(plaintext.AsSpan(), signature, out var bytesWritten);

isSuccess.Should().BeTrue();
signature.ToArray().Should().BeEquivalentTo(validSignature);
bytesWritten.Should().Be(64);
}

[Fact]
public void Sign_WithOffset_WhenSigningWithEd25519Curve_ExpectCorrectSignature()
{
var edDsaSecurityKey = new EdDsaSecurityKey(EdDsa.Create(new EdDsaParameters(ExtendedSecurityAlgorithms.Curves.Ed25519) { D = privateKey }));
var signatureProvider = new EdDsaSignatureProvider(edDsaSecurityKey, ExtendedSecurityAlgorithms.EdDsa);

var input = new byte[plaintext.Length + 1];
Buffer.BlockCopy(plaintext, 0, input, 1, plaintext.Length);

var signature = signatureProvider.Sign(input, 1, plaintext.Length);

signature.Should().BeEquivalentTo(validSignature);
}
}

0 comments on commit 9c54b20

Please sign in to comment.