コード例 #1
0
        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));
        }
コード例 #2
0
        public void AddSecurityKeyData(string accountName, SecurityKeyData securityKeyData)
        {
            var tokens = GetSecurityKeyData(accountName);

            tokens.Add(securityKeyData);
            securityKeyDataBase[accountName] = tokens;
        }
コード例 #3
0
        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));
        }
コード例 #4
0
        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));
        }
コード例 #5
0
        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);
                }
            }
        }
コード例 #6
0
 public void AddSecurityKeyData(string accountName, SecurityKeyData securityKeyData)
 {
     inMemoryStore.AddSecurityKeyData(accountName, securityKeyData);
     Save();
 }
コード例 #7
0
        /// <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);
        }