public AuthenticatorData(byte[] authData) { // Input validation if (authData is null) { throw new Fido2VerificationException("Authenticator data cannot be null"); } if (authData.Length < MinLength) { throw new Fido2VerificationException($"Authenticator data is less than the minimum structure length of {MinLength}"); } // Input parsing var reader = new MemoryReader(authData); RpIdHash = reader.ReadBytes(SHA256HashLenBytes); _flags = (AuthenticatorFlags)reader.ReadByte(); SignCount = reader.ReadUInt32BigEndian(); // Attested credential data is only present if the AT flag is set if (HasAttestedCredentialData) { // Decode attested credential data, which starts at the next byte past the minimum length of the structure. AttestedCredentialData = new AttestedCredentialData(authData.AsMemory(reader.Position), out int bytesRead); reader.Advance(bytesRead); } // Extensions data is only present if the ED flag is set if (HasExtensionsData) { // Read the CBOR object var ext = CborObject.Decode(authData.AsMemory(reader.Position), out int bytesRead); reader.Advance(bytesRead); // Encode the CBOR object back to a byte array. Extensions = new Extensions(ext.Encode()); } // There should be no bytes left over after decoding all data from the structure if (reader.RemainingBytes != 0) { throw new Fido2VerificationException("Leftover bytes decoding AuthenticatorData"); } }