public virtual void TestProcessRegistrationResponse_MultipleTransports() { mockDataStore.Setup(x => x.GetEnrollSessionData(SESSION_ID)) .Returns(new EnrollSessionData(ACCOUNT_NAME, APP_ID_ENROLL, SERVER_CHALLENGE_ENROLL)); var trustedCertificates = new List <X509Certificate>(); trustedCertificates.Add(TRUSTED_CERTIFICATE_MULTIPLE_TRANSPORTS); mockDataStore.Setup(x => x.GetTrustedCertificates()).Returns(trustedCertificates); var u2FServer = new U2FServerReferenceImpl(mockChallengeGenerator.Object, mockDataStore.Object, crypto, TRUSTED_DOMAINS); var registrationResponse = new RegisterResponse(REGISTRATION_RESPONSE_DATA_MULTIPLE_TRANSPORTS_BASE64, BROWSER_DATA_ENROLL_BASE64, SESSION_ID); u2FServer.ProcessRegistrationResponse(registrationResponse, 0L); var transports = new List <SecurityKeyDataTransports>(); transports.Add(SecurityKeyDataTransports.BluetoothRadio); transports.Add(SecurityKeyDataTransports.BluetoothLowEnergy); transports.Add(SecurityKeyDataTransports.Nfc); var expectedKeyData = new SecurityKeyData(0L, transports, KEY_HANDLE, USER_PUBLIC_KEY_ENROLL_HEX, TRUSTED_CERTIFICATE_MULTIPLE_TRANSPORTS, 0); mockDataStore.Verify(x => x.AddSecurityKeyData(ACCOUNT_NAME, expectedKeyData)); }
public void AddSecurityKeyData(string accountName, SecurityKeyData securityKeyData) { var tokens = GetSecurityKeyData(accountName); tokens.Add(securityKeyData); securityKeyDataBase[accountName] = tokens; }
public virtual void TestProcessRegistrationResponse_NoTransports() { mockDataStore.Setup(x => x.GetEnrollSessionData(SESSION_ID)) .Returns(new EnrollSessionData(ACCOUNT_NAME, APP_ID_ENROLL, SERVER_CHALLENGE_ENROLL)); var u2FServer = new U2FServerReferenceImpl(mockChallengeGenerator.Object, mockDataStore.Object, crypto, TRUSTED_DOMAINS); var registrationResponse = new RegisterResponse(REGISTRATION_DATA_BASE64, BROWSER_DATA_ENROLL_BASE64, SESSION_ID); u2FServer.ProcessRegistrationResponse(registrationResponse, 0L); var expectedKeyData = new SecurityKeyData(0L, KEY_HANDLE, USER_PUBLIC_KEY_ENROLL_HEX, VENDOR_CERTIFICATE, 0); mockDataStore.Verify(x => x.AddSecurityKeyData(ACCOUNT_NAME, expectedKeyData)); }
public virtual void TestProcessRegistrationResponse2() { mockDataStore.Setup(x => x.GetEnrollSessionData(SESSION_ID)) .Returns(new EnrollSessionData(ACCOUNT_NAME, APP_ID_ENROLL, SERVER_CHALLENGE_ENROLL)); var trustedCertificates = new List <X509Certificate>(); trustedCertificates.Add(VENDOR_CERTIFICATE); trustedCertificates.Add(TRUSTED_CERTIFICATE_2); mockDataStore.Setup(x => x.GetTrustedCertificates()).Returns(trustedCertificates); var u2FServer = new U2FServerReferenceImpl(mockChallengeGenerator.Object, mockDataStore.Object, crypto, TRUSTED_DOMAINS); var registrationResponse = new RegisterResponse(REGISTRATION_DATA_2_BASE64, BROWSER_DATA_2_BASE64, SESSION_ID); u2FServer.ProcessRegistrationResponse(registrationResponse, 0L); var expectedKeyData = new SecurityKeyData(0L, null, KEY_HANDLE_2, USER_PUBLIC_KEY_2, TRUSTED_CERTIFICATE_2, 0); mockDataStore.Verify(x => x.AddSecurityKeyData(ACCOUNT_NAME, expectedKeyData)); }
private void LoadFromJson(JObject json) { securityKeyDataBase.Clear(); var keys = json.GetValue("keys") as JObject ?? new JObject(); foreach (var pair in keys) { var accountName = pair.Key; var keyDatas = pair.Value; foreach (var keyData in keyDatas) { var enrollmentTime = (long)keyData["enrollmentTime"]; var keyHandle = WebSafeBase64Converter.FromBase64String((string)keyData["keyHandle"]); var publicKey = WebSafeBase64Converter.FromBase64String((string)keyData["publicKey"]); var attestationCertBytes = WebSafeBase64Converter.FromBase64String((string)keyData["attestationCert"]); var attestationCert = new X509CertificateParser().ReadCertificate(attestationCertBytes); var counter = (int)keyData["counter"]; var transportToken = keyData["transports"]; List <SecurityKeyDataTransports> transports = null; if (transportToken != null && transportToken.Type != JTokenType.Null) { var transportsArray = (JArray)transportToken; transports = transportsArray .Select(o => (string)o) .Select( s => (SecurityKeyDataTransports)Enum.Parse(typeof(SecurityKeyDataTransports), s, true)) .ToList(); } var securityKeyData = new SecurityKeyData(enrollmentTime, transports, keyHandle, publicKey, attestationCert, counter); AddSecurityKeyData(accountName, securityKeyData); } } }
public void AddSecurityKeyData(string accountName, SecurityKeyData securityKeyData) { inMemoryStore.AddSecurityKeyData(accountName, securityKeyData); Save(); }
/// <exception cref="U2FException" /> public SecurityKeyData ProcessRegistrationResponse(RegisterResponse registrationResponse, long currentTimeInMillis) { log.Info(">> processRegistrationResponse"); var sessionId = registrationResponse.SessionId; var browserDataBase64 = registrationResponse.Bd; var rawRegistrationDataBase64 = registrationResponse.RegistrationData; var sessionData = dataStore.GetEnrollSessionData(sessionId); if (sessionData == null) { throw new U2FException("Unknown session_id"); } var appId = sessionData.AppId; var rawBrowserData = WebSafeBase64Converter.FromBase64String(browserDataBase64); var browserData = Encoding.UTF8.GetString(rawBrowserData, 0, rawBrowserData.Length); var rawRegistrationData = WebSafeBase64Converter.FromBase64String(rawRegistrationDataBase64); log.Info("-- Input --"); log.Info(" sessionId: " + sessionId); log.Info(" challenge: " + sessionData.Challenge.ToHexString()); log.Info(" accountName: " + sessionData.AccountName); log.Info(" browserData: " + browserData); log.Info(" rawRegistrationData: " + rawRegistrationData.ToHexString()); var registerResponse = RawMessageCodec.DecodeKeyRegisterResponse(rawRegistrationData.Segment()); var userPublicKey = registerResponse.UserPublicKey; var keyHandle = registerResponse.KeyHandle; var attestationCertificate = registerResponse.AttestationCertificate; var signature = registerResponse.Signature; IList <SecurityKeyDataTransports> transports = null; try { transports = ParseTransportsExtension(attestationCertificate); } catch (CertificateParsingException e1) { log.Warn("Could not parse transports extension " + e1.Message); } log.Info("-- Parsed rawRegistrationResponse --"); log.Info(" userPublicKey: " + userPublicKey.ToHexString ()); log.Info(" keyHandle: " + keyHandle.ToHexString()); log.Info(" attestationCertificate: " + SecurityKeyData.SafeCertificateToString(attestationCertificate)); log.Info(" transports: " + transports); log.Info(" attestationCertificate bytes: " + attestationCertificate.GetEncoded().ToHexString()); log.Info(" signature: " + signature.ToHexString()); var appIdSha256 = cryto.ComputeSha256(Encoding.UTF8.GetBytes(appId)); var browserDataSha256 = cryto.ComputeSha256(Encoding.UTF8.GetBytes(browserData)); var signedBytes = RawMessageCodec.EncodeKeyRegisterSignedBytes(appIdSha256, browserDataSha256, keyHandle, userPublicKey); var trustedCertificates = dataStore.GetTrustedCertificates(); if (!trustedCertificates.Contains(attestationCertificate)) { log.Warn("Attestion cert is not trusted"); } VerifyBrowserData(browserData, "navigator.id.finishEnrollment", sessionData); log.Info("Verifying signature of bytes " + signedBytes.ToHexString()); if (!cryto.VerifySignature(attestationCertificate, signedBytes, signature)) { throw new U2FException("Signature is invalid"); } // The first time we create the SecurityKeyData, we set the counter value to -1. // We don't actually know what the counter value of the real device is - but it will // be something bigger than -1, so subsequent signatures will check out ok. var securityKeyData = new SecurityKeyData(currentTimeInMillis, transports, keyHandle, userPublicKey, attestationCertificate, -1); /* initial counter value */ dataStore.AddSecurityKeyData(sessionData.AccountName, securityKeyData); log.Info("<< processRegistrationResponse"); return(securityKeyData); }