예제 #1
0
        public virtual void TestEncodeRegisterSignedBytes()
        {
            var encodedBytes = RawMessageCodec.EncodeKeyRegisterSignedBytes(APP_ID_ENROLL_SHA256,
                                                                            BROWSER_DATA_ENROLL_SHA256, KEY_HANDLE, USER_PUBLIC_KEY_ENROLL_HEX);

            CollectionAssert.AreEqual(EXPECTED_REGISTER_SIGNED_BYTES, encodedBytes);
        }
예제 #2
0
        public Task <KeyResponse <KeyRegisterResponse> > RegisterAsync(KeyRegisterRequest request, CancellationToken cancellationToken = new CancellationToken(),
                                                                       bool invididualAttestation = false)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            log.Info(">> register");

            var applicationSha256 = request.ApplicationSha256;
            var challengeSha256   = request.ChallengeSha256;

            log.Info(" -- Inputs --");
            log.Info("  applicationSha256: " + applicationSha256.ToHexString());
            log.Info("  challengeSha256: " + challengeSha256.ToHexString());

            var userPresent = userPresenceVerifier.VerifyUserPresence();

            if ((userPresent & UserPresenceVerifierConstants.UserPresentFlag) == 0)
            {
                return(TestOfUserPresenceRequired <KeyRegisterResponse>());
            }

            var keyPair   = keyPairGenerator.GenerateKeyPair(applicationSha256, challengeSha256);
            var keyHandle = keyHandleGenerator.GenerateKeyHandle(applicationSha256, keyPair);

            dataStore.StoreKeyPair(keyHandle, keyPair);

            var userPublicKey = keyPairGenerator.EncodePublicKey(keyPair.PublicKey);
            var signedData    = RawMessageCodec.EncodeKeyRegisterSignedBytes(applicationSha256, challengeSha256, keyHandle,
                                                                             userPublicKey);

            log.Info("Signing bytes " + signedData.ToHexString());
            var signature = crypto.Sign(signedData, certificatePrivateKey);

            log.Info(" -- Outputs --");
            log.Info("  userPublicKey: " + userPublicKey.ToHexString());
            log.Info("  keyHandle: " + keyHandle.ToHexString());
            log.Info("  vendorCertificate: " + vendorCertificate);
            log.Info("  signature: " + signature.ToHexString());
            log.Info("<< register");

            var response     = new KeyRegisterResponse(userPublicKey, keyHandle, vendorCertificate, signature);
            var responseData = RawMessageCodec.EncodeKeyRegisterResponse(response).Segment();
            var apdu         = new ApduResponse(ApduResponseStatus.NoError, responseData);
            var keyResponse  = new KeyResponse <KeyRegisterResponse>(apdu, response, KeyResponseStatus.Success);

            return(TaskEx.FromResult(keyResponse));
        }
예제 #3
0
        /// <exception cref="U2FException" />
        public KeyRegisterResponse Register(KeyRegisterRequest keyRegisterRequest)
        {
            if (keyRegisterRequest == null)
            {
                throw new ArgumentNullException(nameof(keyRegisterRequest));
            }

            log.Info(">> register");

            var applicationSha256 = keyRegisterRequest.ApplicationSha256;
            var challengeSha256   = keyRegisterRequest.ChallengeSha256;

            log.Info(" -- Inputs --");
            log.Info("  applicationSha256: " + applicationSha256.ToHexString());
            log.Info("  challengeSha256: " + challengeSha256.ToHexString());

            var userPresent = userPresenceVerifier.VerifyUserPresence();

            if ((userPresent & UserPresenceVerifierConstants.UserPresentFlag) == 0)
            {
                throw new U2FException("Cannot verify user presence");
            }

            var keyPair   = keyPairGenerator.GenerateKeyPair(applicationSha256, challengeSha256);
            var keyHandle = keyHandleGenerator.GenerateKeyHandle(applicationSha256, keyPair);

            dataStore.StoreKeyPair(keyHandle, keyPair);

            var userPublicKey = keyPairGenerator.EncodePublicKey(keyPair.PublicKey);
            var signedData    = RawMessageCodec.EncodeKeyRegisterSignedBytes(applicationSha256, challengeSha256, keyHandle,
                                                                             userPublicKey);

            log.Info("Signing bytes " + signedData.ToHexString());
            var signature = crypto.Sign(signedData, certificatePrivateKey);

            log.Info(" -- Outputs --");
            log.Info("  userPublicKey: " + userPublicKey.ToHexString());
            log.Info("  keyHandle: " + keyHandle.ToHexString());
            log.Info("  vendorCertificate: " + vendorCertificate);
            log.Info("  signature: " + signature.ToHexString());
            log.Info("<< register");

            return(new KeyRegisterResponse(userPublicKey, keyHandle, vendorCertificate, signature));
        }
예제 #4
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);
        }