public void MetadataTOCPayloadEntry_Can_Be_JSON_Roundtripped() { var input = new MetadataTOCPayloadEntry() { AaGuid = Guid.NewGuid().ToString(), MetadataStatement = new MetadataStatement(), StatusReports = Array.Empty <StatusReport>(), TimeOfLastStatusChange = DateTime.UtcNow.ToString("o") }; input.MetadataStatement.AaGuid = Guid.NewGuid().ToString(); input.MetadataStatement.Description = "Test entry"; input.MetadataStatement.AuthenticatorVersion = 1; input.MetadataStatement.AssertionScheme = "abc123"; input.MetadataStatement.AuthenticationAlgorithm = 1; input.MetadataStatement.Upv = new UafVersion[] { new UafVersion { Major = 1, Minor = 0, } }; input.MetadataStatement.AttestationTypes = new ushort[] { 1 }; input.MetadataStatement.UserVerificationDetails = Array.Empty <VerificationMethodDescriptor[]>(); input.MetadataStatement.AttestationRootCertificates = new string[] { "..." }; var json = JsonConvert.SerializeObject(input); var output = JsonConvert.DeserializeObject <MetadataTOCPayloadEntry>(json); Assert.Equal(input.AaGuid, output.AaGuid); }
public async Task <MetadataStatement> GetMetadataStatement(MetadataTOCPayloadEntry entry) { if (_toc == null) { await GetToc(); } if (!string.IsNullOrEmpty(entry.AaGuid) && Guid.TryParse(entry.AaGuid, out Guid parsedAaGuid)) { if (_entries.ContainsKey(parsedAaGuid)) { return(_entries[parsedAaGuid].MetadataStatement); } } return(null); }
public async Task <MetadataStatement> GetMetadataStatement(MetadataTOCPayloadEntry entry) { var statementBase64Url = await DownloadStringAsync(entry.Url); var tocAlg = await GetTocAlg(); var statementBytes = Base64Url.Decode(statementBase64Url); var statementString = Encoding.UTF8.GetString(statementBytes, 0, statementBytes.Length); var statement = JsonConvert.DeserializeObject <MetadataStatement>(statementString); using (HashAlgorithm hasher = CryptoUtils.GetHasher(new HashAlgorithmName(tocAlg))) { statement.Hash = Base64Url.Encode(hasher.ComputeHash(Encoding.UTF8.GetBytes(statementBase64Url))); } return(statement); }
public async Task <MetadataStatement> GetMetadataStatement(MetadataTOCPayloadEntry entry) { var statementBase64Url = await DownloadStringAsync(entry.Url + "/?token=" + _token); var tocAlg = await GetTocAlg(); var statementBytes = Base64Url.Decode(statementBase64Url); var statementString = Encoding.UTF8.GetString(statementBytes, 0, statementBytes.Length); var statement = JsonConvert.DeserializeObject <MetadataStatement>(statementString); using (HashAlgorithm hasher = CryptoUtils.GetHasher(new HashAlgorithmName(tocAlg))) { statement.Hash = Base64Url.Encode(hasher.ComputeHash(Encoding.UTF8.GetBytes(statementBase64Url))); } if (!HashesAreEqual(entry.Hash, statement.Hash)) { throw new VerificationException("TOC entry and statement hashes do not match"); } return(statement); }
public Task <MetadataTOCPayload> GetToc() { if (Directory.Exists(_path)) { foreach (var filename in Directory.GetFiles(_path)) { var rawStatement = File.ReadAllText(filename); var statement = JsonConvert.DeserializeObject <MetadataStatement>(rawStatement); var conformanceEntry = new MetadataTOCPayloadEntry { AaGuid = statement.AaGuid, MetadataStatement = statement, StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } } }; if (null != conformanceEntry.AaGuid) { _entries.Add(new Guid(conformanceEntry.AaGuid), conformanceEntry); } } } _toc = new MetadataTOCPayload() { Entries = _entries.Select(o => o.Value).ToArray(), NextUpdate = "", //Empty means it won't get cached LegalHeader = "Local FAKE", Number = 1 }; return(Task.FromResult(_toc)); }
public async Task <MetadataTOCPayload> GetToc() { var yubico = new MetadataTOCPayloadEntry { AaGuid = "f8a011f3-8c0a-4d15-8006-17111f9edc7d", Hash = "", StatusReports = new StatusReport[] { new StatusReport() { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Yubico YubiKey FIDO2", AttestationRootCertificates = new string[] { YUBICO_ROOT } } }; _entries.Add(new Guid(yubico.AaGuid), yubico); // YubiKey 5 USB and NFC AAGUID values from https://support.yubico.com/support/solutions/articles/15000014219-yubikey-5-series-technical-manual#AAGUID_Valuesxf002do var yubikey5usb = new MetadataTOCPayloadEntry { AaGuid = "cb69481e-8ff7-4039-93ec-0a2729a154a8", Hash = "", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Yubico YubiKey 5 USB", AttestationRootCertificates = new string[] { YUBICO_ROOT } } }; _entries.Add(new Guid(yubikey5usb.AaGuid), yubikey5usb); var yubikey5nfc = new MetadataTOCPayloadEntry { AaGuid = "fa2b99dc-9e39-4257-8f92-4a30d23c4118", Hash = "", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Yubico YubiKey 5 NFC", AttestationRootCertificates = new string[] { YUBICO_ROOT } } }; _entries.Add(new Guid(yubikey5nfc.AaGuid), yubikey5nfc); var yubicoSecuriyKeyNfc = new MetadataTOCPayloadEntry { AaGuid = "6d44ba9b-f6ec-2e49-b930-0c8fe920cb73", Hash = "", StatusReports = new StatusReport[] { new StatusReport() { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { Description = "Yubico Security Key NFC", Icon = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIzLjAuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9Ill1YmljbyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgdmlld0JveD0iMCAwIDc2OCA3NjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDc2OCA3Njg7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbDojOUFDQTNDO30KPC9zdHlsZT4KPHBvbHlnb24gaWQ9IlkiIGNsYXNzPSJzdDAiIHBvaW50cz0iMjE4LjQzLDIxMS44MSAzMTYuNDksMjExLjgxIDM4Ni41Miw0MDAuMDcgNDUzLjIsMjExLjgxIDU0OS41NywyMTEuODEgMzg3LjA4LDYxMS44NiAKCTI4Ni4yMyw2MTEuODYgMzMyLjE3LDUwMi4wNCAiLz4KPHBhdGggaWQ9IkNpcmNsZV8xXyIgY2xhc3M9InN0MCIgZD0iTTM4NCwwQzE3MS45MiwwLDAsMTcxLjkyLDAsMzg0czE3MS45MiwzODQsMzg0LDM4NHMzODQtMTcxLjkyLDM4NC0zODRTNTk2LjA4LDAsMzg0LDB6CgkgTTM4NCw2OTMuNThDMjEzLjAyLDY5My41OCw3NC40Miw1NTQuOTgsNzQuNDIsMzg0UzIxMy4wMiw3NC40MiwzODQsNzQuNDJTNjkzLjU4LDIxMy4wMiw2OTMuNTgsMzg0UzU1NC45OCw2OTMuNTgsMzg0LDY5My41OHoiLz4KPC9zdmc+Cg==", AttachmentHint = 6, AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", AttestationRootCertificates = new string[] { YUBICO_ROOT } } }; _entries.Add(new Guid(yubicoSecuriyKeyNfc.AaGuid), yubicoSecuriyKeyNfc); var msftWhfbSoftware = new MetadataTOCPayloadEntry { AaGuid = "6028B017-B1D4-4C02-B4B3-AFCDAFC96BB2", Hash = "", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Windows Hello software authenticator" } }; _entries.Add(new Guid(msftWhfbSoftware.AaGuid), msftWhfbSoftware); var msftWhfbSoftwareVbs = new MetadataTOCPayloadEntry { AaGuid = "6E96969E-A5CF-4AAD-9B56-305FE6C82795", Hash = "", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Windows Hello VBS software authenticator" } }; _entries.Add(new Guid(msftWhfbSoftwareVbs.AaGuid), msftWhfbSoftwareVbs); var msftWhfbHardware = new MetadataTOCPayloadEntry { AaGuid = "08987058-CADC-4B81-B6E1-30DE50DCBE96", Hash = "", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Windows Hello hardware authenticator" } }; _entries.Add(new Guid(msftWhfbHardware.AaGuid), msftWhfbHardware); var msftWhfbHardwareVbs = new MetadataTOCPayloadEntry { AaGuid = "9DDD1817-AF5A-4672-A2B9-3E3DD95000A9", Hash = "", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Windows Hello VBS hardware authenticator" } }; _entries.Add(new Guid(msftWhfbHardwareVbs.AaGuid), msftWhfbHardwareVbs); var solostatement = await DownloadStringAsync("https://raw.githubusercontent.com/solokeys/solo/master/metadata/Solo-FIDO2-CTAP2-Authenticator.json"); var soloMetadataStatement = JsonConvert.DeserializeObject <MetadataStatement>(solostatement); var soloKeysSolo = new MetadataTOCPayloadEntry { AaGuid = soloMetadataStatement.AaGuid, Url = "https://raw.githubusercontent.com/solokeys/solo/master/metadata/Solo-FIDO2-CTAP2-Authenticator.json", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = soloMetadataStatement }; _entries.Add(new Guid(soloKeysSolo.AaGuid), soloKeysSolo); foreach (var entry in _entries) { entry.Value.MetadataStatement.AaGuid = entry.Value.AaGuid; } _toc = new MetadataTOCPayload() { Entries = _entries.Select(o => o.Value).ToArray(), NextUpdate = _cacheUntil?.ToString("yyyy-MM-dd") ?? "", //Results in no caching LegalHeader = "Static FAKE", Number = 1 }; return(_toc); }
public async Task <MetadataTOCPayload> GetToc() { #region Yubico // Yubico Security Key (5.1.x) var yubico = new MetadataTOCPayloadEntry { AaGuid = "f8a011f3-8c0a-4d15-8006-17111f9edc7d", Hash = "", StatusReports = new StatusReport[] { new StatusReport() { Status = AuthenticatorStatus.FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Yubico Security Key (5.1.x)", AttestationRootCertificates = new string[] { YUBICO_ROOT } } }; _entries.Add(new Guid(yubico.AaGuid), yubico); // YubiKey 5 (5.1.x) USB and NFC AAGUID values from https://support.yubico.com/support/solutions/articles/15000014219-yubikey-5-series-technical-manual#AAGUID_Valuesxf002do // Yubikey 5 & YubiKey 5C & YubiKey 5C Nano & YubiKey 5 Nano (5.1.x) var yubikey5usb = new MetadataTOCPayloadEntry { AaGuid = "cb69481e-8ff7-4039-93ec-0a2729a154a8", Hash = "", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Yubikey 5, YubiKey 5C, YubiKey 5C Nano, YubiKey 5 Nano (5.1.x)", AttachmentHint = 6, AttestationRootCertificates = new string[] { YUBICO_ROOT } } }; _entries.Add(new Guid(yubikey5usb.AaGuid), yubikey5usb); // Yubikey 5 & YubiKey 5C & YubiKey 5C Nano & YubiKey 5 Nano (5.2.x) var yubikey5usb52 = new MetadataTOCPayloadEntry { AaGuid = "ee882879-721c-4913-9775-3dfcce97072a", Hash = "", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Yubikey 5, YubiKey 5C, YubiKey 5C Nano, YubiKey 5 Nano (5.2.x)", AttachmentHint = 6, AttestationRootCertificates = new string[] { YUBICO_ROOT } } }; _entries.Add(new Guid(yubikey5usb52.AaGuid), yubikey5usb52); // YubiKey 5 NFC (5.1.x) var yubikey5nfc = new MetadataTOCPayloadEntry { AaGuid = "fa2b99dc-9e39-4257-8f92-4a30d23c4118", Hash = "", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Yubico YubiKey 5 NFC (5.1.x)", AttachmentHint = 30, AttestationRootCertificates = new string[] { YUBICO_ROOT } } }; _entries.Add(new Guid(yubikey5nfc.AaGuid), yubikey5nfc); // YubiKey 5 NFC (5.2.x) var yubikey5nfc52 = new MetadataTOCPayloadEntry { AaGuid = "2fc0579f-8113-47ea-b116-bb5a8db9202a", Hash = "", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Yubico YubiKey 5 NFC (5.2.x)", AttachmentHint = 30, AttestationRootCertificates = new string[] { YUBICO_ROOT } } }; _entries.Add(new Guid(yubikey5nfc52.AaGuid), yubikey5nfc52); // YubiKey 5Ci (5.2.x) var yubikey5Ci = new MetadataTOCPayloadEntry { AaGuid = "c5ef55ff-ad9a-4b9f-b580-adebafe026d", Hash = "", StatusReports = new StatusReport[] { new StatusReport() { Status = AuthenticatorStatus.FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { Description = "Yubikey 5Ci (5.2.x)", AttachmentHint = 6, AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", AttestationRootCertificates = new string[] { YUBICO_ROOT } } }; _entries.Add(new Guid(yubikey5Ci.AaGuid), yubikey5Ci); // Security Key 5.2.x var yubicoSecuriyKey52 = new MetadataTOCPayloadEntry { AaGuid = "b92c3f9a-c014-4056-887f-140a2501163b", Hash = "", StatusReports = new StatusReport[] { new StatusReport() { Status = AuthenticatorStatus.FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { Description = "Yubico Security Key (5.2.x)", AttachmentHint = 6, AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", AttestationRootCertificates = new string[] { YUBICO_ROOT } } }; _entries.Add(new Guid(yubicoSecuriyKey52.AaGuid), yubicoSecuriyKey52); // Security Key NFC 5.1.x var yubicoSecuriyKeyNfc = new MetadataTOCPayloadEntry { AaGuid = "6d44ba9b-f6ec-2e49-b930-0c8fe920cb73", Hash = "", StatusReports = new StatusReport[] { new StatusReport() { Status = AuthenticatorStatus.FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { Description = "Yubico Security Key NFC (5.1.x)", AttachmentHint = 30, AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", AttestationRootCertificates = new string[] { YUBICO_ROOT } } }; _entries.Add(new Guid(yubicoSecuriyKeyNfc.AaGuid), yubicoSecuriyKeyNfc); // Security Key NFC 5.2.x var yubicoSecuriyKeyNfc52 = new MetadataTOCPayloadEntry { AaGuid = "149a2021-8ef6-4133-96b8-81f8d5b7f1f5", Hash = "", StatusReports = new StatusReport[] { new StatusReport() { Status = AuthenticatorStatus.FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { Description = "Yubico Security Key NFC (5.2.x)", AttachmentHint = 30, AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", AttestationRootCertificates = new string[] { YUBICO_ROOT } } }; _entries.Add(new Guid(yubicoSecuriyKeyNfc52.AaGuid), yubicoSecuriyKeyNfc52); #endregion #region Microsoft Hello var msftWhfbSoftware = new MetadataTOCPayloadEntry { AaGuid = "6028B017-B1D4-4C02-B4B3-AFCDAFC96BB2", Hash = "", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Windows Hello software authenticator" } }; _entries.Add(new Guid(msftWhfbSoftware.AaGuid), msftWhfbSoftware); var msftWhfbSoftwareVbs = new MetadataTOCPayloadEntry { AaGuid = "6E96969E-A5CF-4AAD-9B56-305FE6C82795", Hash = "", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Windows Hello VBS software authenticator" } }; _entries.Add(new Guid(msftWhfbSoftwareVbs.AaGuid), msftWhfbSoftwareVbs); var msftWhfbHardware = new MetadataTOCPayloadEntry { AaGuid = "08987058-CADC-4B81-B6E1-30DE50DCBE96", Hash = "", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Windows Hello hardware authenticator" } }; _entries.Add(new Guid(msftWhfbHardware.AaGuid), msftWhfbHardware); var msftWhfbHardwareVbs = new MetadataTOCPayloadEntry { AaGuid = "9DDD1817-AF5A-4672-A2B9-3E3DD95000A9", Hash = "", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = new MetadataStatement { AttestationTypes = new ushort[] { (ushort)MetadataAttestationType.ATTESTATION_BASIC_FULL }, Hash = "", Description = "Windows Hello VBS hardware authenticator" } }; _entries.Add(new Guid(msftWhfbHardwareVbs.AaGuid), msftWhfbHardwareVbs); #endregion #region Solo var solostatement = await DownloadStringAsync("https://raw.githubusercontent.com/solokeys/solo/master/metadata/Solo-FIDO2-CTAP2-Authenticator.json"); var soloMetadataStatement = JsonConvert.DeserializeObject <MetadataStatement>(solostatement); var soloKeysSolo = new MetadataTOCPayloadEntry { AaGuid = soloMetadataStatement.AaGuid, Url = "https://raw.githubusercontent.com/solokeys/solo/master/metadata/Solo-FIDO2-CTAP2-Authenticator.json", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = soloMetadataStatement }; _entries.Add(new Guid(soloKeysSolo.AaGuid), soloKeysSolo); var soloTapStatement = await DownloadStringAsync("https://raw.githubusercontent.com/solokeys/solo/master/metadata/SoloTap-FIDO2-CTAP2-Authenticator.json"); var soloTapMetadataStatement = JsonConvert.DeserializeObject <MetadataStatement>(soloTapStatement); var soloTapMetadata = new MetadataTOCPayloadEntry { AaGuid = soloTapMetadataStatement.AaGuid, Url = "https://raw.githubusercontent.com/solokeys/solo/master/metadata/SoloTap-FIDO2-CTAP2-Authenticator.json", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = soloTapMetadataStatement }; _entries.Add(new Guid(soloTapMetadata.AaGuid), soloTapMetadata); var soloSomuStatement = await DownloadStringAsync("https://raw.githubusercontent.com/solokeys/solo/master/metadata/Somu-FIDO2-CTAP2-Authenticator.json"); var soloSomuMetadataStatement = JsonConvert.DeserializeObject <MetadataStatement>(soloSomuStatement); var soloSomuMetadata = new MetadataTOCPayloadEntry { AaGuid = soloSomuMetadataStatement.AaGuid, Url = "https://raw.githubusercontent.com/solokeys/solo/master/metadata/Somu-FIDO2-CTAP2-Authenticator.json", StatusReports = new StatusReport[] { new StatusReport { Status = AuthenticatorStatus.NOT_FIDO_CERTIFIED } }, MetadataStatement = soloSomuMetadataStatement }; _entries.Add(new Guid(soloSomuMetadata.AaGuid), soloSomuMetadata); #endregion foreach (var entry in _entries) { entry.Value.MetadataStatement.AaGuid = entry.Value.AaGuid; } _toc = new MetadataTOCPayload() { Entries = _entries.Select(o => o.Value).ToArray(), NextUpdate = _cacheUntil?.ToString("yyyy-MM-dd") ?? "", //Results in no caching LegalHeader = "Static FAKE", Number = 1 }; return(_toc); }