diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 00000000..f07919ea
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,195 @@
+name: master
+
+on:
+ workflow_dispatch:
+ inputs:
+ force_version:
+ description: "The version to use"
+ required: true
+ default: "0.0.0-test"
+ type: string
+ push:
+ branches:
+ - master
+ pull_request:
+ branches:
+ - master
+ release:
+ types:
+ - published
+
+env:
+ # Setting these variables allows .NET CLI to use rich color codes in console output
+ TERM: xterm
+ DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION: true
+ # Skip boilerplate output
+ DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
+ DOTNET_NOLOGO: true
+ DOTNET_CLI_TELEMETRY_OPTOUT: true
+
+jobs:
+ # Determine version
+ version:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+
+ steps:
+ - name: Determine stable version
+ id: stable-version
+ if: ${{ github.event_name == 'release' }}
+ run: |
+ if ! [[ "${{ github.event.release.tag_name }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z].*)?$ ]]; then
+ echo "Invalid version: ${{ github.event.release.tag_name }}"
+ exit 1
+ fi
+
+ echo "version=${{ github.event.release.tag_name }}" >> $GITHUB_OUTPUT
+
+ - name: Determine prerelease version
+ id: pre-version
+ if: ${{ github.event_name != 'release' }}
+ run: |
+ hash="${{ github.event.pull_request.head.sha || github.sha }}"
+ echo "version=0.0.0-ci-${hash:0:7}" >> $GITHUB_OUTPUT
+
+ outputs:
+ version: ${{ github.event.inputs.force_version || steps.stable-version.outputs.version || steps.pre-version.outputs.version }}
+
+ # Check formatting
+# format:
+# runs-on: ubuntu-latest
+# permissions:
+# contents: read
+
+# steps:
+# - name: Checkout
+# uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
+
+# - name: Install .NET
+# uses: actions/setup-dotnet@607fce577a46308457984d59e4954e075820f10a # v3.0.3
+
+# - name: Validate format
+# run: dotnet format --verify-no-changes
+
+ # Run tests
+ test:
+ strategy:
+ fail-fast: false
+ matrix:
+ os:
+ - ubuntu-latest
+ # Windows runners don't support Linux Docker containers (needed for tests),
+ # so we currently cannot run tests on Windows.
+ # - windows-latest
+
+ runs-on: ${{ matrix.os }}
+ permissions:
+ contents: read
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
+
+ - name: Install .NET
+ uses: actions/setup-dotnet@607fce577a46308457984d59e4954e075820f10a # v3.0.3
+
+ - name: Run restore
+ run: dotnet restore
+
+ - name: Run build
+ run: >
+ dotnet build
+ --no-restore
+ --configuration Release
+
+ - name: Run tests
+ run: >
+ dotnet test
+ --no-restore
+ --no-build
+ --configuration Release
+ ${{ runner.os == 'Windows' && '-p:IncludeNetCoreAppTargets=false' || '' }}
+ --logger "trx;LogFileName=pw-test-results.trx"
+ --
+ RunConfiguration.CollectSourceInformation=true
+
+ # Pack the output into NuGet packages
+ pack:
+ needs: version
+ runs-on: ubuntu-latest
+ permissions:
+ actions: write
+ contents: read
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
+
+ - name: Install .NET
+ uses: actions/setup-dotnet@607fce577a46308457984d59e4954e075820f10a # v3.0.3
+
+ - name: Run restore
+ run: dotnet restore
+
+ - name: Run build
+ run: >
+ dotnet build
+ --no-restore
+ --configuration Release
+ -p:ContinuousIntegrationBuild=true
+ -p:Version=${{ needs.version.outputs.version }}
+
+ - name: Run pack
+ run: >
+ dotnet pack
+ -p:Version=${{ needs.version.outputs.version }}
+ -p:ContinuousIntegrationBuild=true
+ --no-restore
+ --no-build
+ --configuration Release
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ with:
+ name: packages
+ path: "**/*.nupkg"
+
+ # Deploy the NuGet packages to the corresponding registries
+ deploy:
+ needs:
+ # Technically, it's not required for the format job to succeed for us to push the package,
+ # so we may consider removing it as a prerequisite here.
+ # - format
+ - test
+ - pack
+
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ packages: write
+
+ steps:
+ - name: Download artifacts
+ uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
+ with:
+ name: packages
+
+ - name: Install .NET
+ uses: actions/setup-dotnet@607fce577a46308457984d59e4954e075820f10a # v3.0.3
+
+ # Publish to GitHub package registry every time, whether it's a prerelease
+ # version or a stable release version.
+ - name: Publish packages (GitHub Registry)
+ run: >
+ dotnet nuget push **/*.nupkg
+ --source https://nuget.pkg.github.com/passwordless-lib/index.json
+ --api-key ${{ secrets.GITHUB_TOKEN }}
+
+ # Only publish to NuGet on stable releases
+ # - name: Publish packages (NuGet Registry)
+ # if: ${{ github.event_name == 'release' }}
+ # run: >
+ # dotnet nuget push **/*.nupkg
+ # --source https://api.nuget.org/v3/index.json
+ # --api-key ${{ secrets.nuget_api_key }}
\ No newline at end of file
diff --git a/Src/Directory.Build.props b/Src/Directory.Build.props
index 94c54bc0..00c23c19 100644
--- a/Src/Directory.Build.props
+++ b/Src/Directory.Build.props
@@ -14,6 +14,6 @@
true
- true
+ false
\ No newline at end of file
diff --git a/Src/Fido2.Models/AssertionOptions.cs b/Src/Fido2.Models/AssertionOptions.cs
index cb6e5c5e..03a22b06 100644
--- a/Src/Fido2.Models/AssertionOptions.cs
+++ b/Src/Fido2.Models/AssertionOptions.cs
@@ -24,7 +24,7 @@ public class AssertionOptions : Fido2ResponseBase
/// This member specifies a time, in milliseconds, that the caller is willing to wait for the call to complete. This is treated as a hint, and MAY be overridden by the client.
///
[JsonPropertyName("timeout")]
- public uint Timeout { get; set; }
+ public ulong Timeout { get; set; }
///
/// This OPTIONAL member specifies the relying party identifier claimed by the caller.If omitted, its value will be the CredentialsContainer object’s relevant settings object's origin's effective domain
diff --git a/Src/Fido2.Models/CredentialCreateOptions.cs b/Src/Fido2.Models/CredentialCreateOptions.cs
index 1625486c..f899a88f 100644
--- a/Src/Fido2.Models/CredentialCreateOptions.cs
+++ b/Src/Fido2.Models/CredentialCreateOptions.cs
@@ -43,14 +43,14 @@ public sealed class CredentialCreateOptions : Fido2ResponseBase
/// This member specifies a time, in milliseconds, that the caller is willing to wait for the call to complete. This is treated as a hint, and MAY be overridden by the platform.
///
[JsonPropertyName("timeout")]
- public long Timeout { get; set; }
+ public ulong Timeout { get; set; }
///
/// This member is intended for use by Relying Parties that wish to express their preference for attestation conveyance.The default is none.
///
[JsonPropertyName("attestation")]
- public AttestationConveyancePreference Attestation { get; set; } = AttestationConveyancePreference.None;
-
+ public AttestationConveyancePreference Attestation { get; set; } = AttestationConveyancePreference.None;
+
///
/// This member is intended for use by Relying Parties that wish to select the appropriate authenticators to participate in the create() operation.
///
@@ -225,7 +225,7 @@ public ResidentKeyRequirement ResidentKey
///
[Obsolete("Use property ResidentKey.")]
[JsonPropertyName("requireResidentKey")]
- public bool RequireResidentKey
+ public bool RequireResidentKey
{
get => _requireResidentKey;
set
diff --git a/Src/Fido2/Fido2.cs b/Src/Fido2/Fido2.cs
index 44f08f65..abb5891e 100644
--- a/Src/Fido2/Fido2.cs
+++ b/Src/Fido2/Fido2.cs
@@ -58,18 +58,18 @@ public CredentialCreateOptions RequestNewCredential(
/// Verifies the response from the browser/authenticator after creating new credentials.
///
/// The attestation response from the authenticator.
- /// The original options that was sent to the client.
+ /// The original options that was sent to the client.
/// The delegate used to validate that the CredentialID is unique to this user.
/// The used to propagate notifications that the operation should be canceled.
///
public async Task MakeNewCredentialAsync(
AuthenticatorAttestationRawResponse attestationResponse,
- CredentialCreateOptions origChallenge,
+ CredentialCreateOptions originalOptions,
IsCredentialIdUniqueToUserAsyncDelegate isCredentialIdUniqueToUser,
CancellationToken cancellationToken = default)
{
var parsedResponse = AuthenticatorAttestationResponse.Parse(attestationResponse);
- var success = await parsedResponse.VerifyAsync(origChallenge, _config, isCredentialIdUniqueToUser, _metadataService, cancellationToken);
+ var success = await parsedResponse.VerifyAsync(originalOptions, _config, isCredentialIdUniqueToUser, _metadataService, cancellationToken);
// todo: Set Errormessage etc.
return new MakeNewCredentialResult(
diff --git a/Src/Fido2/IFido2.cs b/Src/Fido2/IFido2.cs
index 585dc12a..5dcfd463 100644
--- a/Src/Fido2/IFido2.cs
+++ b/Src/Fido2/IFido2.cs
@@ -9,8 +9,8 @@ namespace Fido2NetLib;
public interface IFido2
{
AssertionOptions GetAssertionOptions(
- IEnumerable allowedCredentials,
- UserVerificationRequirement? userVerification,
+ IEnumerable allowedCredentials,
+ UserVerificationRequirement? userVerification,
AuthenticationExtensionsClientInputs? extensions = null);
Task MakeAssertionAsync(
@@ -24,7 +24,7 @@ Task MakeAssertionAsync(
Task MakeNewCredentialAsync(
AuthenticatorAttestationRawResponse attestationResponse,
- CredentialCreateOptions origChallenge,
+ CredentialCreateOptions originalOptions,
IsCredentialIdUniqueToUserAsyncDelegate isCredentialIdUniqueToUser,
CancellationToken cancellationToken = default);
diff --git a/Test/Attestation/Apple.cs b/Test/Attestation/Apple.cs
index 97c93517..236ae77a 100644
--- a/Test/Attestation/Apple.cs
+++ b/Test/Attestation/Apple.cs
@@ -233,7 +233,7 @@ public async Task TestApplePublicKeyMismatch()
}
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -271,7 +271,7 @@ public async Task TestApplePublicKeyMismatch()
Origins = new HashSet { "https://www.passwordless.dev" },
});
- var credentialMakeResult = await lib.MakeNewCredentialAsync(attestationResponse, origChallenge, callback);
+ var credentialMakeResult = await lib.MakeNewCredentialAsync(attestationResponse, originalOptions, callback);
}
private string[] StackAllocSha256(byte[] authData, byte[] clientDataJson)
diff --git a/Test/AuthenticatorResponse.cs b/Test/AuthenticatorResponse.cs
index f240de78..cbaea684 100644
--- a/Test/AuthenticatorResponse.cs
+++ b/Test/AuthenticatorResponse.cs
@@ -87,7 +87,7 @@ public async Task TestAuthenticatorOriginsAsync(string origin, string expectedOr
},
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -125,7 +125,7 @@ public async Task TestAuthenticatorOriginsAsync(string origin, string expectedOr
Origins = new HashSet { expectedOrigin },
});
- var result = await lib.MakeNewCredentialAsync(rawResponse, origChallenge, callback);
+ var result = await lib.MakeNewCredentialAsync(rawResponse, originalOptions, callback);
}
[Theory]
@@ -190,7 +190,7 @@ public async Task TestAuthenticatorOriginsFail(string origin, string expectedOri
},
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -228,7 +228,7 @@ public async Task TestAuthenticatorOriginsFail(string origin, string expectedOri
Origins = new HashSet { expectedOrigin },
});
- var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, origChallenge, callback));
+ var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, originalOptions, callback));
Assert.StartsWith("Fully qualified origin", ex.Message);
}
@@ -401,7 +401,7 @@ public async Task TestAuthenticatorAttestationResponseInvalidType()
},
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -439,7 +439,7 @@ public async Task TestAuthenticatorAttestationResponseInvalidType()
Origins = new HashSet { rp },
});
- var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, origChallenge, callback));
+ var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, originalOptions, callback));
Assert.Same(Fido2ErrorMessages.AttestationResponseTypeNotWebAuthnGet, ex.Message);
}
@@ -473,7 +473,7 @@ public async Task TestAuthenticatorAttestationResponseInvalidRawId(byte[] value)
},
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -511,7 +511,7 @@ public async Task TestAuthenticatorAttestationResponseInvalidRawId(byte[] value)
Origins = new HashSet { rp },
});
- var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, origChallenge, callback));
+ var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, originalOptions, callback));
Assert.Same(Fido2ErrorMessages.AttestationResponseIdMissing, ex.Message);
}
@@ -543,7 +543,7 @@ public async Task TestAuthenticatorAttestationResponseInvalidRawType()
},
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -581,7 +581,7 @@ public async Task TestAuthenticatorAttestationResponseInvalidRawType()
Origins = new HashSet { rp },
});
- var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, origChallenge, callback));
+ var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, originalOptions, callback));
Assert.Equal("AttestationResponse type must be 'public-key'", ex.Message);
}
@@ -620,7 +620,7 @@ public async Task TestAuthenticatorAttestationResponseRpidMismatch()
},
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -658,7 +658,7 @@ public async Task TestAuthenticatorAttestationResponseRpidMismatch()
Origins = new HashSet { rp },
});
- var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, origChallenge, callback));
+ var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, originalOptions, callback));
Assert.Equal(Fido2ErrorCode.InvalidRpidHash, ex.Code);
Assert.Equal(Fido2ErrorMessages.InvalidRpidHash, ex.Message);
}
@@ -699,7 +699,7 @@ public async Task TestAuthenticatorAttestationResponseNotUserPresentAsync()
},
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -737,7 +737,7 @@ public async Task TestAuthenticatorAttestationResponseNotUserPresentAsync()
Origins = new HashSet { rp },
});
- var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, origChallenge, callback));
+ var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, originalOptions, callback));
Assert.Equal(Fido2ErrorCode.UserPresentFlagNotSet, ex.Code);
Assert.Equal(Fido2ErrorMessages.UserPresentFlagNotSet, ex.Message);
@@ -778,7 +778,7 @@ public async Task TestAuthenticatorAttestationResponseBackupEligiblePolicyRequir
},
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -817,7 +817,7 @@ public async Task TestAuthenticatorAttestationResponseBackupEligiblePolicyRequir
BackupEligibleCredentialPolicy = Fido2Configuration.CredentialBackupPolicy.Required,
});
- var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, origChallenge, callback));
+ var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, originalOptions, callback));
Assert.Equal(Fido2ErrorMessages.BackupEligibilityRequirementNotMet, ex.Message);
}
@@ -856,7 +856,7 @@ public async Task TestAuthenticatorAttestationResponseBackupEligiblePolicyDisall
},
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -895,7 +895,7 @@ public async Task TestAuthenticatorAttestationResponseBackupEligiblePolicyDisall
BackupEligibleCredentialPolicy = Fido2Configuration.CredentialBackupPolicy.Disallowed,
});
- var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, origChallenge, callback));
+ var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, originalOptions, callback));
Assert.Equal(Fido2ErrorMessages.BackupEligibilityRequirementNotMet, ex.Message);
}
@@ -934,7 +934,7 @@ public async Task TestAuthenticatorAttestationResponseNoAttestedCredentialData()
},
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -972,7 +972,7 @@ public async Task TestAuthenticatorAttestationResponseNoAttestedCredentialData()
Origins = new HashSet { rp },
});
- var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, origChallenge, callback));
+ var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, originalOptions, callback));
Assert.Equal("Attestation flag not set on attestation data", ex.Message);
}
@@ -1012,7 +1012,7 @@ public async Task TestAuthenticatorAttestationResponseUnknownAttestationType()
},
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -1050,7 +1050,7 @@ public async Task TestAuthenticatorAttestationResponseUnknownAttestationType()
Origins = new HashSet { rp },
});
- var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, origChallenge, callback));
+ var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, originalOptions, callback));
Assert.Equal("Unknown attestation type. Was 'testing'", ex.Message);
Assert.Equal(Fido2ErrorCode.UnknownAttestationType, ex.Code);
}
@@ -1090,7 +1090,7 @@ public async Task TestAuthenticatorAttestationResponseNotUniqueCredId()
},
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -1128,7 +1128,7 @@ public async Task TestAuthenticatorAttestationResponseNotUniqueCredId()
Origins = new HashSet { rp },
});
- var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, origChallenge, callback));
+ var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, originalOptions, callback));
Assert.Equal("CredentialId is not unique to this user", ex.Message);
}
@@ -1167,7 +1167,7 @@ public async Task TestAuthenticatorAttestationResponseUVRequired()
},
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -1205,7 +1205,7 @@ public async Task TestAuthenticatorAttestationResponseUVRequired()
Origins = new HashSet { rp },
});
- var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, origChallenge, callback));
+ var ex = await Assert.ThrowsAsync(() => lib.MakeNewCredentialAsync(rawResponse, originalOptions, callback));
Assert.Equal("User Verified flag not set in authenticator data and user verification was required", ex.Message);
}
diff --git a/Test/Fido2Tests.cs b/Test/Fido2Tests.cs
index 756d6c89..1d7d144f 100644
--- a/Test/Fido2Tests.cs
+++ b/Test/Fido2Tests.cs
@@ -74,8 +74,8 @@ static Fido2Tests()
new (COSE.KeyType.OKP, COSE.Algorithm.EdDSA, COSE.EllipticCurve.Ed25519),
new (COSE.KeyType.EC2, COSE.Algorithm.ES256K, COSE.EllipticCurve.P256K)
};
- }
-
+ }
+
private async Task GetAsync(string filename)
{
return JsonSerializer.Deserialize(await File.ReadAllTextAsync(filename));
@@ -117,7 +117,7 @@ public byte[] _clientDataJson
public byte[] _attToBeSignedHash(HashAlgorithmName alg)
{
- return CryptoUtils.HashData(alg, _attToBeSigned);
+ return CryptoUtils.HashData(alg, _attToBeSigned);
}
public byte[] _credentialID;
@@ -125,15 +125,15 @@ public byte[] _attToBeSignedHash(HashAlgorithmName alg)
public ushort _signCount;
protected Guid _aaguid = new("F1D0F1D0-F1D0-F1D0-F1D0-F1D0F1D0F1D0");
public Extensions GetExtensions()
- {
+ {
var extBytes = new CborMap { { "testing", true } }.Encode();
- return new Extensions(extBytes);
+ return new Extensions(extBytes);
}
- public AuthenticatorData _authData => new(_rpIdHash, _flags, _signCount, _acd, GetExtensions());
-
- public AttestedCredentialData _acd => new(_aaguid, _credentialID, _credentialPublicKey);
-
+ public AuthenticatorData _authData => new(_rpIdHash, _flags, _signCount, _acd, GetExtensions());
+
+ public AttestedCredentialData _acd => new(_aaguid, _credentialID, _credentialPublicKey);
+
public Attestation()
{
_credentialID = RandomNumberGenerator.GetBytes(16);
@@ -179,7 +179,7 @@ public async Task MakeAttestationResponseAsync()
}
};
- var origChallenge = new CredentialCreateOptions
+ var originalOptions = new CredentialCreateOptions
{
Attestation = AttestationConveyancePreference.Direct,
AuthenticatorSelection = new AuthenticatorSelection
@@ -226,9 +226,9 @@ public async Task MakeAttestationResponseAsync()
ServerDomain = rp,
ServerName = rp,
Origins = new HashSet { rp },
- });
-
- var credentialMakeResult = await lib.MakeNewCredentialAsync(attestationResponse, origChallenge, callback);
+ });
+
+ var credentialMakeResult = await lib.MakeNewCredentialAsync(attestationResponse, originalOptions, callback);
return credentialMakeResult;
}
@@ -353,8 +353,8 @@ internal static byte[] SignData(COSE.KeyType kty, COSE.Algorithm alg, byte[] dat
default:
throw new ArgumentOutOfRangeException(nameof(kty), $"Missing or unknown kty {kty}");
}
- }
-
+ }
+
[Fact]
public void TestStringIsSerializable()
{
@@ -387,11 +387,11 @@ public void TestStringIsSerializable()
Assert.Equal(AuthenticatorAttachment.CrossPlatform, y2);
// test list of typed strings
- var z1 = new[] {
- AuthenticatorTransport.Ble,
- AuthenticatorTransport.Usb,
+ var z1 = new[] {
+ AuthenticatorTransport.Ble,
+ AuthenticatorTransport.Usb,
AuthenticatorTransport.Nfc,
- AuthenticatorTransport.Internal
+ AuthenticatorTransport.Internal
};
var zjson = JsonSerializer.Serialize(z1);
@@ -464,9 +464,9 @@ public void TestAppleAppAttestProd()
var clientDataJson = SHA256.HashData(Encoding.UTF8.GetBytes("1234567890abcdefgh"));
var verifier = new AppleAppAttest();
- var ex = Assert.Throws(() =>
- {
- (AttestationType attType, X509Certificate[] trustPath) = verifier.Verify(AttestationObject.AttStmt, AttestationObject.AuthData, clientDataJson);
+ var ex = Assert.Throws(() =>
+ {
+ (AttestationType attType, X509Certificate[] trustPath) = verifier.Verify(AttestationObject.AttStmt, AttestationObject.AuthData, clientDataJson);
});
const string windowsErrorMessage = "Failed to build chain in Apple AppAttest attestation: A required certificate is not within its validity period when verifying against the current system clock or the timestamp in the signed file.";
@@ -822,8 +822,8 @@ public async Task TestAssertionResponse()
Assert.Equal(new byte[] { 0xf1, 0xd0 }, avr.CredentialId);
Assert.Equal("1", avr.SignCount.ToString("X"));
}
- }
-
+ }
+
internal static async Task MakeAssertionResponseAsync(
COSE.KeyType kty,
COSE.Algorithm alg,
@@ -846,16 +846,16 @@ internal static async Task MakeAssertionResponseAsync(
{
case COSE.KeyType.EC2:
{
- ecdsa ??= MakeECDsa(alg, crv);
-
+ ecdsa ??= MakeECDsa(alg, crv);
+
var ecParams = ecdsa.ExportParameters(true);
cpk = MakeCredentialPublicKey(kty, alg, crv, ecParams.Q.X, ecParams.Q.Y);
break;
}
case COSE.KeyType.RSA:
{
- rsa ??= RSA.Create();
-
+ rsa ??= RSA.Create();
+
var rsaParams = rsa.ExportParameters(true);
cpk = MakeCredentialPublicKey(kty, alg, rsaParams.Modulus, rsaParams.Exponent);
break;
@@ -894,7 +894,7 @@ internal static async Task MakeAssertionResponseAsync(
var clientDataJson = JsonSerializer.SerializeToUtf8Bytes(clientData);
var hashedClientDataJson = SHA256.HashData(clientDataJson);
- byte[] data = DataHelper.Concat(authData, hashedClientDataJson);
+ byte[] data = DataHelper.Concat(authData, hashedClientDataJson);
byte[] signature = SignData(kty, alg, data, ecdsa, rsa, expandedPrivateKey);
var userHandle = new byte[16];
@@ -935,12 +935,12 @@ internal static async Task MakeAssertionResponseAsync(
}
internal static void MakeEdDSA(out byte[] privateKeySeed, out byte[] publicKey, out byte[] expandedPrivateKey)
- {
+ {
privateKeySeed = new byte[32];
RandomNumberGenerator.Fill(privateKeySeed);
var key = Key.Create(SignatureAlgorithm.Ed25519, new KeyCreationParameters() { ExportPolicy = KeyExportPolicies.AllowPlaintextExport });
expandedPrivateKey = key.Export(KeyBlobFormat.RawPrivateKey);
- publicKey = key.Export(KeyBlobFormat.RawPublicKey);
+ publicKey = key.Export(KeyBlobFormat.RawPublicKey);
}
internal static ECDsa MakeECDsa(COSE.Algorithm alg, COSE.EllipticCurve crv)