diff --git a/Src/Fido2.AspNet/DistributedCacheMetadataService.cs b/Src/Fido2.AspNet/DistributedCacheMetadataService.cs index 2f6c6587..f2072014 100644 --- a/Src/Fido2.AspNet/DistributedCacheMetadataService.cs +++ b/Src/Fido2.AspNet/DistributedCacheMetadataService.cs @@ -29,9 +29,7 @@ public DistributedCacheMetadataService( ILogger logger, ISystemClock systemClock) { - - if (repositories == null) - throw new ArgumentNullException(nameof(repositories)); + ArgumentNullException.ThrowIfNull(repositories); _repositories = repositories.ToList(); _distributedCache = distributedCache; diff --git a/Src/Fido2.Models/AssertionOptions.cs b/Src/Fido2.Models/AssertionOptions.cs index f273ed0f..536f6b93 100644 --- a/Src/Fido2.Models/AssertionOptions.cs +++ b/Src/Fido2.Models/AssertionOptions.cs @@ -12,23 +12,28 @@ namespace Fido2NetLib; public class AssertionOptions : Fido2ResponseBase { /// - /// This member represents a challenge that the selected authenticator signs, along with other data, when producing an authentication assertion.See the §13.1 Cryptographic Challenges security consideration. + /// This member represents a challenge that the selected authenticator signs, along with other data, when producing an authentication assertion. + /// See the §13.1 Cryptographic Challenges security consideration. /// [JsonPropertyName("challenge")] [JsonConverter(typeof(Base64UrlConverter))] public byte[] Challenge { get; set; } +#nullable enable + /// - /// 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. + /// 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 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 + /// 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 /// [JsonPropertyName("rpId")] - public string RpId { get; set; } + public string? RpId { get; set; } /// /// This OPTIONAL member contains a list of PublicKeyCredentialDescriptor objects representing public key credentials acceptable to the caller, in descending order of the caller’s preference(the first item in the list is the most preferred credential, and so on down the list) @@ -37,24 +42,26 @@ public class AssertionOptions : Fido2ResponseBase public IReadOnlyList AllowCredentials { get; set; } = Array.Empty(); /// - /// This member describes the Relying Party's requirements regarding user verification for the get() operation. Eligible authenticators are filtered to only those capable of satisfying this requirement + /// This member describes the Relying Party's requirements regarding user verification for the get() operation. + /// Eligible authenticators are filtered to only those capable of satisfying this requirement /// [JsonPropertyName("userVerification")] public UserVerificationRequirement? UserVerification { get; set; } /// - /// This OPTIONAL member contains additional parameters requesting additional processing by the client and authenticator. For example, if transaction confirmation is sought from the user, then the prompt string might be included as an extension. + /// This OPTIONAL member contains additional parameters requesting additional processing by the client and authenticator. + /// For example, if transaction confirmation is sought from the user, then the prompt string might be included as an extension. /// [JsonPropertyName("extensions")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public AuthenticationExtensionsClientInputs Extensions { get; set; } + public AuthenticationExtensionsClientInputs? Extensions { get; set; } public static AssertionOptions Create( Fido2Configuration config, byte[] challenge, IReadOnlyList allowedCredentials, UserVerificationRequirement? userVerification, - AuthenticationExtensionsClientInputs extensions) + AuthenticationExtensionsClientInputs? extensions) { return new AssertionOptions() { @@ -76,6 +83,6 @@ public string ToJson() public static AssertionOptions FromJson(string json) { - return JsonSerializer.Deserialize(json, FidoModelSerializerContext.Default.AssertionOptions); + return JsonSerializer.Deserialize(json, FidoModelSerializerContext.Default.AssertionOptions)!; } } diff --git a/Src/Fido2.Models/Converters/EnumNameMapper.cs b/Src/Fido2.Models/Converters/EnumNameMapper.cs index b811ccb3..d69568bc 100644 --- a/Src/Fido2.Models/Converters/EnumNameMapper.cs +++ b/Src/Fido2.Models/Converters/EnumNameMapper.cs @@ -1,4 +1,5 @@ -using System.Diagnostics.CodeAnalysis; +using System.Collections.Frozen; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.Serialization; @@ -7,19 +8,20 @@ namespace Fido2NetLib; public static class EnumNameMapper<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] TEnum> where TEnum : struct, Enum { - private static readonly Dictionary s_valueToNames = GetIdToNameMap(); - private static readonly Dictionary s_namesToValues = Invert(s_valueToNames); + private static readonly FrozenDictionary s_valueToNames = GetIdToNameMap(); + private static readonly FrozenDictionary s_namesToValues = Invert(s_valueToNames); - private static Dictionary Invert(Dictionary map) + private static FrozenDictionary Invert(FrozenDictionary map) { - var result = new Dictionary(map.Count, StringComparer.OrdinalIgnoreCase); + var items = new KeyValuePair[map.Count]; + int i = 0; foreach (var item in map) { - result[item.Value] = item.Key; + items[i++] = new(item.Value, item.Key); } - return result; + return items.ToFrozenDictionary(StringComparer.OrdinalIgnoreCase); } public static bool TryGetValue(string name, out TEnum value) @@ -37,9 +39,9 @@ public static IEnumerable GetNames() return s_namesToValues.Keys; } - private static Dictionary GetIdToNameMap() + private static FrozenDictionary GetIdToNameMap() { - var dic = new Dictionary(); + var items = new List>(); foreach (var field in typeof(TEnum).GetFields(BindingFlags.Public | BindingFlags.Static)) { @@ -47,9 +49,9 @@ private static Dictionary GetIdToNameMap() var value = (TEnum)field.GetValue(null); - dic[value] = description is not null ? description.Value : value.ToString(); + items.Add(new(value, description is not null ? description.Value : value.ToString())); } - return dic; + return items.ToFrozenDictionary(); } } diff --git a/Src/Fido2.Models/Metadata/BiometricStatusReport.cs b/Src/Fido2.Models/Metadata/BiometricStatusReport.cs index f74aef2b..669983a4 100644 --- a/Src/Fido2.Models/Metadata/BiometricStatusReport.cs +++ b/Src/Fido2.Models/Metadata/BiometricStatusReport.cs @@ -14,8 +14,9 @@ public class BiometricStatusReport /// /// Gets or sets the level of the biometric certification of this biometric component of the authenticator. /// - [JsonPropertyName("certLevel"), Required] - public ushort CertLevel { get; set; } + [JsonPropertyName("certLevel")] + public required ushort CertLevel { get; set; } + /// /// Gets or sets a single USER_VERIFY constant indicating the modality of the biometric component. /// @@ -23,8 +24,8 @@ public class BiometricStatusReport /// This is not a bit flag combination. /// This value MUST be non-zero and this value MUST correspond to one or more entries in field userVerificationDetails in the related Metadata Statement. /// - [JsonPropertyName("modality"), Required] - public ulong Modality { get; set; } + [JsonPropertyName("modality")] + public required ulong Modality { get; set; } /// /// Gets or sets a ISO-8601 formatted date since when the certLevel achieved, if applicable. diff --git a/Src/Fido2.Models/Metadata/CodeAccuracyDescriptor.cs b/Src/Fido2.Models/Metadata/CodeAccuracyDescriptor.cs index 467ed775..bec65a15 100644 --- a/Src/Fido2.Models/Metadata/CodeAccuracyDescriptor.cs +++ b/Src/Fido2.Models/Metadata/CodeAccuracyDescriptor.cs @@ -1,5 +1,4 @@ -using System.ComponentModel.DataAnnotations; -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace Fido2NetLib; @@ -14,15 +13,15 @@ public sealed class CodeAccuracyDescriptor /// /// Gets or sets the numeric system base (radix) of the code, e.g. 10 in the case of decimal digits. /// - [JsonPropertyName("base"), Required] - public ushort Base { get; set; } - + [JsonPropertyName("base")] + public required ushort Base { get; set; } + /// /// Gets or sets the minimum number of digits of the given base required for that code, e.g. 4 in the case of 4 digits. /// - [JsonPropertyName("minLength"), Required] - public ushort MinLength { get; set; } - + [JsonPropertyName("minLength")] + public required ushort MinLength { get; set; } + /// /// Gets or sets the maximum number of false attempts before the authenticator will block this method (at least for some time). /// Zero (0) means it will never block. diff --git a/Src/Fido2.Models/Metadata/DisplayPNGCharacteristicsDescriptor.cs b/Src/Fido2.Models/Metadata/DisplayPNGCharacteristicsDescriptor.cs index 4affbf17..b0e6327a 100644 --- a/Src/Fido2.Models/Metadata/DisplayPNGCharacteristicsDescriptor.cs +++ b/Src/Fido2.Models/Metadata/DisplayPNGCharacteristicsDescriptor.cs @@ -1,5 +1,4 @@ -using System.ComponentModel.DataAnnotations; -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace Fido2NetLib; @@ -14,44 +13,44 @@ public sealed class DisplayPNGCharacteristicsDescriptor /// /// Gets or sets the image width. /// - [JsonPropertyName("width"), Required] - public ulong Width { get; set; } - + [JsonPropertyName("width")] + public required ulong Width { get; set; } + /// /// Gets or sets the image height. /// - [JsonPropertyName("height"), Required] - public ulong Height { get; set; } + [JsonPropertyName("height")] + public required ulong Height { get; set; } /// /// Gets or sets the bit depth - bits per sample or per palette index. /// - [JsonPropertyName("bitDepth"), Required] - public byte BitDepth { get; set; } + [JsonPropertyName("bitDepth")] + public required byte BitDepth { get; set; } /// /// Gets or sets the color type defines the PNG image type. /// - [JsonPropertyName("colorType"), Required] - public byte ColorType { get; set; } + [JsonPropertyName("colorType")] + public required byte ColorType { get; set; } /// /// Gets or sets the compression method used to compress the image data. /// - [JsonPropertyName("compression"), Required] - public byte Compression { get; set; } + [JsonPropertyName("compression")] + public required byte Compression { get; set; } /// /// Gets or sets the filter method is the preprocessing method applied to the image data before compression. /// - [JsonPropertyName("filter"), Required] - public byte Filter { get; set; } + [JsonPropertyName("filter")] + public required byte Filter { get; set; } /// /// Gets or sets the interlace method is the transmission order of the image data. /// - [JsonPropertyName("interlace"), Required] - public byte Interlace { get; set; } + [JsonPropertyName("interlace")] + public required byte Interlace { get; set; } /// /// Gets or sets the palette (1 to 256 palette entries). diff --git a/Src/Fido2.Models/Metadata/EcdaaTrustAnchor.cs b/Src/Fido2.Models/Metadata/EcdaaTrustAnchor.cs index a2d2540e..b05ddee1 100644 --- a/Src/Fido2.Models/Metadata/EcdaaTrustAnchor.cs +++ b/Src/Fido2.Models/Metadata/EcdaaTrustAnchor.cs @@ -1,5 +1,4 @@ -using System.ComponentModel.DataAnnotations; -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace Fido2NetLib; @@ -15,37 +14,42 @@ public sealed class EcdaaTrustAnchor /// /// Gets or sets a base64url encoding of the result of ECPoint2ToB of the ECPoint2 X=P2​x​​. /// - [JsonPropertyName("x"), Required] - public string X { get; set; } + [JsonConverter(typeof(Base64UrlConverter))] + [JsonPropertyName("x")] + public required byte[] X { get; set; } /// /// Gets or sets a base64url encoding of the result of ECPoint2ToB of the ECPoint2. /// - [JsonPropertyName("y"), Required] - public string Y { get; set; } + [JsonConverter(typeof(Base64UrlConverter))] + [JsonPropertyName("y")] + public required byte[] Y { get; set; } /// /// Gets or sets a base64url encoding of the result of BigNumberToB(c). /// - [JsonPropertyName("c"), Required] - public string C { get; set; } + [JsonConverter(typeof(Base64UrlConverter))] + [JsonPropertyName("c")] + public required byte[] C { get; set; } /// /// Gets or sets the base64url encoding of the result of BigNumberToB(sx). /// - [JsonPropertyName("sx"), Required] - public string SX { get; set; } + [JsonConverter(typeof(Base64UrlConverter))] + [JsonPropertyName("sx")] + public required byte[] SX { get; set; } /// /// Gets or sets the base64url encoding of the result of BigNumberToB(sy). /// - [JsonPropertyName("sy"), Required] - public string SY { get; set; } + [JsonConverter(typeof(Base64UrlConverter))] + [JsonPropertyName("sy")] + public required byte[] SY { get; set; } /// /// Gets or sets a name of the Barreto-Naehrig elliptic curve for G1. /// "BN_P256", "BN_P638", "BN_ISOP256", and "BN_ISOP512" are supported. /// - [JsonPropertyName("G1Curve"), Required] - public string G1Curve { get; set; } + [JsonPropertyName("G1Curve")] + public required string G1Curve { get; set; } } diff --git a/Src/Fido2.Models/Metadata/ExtensionDescriptor.cs b/Src/Fido2.Models/Metadata/ExtensionDescriptor.cs index 9adca29d..45967357 100644 --- a/Src/Fido2.Models/Metadata/ExtensionDescriptor.cs +++ b/Src/Fido2.Models/Metadata/ExtensionDescriptor.cs @@ -1,4 +1,6 @@ -using System.ComponentModel.DataAnnotations; +#nullable enable + +using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; namespace Fido2NetLib; @@ -14,8 +16,8 @@ public class ExtensionDescriptor /// /// Gets or sets the identifier that identifies the extension. /// - [JsonPropertyName("id"), Required] - public string Id { get; set; } + [JsonPropertyName("id")] + public required string Id { get; set; } /// /// Gets or sets the tag. @@ -35,7 +37,7 @@ public class ExtensionDescriptor /// This field MAY be missing or it MAY be empty. /// [JsonPropertyName("data")] - public string Data { get; set; } + public string? Data { get; set; } /// /// Gets or sets a value indication whether an unknown extensions must be ignored (false) or must lead to an error (true) when the extension is to be processed by the FIDO Server, FIDO Client, ASM, or FIDO Authenticator. diff --git a/Src/Fido2.Models/Metadata/PatternAccuracyDescriptor.cs b/Src/Fido2.Models/Metadata/PatternAccuracyDescriptor.cs index 53227e8c..1356f722 100644 --- a/Src/Fido2.Models/Metadata/PatternAccuracyDescriptor.cs +++ b/Src/Fido2.Models/Metadata/PatternAccuracyDescriptor.cs @@ -1,5 +1,4 @@ -using System.ComponentModel.DataAnnotations; -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace Fido2NetLib; @@ -14,8 +13,8 @@ public sealed class PatternAccuracyDescriptor /// /// Gets or sets the number of possible patterns (having the minimum length) out of which exactly one would be the right one, i.e. 1/probability in the case of equal distribution. /// - [JsonPropertyName("minComplexity"), Required] - public ulong MinComplexity { get; set; } + [JsonPropertyName("minComplexity")] + public required ulong MinComplexity { get; set; } /// /// Gets or sets maximum number of false attempts before the authenticator will block authentication using this method (at least temporarily). diff --git a/Src/Fido2.Models/Objects/AuthenticationExtensionsPRFInputs.cs b/Src/Fido2.Models/Objects/AuthenticationExtensionsPRFInputs.cs index b5b62897..a32a4145 100644 --- a/Src/Fido2.Models/Objects/AuthenticationExtensionsPRFInputs.cs +++ b/Src/Fido2.Models/Objects/AuthenticationExtensionsPRFInputs.cs @@ -13,6 +13,7 @@ public sealed class AuthenticationExtensionsPRFInputs /// [JsonPropertyName("eval")] public AuthenticationExtensionsPRFValues Eval { get; set; } + /// /// A record mapping base64url encoded credential IDs to PRF inputs to evaluate for that credential. /// https://w3c.github.io/webauthn/#dom-authenticationextensionsprfinputs-evalbycredential diff --git a/Src/Fido2.Models/Objects/AuthenticationExtensionsPRFOutputs.cs b/Src/Fido2.Models/Objects/AuthenticationExtensionsPRFOutputs.cs index 24f4f873..bcfcd6b3 100644 --- a/Src/Fido2.Models/Objects/AuthenticationExtensionsPRFOutputs.cs +++ b/Src/Fido2.Models/Objects/AuthenticationExtensionsPRFOutputs.cs @@ -12,6 +12,7 @@ public sealed class AuthenticationExtensionsPRFOutputs /// [JsonPropertyName("enabled")] public bool Enabled { get; set; } + /// /// The results of evaluating the PRF inputs. /// diff --git a/Src/Fido2.Models/Objects/AuthenticationExtensionsPRFValues.cs b/Src/Fido2.Models/Objects/AuthenticationExtensionsPRFValues.cs index 876299ea..ba67394e 100644 --- a/Src/Fido2.Models/Objects/AuthenticationExtensionsPRFValues.cs +++ b/Src/Fido2.Models/Objects/AuthenticationExtensionsPRFValues.cs @@ -1,4 +1,6 @@ -using System.Text.Json.Serialization; +#nullable enable + +using System.Text.Json.Serialization; namespace Fido2NetLib.Objects; @@ -12,13 +14,14 @@ public sealed class AuthenticationExtensionsPRFValues /// [JsonPropertyName("first")] [JsonConverter(typeof(Base64UrlConverter))] - public byte[] First { get; set; } + public required byte[] First { get; set; } + /// /// salt2 value to the PRF evaluation. /// [JsonPropertyName("second")] [JsonConverter(typeof(Base64UrlConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public byte[] Second { get; set; } + public byte[]? Second { get; set; } } diff --git a/Src/Fido2.Models/Objects/CredentialPropertiesOutput.cs b/Src/Fido2.Models/Objects/CredentialPropertiesOutput.cs index 2b9efd34..49fab545 100644 --- a/Src/Fido2.Models/Objects/CredentialPropertiesOutput.cs +++ b/Src/Fido2.Models/Objects/CredentialPropertiesOutput.cs @@ -1,5 +1,4 @@ -#nullable enable -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace Fido2NetLib.Objects; diff --git a/Src/Fido2.Models/Objects/Version.cs b/Src/Fido2.Models/Objects/Version.cs index d13503d8..a7c8d913 100644 --- a/Src/Fido2.Models/Objects/Version.cs +++ b/Src/Fido2.Models/Objects/Version.cs @@ -8,7 +8,6 @@ namespace Fido2NetLib; /// /// /// - public class Version { /// diff --git a/Src/Fido2/AttestationFormat/Apple.cs b/Src/Fido2/AttestationFormat/Apple.cs index fe59f3ab..b7ee6eb5 100644 --- a/Src/Fido2/AttestationFormat/Apple.cs +++ b/Src/Fido2/AttestationFormat/Apple.cs @@ -66,7 +66,7 @@ public override ValueTask VerifyAsync(VerifyAttestation ReadOnlySpan nonceToHash = request.Data; // 4. Perform SHA-256 hash of nonceToHash to produce nonce. - Span nonce = stackalloc byte[32]; + Span nonce = stackalloc byte[SHA256.HashSizeInBytes]; SHA256.HashData(nonceToHash, nonce); // 5. Verify nonce matches the value of the extension with OID ( 1.2.840.113635.100.8.2 ) in credCert. diff --git a/Src/Fido2/AttestationFormat/AppleAppAttest.cs b/Src/Fido2/AttestationFormat/AppleAppAttest.cs index 3105555c..01fb057c 100644 --- a/Src/Fido2/AttestationFormat/AppleAppAttest.cs +++ b/Src/Fido2/AttestationFormat/AppleAppAttest.cs @@ -34,9 +34,7 @@ public static byte[] GetAppleAppIdFromCredCertExtValue(X509ExtensionCollection e } // From https://www.apple.com/certificateauthority/Apple_App_Attestation_Root_CA.pem - internal static readonly string appleAppAttestationRootCA = "MIICITCCAaegAwIBAgIQC/O+DvHN0uD7jG5yH2IXmDAKBggqhkjOPQQDAzBSMSYwJAYDVQQDDB1BcHBsZSBBcHAgQXR0ZXN0YXRpb24gUm9vdCBDQTETMBEGA1UECgwKQXBwbGUgSW5jLjETMBEGA1UECAwKQ2FsaWZvcm5pYTAeFw0yMDAzMTgxODMyNTNaFw00NTAzMTUwMDAwMDBaMFIxJjAkBgNVBAMMHUFwcGxlIEFwcCBBdHRlc3RhdGlvbiBSb290IENBMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAERTHhmLW07ATaFQIEVwTtT4dyctdhNbJhFs/Ii2FdCgAHGbpphY3+d8qjuDngIN3WVhQUBHAoMeQ/cLiP1sOUtgjqK9auYen1mMEvRq9Sk3Jm5X8U62H+xTD3FE9TgS41o0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSskRBTM72+aEH/pwyp5frq5eWKoTAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIwQgFGnByvsiVbpTKwSga0kP0e8EeDS4+sQmTvb7vn53O5+FRXgeLhpJ06ysC5PrOyAjEAp5U4xDgEgllF7En3VcE3iexZZtKeYnpqtijVoyFraWVIyd/dganmrduC1bmTBGwD"; - - public static readonly X509Certificate2 AppleAppAttestRootCA = new(Convert.FromBase64String(appleAppAttestationRootCA)); + public static readonly X509Certificate2 AppleAppAttestRootCA = X509CertificateHelper.CreateFromBase64String("MIICITCCAaegAwIBAgIQC/O+DvHN0uD7jG5yH2IXmDAKBggqhkjOPQQDAzBSMSYwJAYDVQQDDB1BcHBsZSBBcHAgQXR0ZXN0YXRpb24gUm9vdCBDQTETMBEGA1UECgwKQXBwbGUgSW5jLjETMBEGA1UECAwKQ2FsaWZvcm5pYTAeFw0yMDAzMTgxODMyNTNaFw00NTAzMTUwMDAwMDBaMFIxJjAkBgNVBAMMHUFwcGxlIEFwcCBBdHRlc3RhdGlvbiBSb290IENBMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAERTHhmLW07ATaFQIEVwTtT4dyctdhNbJhFs/Ii2FdCgAHGbpphY3+d8qjuDngIN3WVhQUBHAoMeQ/cLiP1sOUtgjqK9auYen1mMEvRq9Sk3Jm5X8U62H+xTD3FE9TgS41o0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSskRBTM72+aEH/pwyp5frq5eWKoTAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIwQgFGnByvsiVbpTKwSga0kP0e8EeDS4+sQmTvb7vn53O5+FRXgeLhpJ06ysC5PrOyAjEAp5U4xDgEgllF7En3VcE3iexZZtKeYnpqtijVoyFraWVIyd/dganmrduC1bmTBGwD"u8); // From https://developer.apple.com/documentation/devicecheck/validating_apps_that_connect_to_your_server // "aaguid field is either appattestdevelop if operating in the development environment..." diff --git a/Src/Fido2/AttestationFormat/Tpm.cs b/Src/Fido2/AttestationFormat/Tpm.cs index d430ac4b..d4ea8d86 100644 --- a/Src/Fido2/AttestationFormat/Tpm.cs +++ b/Src/Fido2/AttestationFormat/Tpm.cs @@ -490,10 +490,10 @@ public CertInfo(byte[] data) private static readonly Dictionary s_tpmAlgToDigestSizeMap = new() { - { TpmAlg.TPM_ALG_SHA1, (160/8) }, - { TpmAlg.TPM_ALG_SHA256, (256/8) }, - { TpmAlg.TPM_ALG_SHA384, (384/8) }, - { TpmAlg.TPM_ALG_SHA512, (512/8) } + { TpmAlg.TPM_ALG_SHA1, SHA1.HashSizeInBytes }, + { TpmAlg.TPM_ALG_SHA256, SHA256.HashSizeInBytes }, + { TpmAlg.TPM_ALG_SHA384, SHA384.HashSizeInBytes }, + { TpmAlg.TPM_ALG_SHA512, SHA512.HashSizeInBytes } }; public static (ushort size, byte[] name) NameFromTPM2BName(ReadOnlySpan ab, ref int offset) diff --git a/Src/Fido2/AuthenticatorAttestationResponse.cs b/Src/Fido2/AuthenticatorAttestationResponse.cs index 83107de3..d5665ae8 100644 --- a/Src/Fido2/AuthenticatorAttestationResponse.cs +++ b/Src/Fido2/AuthenticatorAttestationResponse.cs @@ -268,20 +268,13 @@ private async Task DevicePublicKeyRegistrationAsync( /// /// The AttestationObject after CBOR parsing /// - public sealed class ParsedAttestationObject + public sealed class ParsedAttestationObject(string fmt, CborMap attStmt, AuthenticatorData authData) { - public ParsedAttestationObject(string fmt, CborMap attStmt, AuthenticatorData authData) - { - Fmt = fmt; - AttStmt = attStmt; - AuthData = authData; - } - - public string Fmt { get; } + public string Fmt { get; } = fmt; - public CborMap AttStmt { get; } + public CborMap AttStmt { get; } = attStmt; - public AuthenticatorData AuthData { get; } + public AuthenticatorData AuthData { get; } = authData; internal static ParsedAttestationObject FromCbor(CborMap cbor) { diff --git a/Src/Fido2/Metadata/ConformanceMetadataRepository.cs b/Src/Fido2/Metadata/ConformanceMetadataRepository.cs index ae04838d..ba7ef711 100644 --- a/Src/Fido2/Metadata/ConformanceMetadataRepository.cs +++ b/Src/Fido2/Metadata/ConformanceMetadataRepository.cs @@ -124,8 +124,7 @@ private Task DownloadDataAsync(string url, CancellationToken cancellatio public async Task DeserializeAndValidateBlobAsync(string rawBLOBJwt, CancellationToken cancellationToken = default) { - if (string.IsNullOrWhiteSpace(rawBLOBJwt)) - throw new ArgumentNullException(nameof(rawBLOBJwt)); + ArgumentException.ThrowIfNullOrWhiteSpace(rawBLOBJwt); var jwtParts = rawBLOBJwt.Split('.'); diff --git a/Src/Fido2/Metadata/Fido2MetadataServiceRepository.cs b/Src/Fido2/Metadata/Fido2MetadataServiceRepository.cs index 0e7e4c9c..0e874117 100644 --- a/Src/Fido2/Metadata/Fido2MetadataServiceRepository.cs +++ b/Src/Fido2/Metadata/Fido2MetadataServiceRepository.cs @@ -59,8 +59,7 @@ private async Task GetRawBlobAsync(CancellationToken cancellationToken) private async Task DeserializeAndValidateBlobAsync(string rawBLOBJwt, CancellationToken cancellationToken) { - if (string.IsNullOrWhiteSpace(rawBLOBJwt)) - throw new ArgumentNullException(nameof(rawBLOBJwt)); + ArgumentException.ThrowIfNullOrWhiteSpace(rawBLOBJwt); var jwtParts = rawBLOBJwt.Split('.'); diff --git a/Src/Fido2/Objects/AuthenticatorData.cs b/Src/Fido2/Objects/AuthenticatorData.cs index bb3eb201..6b7bb1b7 100644 --- a/Src/Fido2/Objects/AuthenticatorData.cs +++ b/Src/Fido2/Objects/AuthenticatorData.cs @@ -1,6 +1,7 @@ using System; using System.Buffers; using System.Diagnostics.CodeAnalysis; +using System.Security.Cryptography; using Fido2NetLib.Cbor; using Fido2NetLib.Exceptions; @@ -12,15 +13,13 @@ public sealed class AuthenticatorData( AuthenticatorFlags flags, uint signCount, AttestedCredentialData? acd, - Extensions? exts = null) + Extensions? extensions = null) { /// /// Minimum length of the authenticator data structure. /// /// - internal const int MinLength = SHA256HashLenBytes + sizeof(AuthenticatorFlags) + sizeof(uint); - - private const int SHA256HashLenBytes = 32; // 256 bits, 8 bits per byte + internal const int MinLength = SHA256.HashSizeInBytes + sizeof(AuthenticatorFlags) + sizeof(uint); /// /// SHA-256 hash of the RP ID the credential is scoped to. @@ -41,7 +40,7 @@ public sealed class AuthenticatorData( /// /// Optional extensions to suit particular use cases. /// - public Extensions? Extensions { get; } = exts; + public Extensions? Extensions { get; } = extensions; /// /// Flags contains information from the authenticator about the authentication @@ -101,9 +100,7 @@ public byte[] ToByteArray() var writer = new ArrayBufferWriter(512); writer.Write(RpIdHash); - - writer.Write(stackalloc byte[1] { (byte)_flags }); - + writer.Write([(byte)_flags]); writer.WriteUInt32BigEndian(SignCount); if (HasAttestedCredentialData && AttestedCredentialData != null) @@ -130,7 +127,7 @@ public static AuthenticatorData Parse(byte[] data) // Input parsing var reader = new MemoryReader(data); - byte[] rpIdHash = reader.ReadBytes(SHA256HashLenBytes); + byte[] rpIdHash = reader.ReadBytes(SHA256.HashSizeInBytes); var flags = (AuthenticatorFlags)reader.ReadByte();