public virtual void TestDecodeAuthenticateResponse() { KeySignResponse keySignResponse = RawMessageCodec .DecodeKeySignResponse(SIGN_RESPONSE_DATA.Segment()); Assert.AreEqual(new KeySignResponse(UserPresenceVerifierConstants.UserPresentFlag, COUNTER_VALUE, SIGNATURE_AUTHENTICATE), keySignResponse); }
public virtual void TestEncodeRegisterRequest() { var registerRequest = new KeyRegisterRequest(APP_ID_ENROLL_SHA256, BROWSER_DATA_ENROLL_SHA256); var encodedBytes = RawMessageCodec.EncodeKeyRegisterRequest(registerRequest); CollectionAssert.AreEqual(REGISTRATION_REQUEST_DATA, encodedBytes); }
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); }
public async Task <RegisterResponse> Register(ICollection <RegisterRequest> registrationRequests, ICollection <SignRequest> signRequests, CancellationToken cancellationToken = default(CancellationToken)) { var appIds = registrationRequests .Select(r => r.AppId) .Concat(signRequests.Select(r => r.AppId)) .Distinct() .ToList(); await CheckOriginAndAppIdsAsync(appIds, cancellationToken); var signInfos = signRequests.Select(GenerateSignInfo).ToDictionary(s => s.KeySignRequest); var keySignRequests = signInfos.Keys.ToList(); var registerInfos = registrationRequests.Select(GenerateRegisterInfo).ToDictionary(s => s.KeyRegisterRequest); var keyRegisterRequests = registerInfos.Keys.ToList(); var result = await keyOperations.Register(keyRegisterRequests, keySignRequests, cancellationToken); if (!result.IsSuccess) { return(null); } var registerInfo = registerInfos[result.Request]; return(new RegisterResponse( WebSafeBase64Converter.ToBase64String(RawMessageCodec.EncodeKeyRegisterResponse(result.Response)), WebSafeBase64Converter.ToBase64String(registerInfo.ClientDataBase64), registerInfo.RegisterRequest.SessionId)); }
public virtual void TestEncodeAuthenticateSignedBytes() { var encodedBytes = RawMessageCodec.EncodeKeySignSignedBytes(APP_ID_SIGN_SHA256, UserPresenceVerifierConstants.UserPresentFlag, COUNTER_VALUE, BROWSER_DATA_SIGN_SHA256); CollectionAssert.AreEqual(EXPECTED_AUTHENTICATE_SIGNED_BYTES, encodedBytes); }
/// <exception cref="U2FException" /> public KeySignResponse Authenticate(KeySignRequest keySignRequest) { if (keySignRequest == null) { throw new ArgumentNullException(nameof(keySignRequest)); } log.Info(">> authenticate"); var applicationSha256 = keySignRequest.ApplicationSha256; var challengeSha256 = keySignRequest.ChallengeSha256; var keyHandle = keySignRequest.KeyHandle; log.Info(" -- Inputs --"); log.Info(" applicationSha256: " + applicationSha256.ToHexString()); log.Info(" challengeSha256: " + challengeSha256.ToHexString()); log.Info(" keyHandle: " + keyHandle.ToHexString()); var keyPair = dataStore.GetKeyPair(keyHandle); var counter = dataStore.IncrementCounter(); var userPresence = userPresenceVerifier.VerifyUserPresence(); var signedData = RawMessageCodec.EncodeKeySignSignedBytes(applicationSha256, userPresence, counter, challengeSha256); log.Info("Signing bytes " + signedData.ToHexString()); var signature = crypto.Sign(signedData, keyPair.PrivateKey); log.Info(" -- Outputs --"); log.Info(" userPresence: " + userPresence); log.Info(" counter: " + counter); log.Info(" signature: " + signature.ToHexString()); log.Info("<< authenticate"); return(new KeySignResponse(userPresence, counter, signature)); }
public virtual void TestDecodeRegisterRequest() { KeyRegisterRequest keyRegisterRequest = RawMessageCodec .DecodeKeyRegisterRequest(REGISTRATION_REQUEST_DATA); Assert.AreEqual(new KeyRegisterRequest(APP_ID_ENROLL_SHA256 , BROWSER_DATA_ENROLL_SHA256), keyRegisterRequest); }
public virtual void TestEncodeAuthenticateResponse() { var authenticateResponse = new KeySignResponse(UserPresenceVerifierConstants.UserPresentFlag, COUNTER_VALUE, SIGNATURE_AUTHENTICATE); var encodedBytes = RawMessageCodec.EncodeKeySignResponse(authenticateResponse); CollectionAssert.AreEqual(SIGN_RESPONSE_DATA, encodedBytes); }
public virtual void TestDecodeAuthenticateRequest() { var authenticateRequest = RawMessageCodec.DecodeKeySignRequest(SIGN_REQUEST_DATA); Assert.AreEqual( new KeySignRequest(U2FVersion.V2, BROWSER_DATA_SIGN_SHA256, APP_ID_SIGN_SHA256, KEY_HANDLE), authenticateRequest); }
public virtual void TestDecodeRegisterResponse() { var registerResponse = RawMessageCodec.DecodeKeyRegisterResponse(REGISTRATION_RESPONSE_DATA.Segment()); Assert.AreEqual( new KeyRegisterResponse(USER_PUBLIC_KEY_ENROLL_HEX, KEY_HANDLE, VENDOR_CERTIFICATE, SIGNATURE_ENROLL), registerResponse); }
public virtual void TestEncodeAuthenticateRequest() { var authenticateRequest = new KeySignRequest(U2FVersion.V2, BROWSER_DATA_SIGN_SHA256, APP_ID_SIGN_SHA256, KEY_HANDLE); var encodedBytes = RawMessageCodec.EncodeKeySignRequest(authenticateRequest); CollectionAssert.AreEqual(SIGN_REQUEST_DATA, encodedBytes); }
public virtual void TestEncodeRegisterResponse() { var registerResponse = new KeyRegisterResponse(USER_PUBLIC_KEY_ENROLL_HEX, KEY_HANDLE, VENDOR_CERTIFICATE, SIGNATURE_ENROLL); var encodedBytes = RawMessageCodec.EncodeKeyRegisterResponse(registerResponse); CollectionAssert.AreEqual(REGISTRATION_RESPONSE_DATA, encodedBytes); }
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)); }
public Task <KeyResponse <KeySignResponse> > SignAsync(KeySignRequest request, CancellationToken cancellationToken = new CancellationToken(), bool noWink = false) { if (request == null) { throw new ArgumentNullException(nameof(request)); } log.Info(">> authenticate"); var applicationSha256 = request.ApplicationSha256; var challengeSha256 = request.ChallengeSha256; var keyHandle = request.KeyHandle; log.Info(" -- Inputs --"); log.Info(" applicationSha256: " + applicationSha256.ToHexString()); log.Info(" challengeSha256: " + challengeSha256.ToHexString()); log.Info(" keyHandle: " + keyHandle.ToHexString()); var keyPair = dataStore.GetKeyPair(keyHandle); var counter = dataStore.IncrementCounter(); var userPresent = userPresenceVerifier.VerifyUserPresence(); if ((userPresent & UserPresenceVerifierConstants.UserPresentFlag) == 0) { return(TestOfUserPresenceRequired <KeySignResponse>()); } var signedData = RawMessageCodec.EncodeKeySignSignedBytes(applicationSha256, userPresent, counter, challengeSha256); log.Info("Signing bytes " + signedData.ToHexString()); var signature = crypto.Sign(signedData, keyPair.PrivateKey); log.Info(" -- Outputs --"); log.Info(" userPresence: " + userPresent); log.Info(" counter: " + counter); log.Info(" signature: " + signature.ToHexString()); log.Info("<< authenticate"); var response = new KeySignResponse(userPresent, counter, signature); var responseData = RawMessageCodec.EncodeKeySignResponse(response).Segment(); var apdu = new ApduResponse(ApduResponseStatus.NoError, responseData); var keyResponse = new KeyResponse <KeySignResponse>(apdu, response, KeyResponseStatus.Success); return(TaskEx.FromResult(keyResponse)); }
/// <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)); }
public void Register(string origin, string accountName) { var registrationRequest = server.GetRegistrationRequest(accountName, origin); if (!registrationRequest.Version.Equals(U2FConsts.U2Fv2)) { throw new U2FException($"Unsupported protocol version: {registrationRequest.Version}"); } appIdVerifier.ValidateOrigin(registrationRequest.AppId, origin); var channelIdJson = channelIdProvider.GetJsonChannelId(); string clientData; var registerRequest = RegistrationRequestToRegisterRequest(origin, registrationRequest, channelIdJson, out clientData, crypto); var registerResponse = key.Register(registerRequest); var rawRegisterResponse = RawMessageCodec.EncodeKeyRegisterResponse(registerResponse); var rawRegisterResponseBase64 = WebSafeBase64Converter.ToBase64String(rawRegisterResponse); var clientDataBase64 = WebSafeBase64Converter.ToBase64String(Encoding.UTF8.GetBytes(clientData)); server.ProcessRegistrationResponse( new RegisterResponse(rawRegisterResponseBase64, clientDataBase64, registrationRequest.SessionId), clock.Now.ToUnixTimeMilliseconds()); }
public void Authenticate(string origin, string accountName) { // the key can be used to sign any of the requests - we're gonna sign the first one. var signRequest = server.GetSignRequests(accountName, origin)[0]; if (!signRequest.Version.Equals(U2FConsts.U2Fv2)) { throw new U2FException($"Unsupported protocol version: {signRequest.Version}"); } appIdVerifier.ValidateOrigin(signRequest.AppId, origin); var channelIdJson = channelIdProvider.GetJsonChannelId(); string clientData; var authenticateRequest = SignRequestToAuthenticateRequest(origin, signRequest, channelIdJson, out clientData, crypto); var authenticateResponse = key.Authenticate(authenticateRequest); var rawAuthenticateResponse = RawMessageCodec.EncodeKeySignResponse(authenticateResponse); var rawAuthenticateResponse64 = WebSafeBase64Converter.ToBase64String(rawAuthenticateResponse); var clientDataBase64 = WebSafeBase64Converter.ToBase64String(Encoding.UTF8.GetBytes(clientData)); server.ProcessSignResponse(new SignResponse(clientDataBase64, rawAuthenticateResponse64, signRequest.Challenge, signRequest.SessionId, signRequest.AppId)); }
public SecurityKeyData ProcessSignResponse(SignResponse signResponse) { log.Info(">> processSignResponse"); var sessionId = signResponse.SessionId; var browserDataBase64 = signResponse.Bd; var rawSignDataBase64 = signResponse.Sign; var sessionData = dataStore.GetSignSessionData(sessionId); if (sessionData == null) { throw new U2FException("Unknown session_id"); } var appId = sessionData.AppId; var securityKeyData = dataStore .GetSecurityKeyData(sessionData.AccountName) .FirstOrDefault(k => sessionData.GetPublicKey().SequenceEqual(k.PublicKey)); if (securityKeyData == null) { throw new U2FException("No security keys registered for this user"); } var browserDataBytes = WebSafeBase64Converter.FromBase64String(browserDataBase64); var browserData = Encoding.UTF8.GetString(browserDataBytes, 0, browserDataBytes.Length); var rawSignData = WebSafeBase64Converter.FromBase64String(rawSignDataBase64); log.Info("-- Input --"); log.Info(" sessionId: " + sessionId); log.Info(" publicKey: " + securityKeyData.PublicKey.ToHexString()); log.Info(" challenge: " + sessionData.Challenge.ToHexString()); log.Info(" accountName: " + sessionData.AccountName); log.Info(" browserData: " + browserData); log.Info(" rawSignData: " + rawSignData.ToHexString()); VerifyBrowserData(browserData, "navigator.id.getAssertion", sessionData); var authenticateResponse = RawMessageCodec.DecodeKeySignResponse(rawSignData.Segment()); var userPresence = authenticateResponse.UserPresence; var counter = authenticateResponse.Counter; var signature = authenticateResponse.Signature; log.Info("-- Parsed rawSignData --"); log.Info(" userPresence: " + userPresence.ToString("X2")); log.Info(" counter: " + counter); log.Info(" signature: " + signature.ToHexString()); if (userPresence != UserPresenceVerifierConstants.UserPresentFlag) { throw new U2FException("User presence invalid during authentication"); } if (counter <= securityKeyData.Counter) { throw new U2FException("Counter value smaller than expected!"); } var appIdSha256 = cryto.ComputeSha256(Encoding.UTF8.GetBytes(appId)); var browserDataSha256 = cryto.ComputeSha256(Encoding.UTF8.GetBytes(browserData)); var signedBytes = RawMessageCodec.EncodeKeySignSignedBytes(appIdSha256, userPresence, counter, browserDataSha256); log.Info("Verifying signature of bytes " + signedBytes.ToHexString()); if (!cryto.VerifySignature(cryto.DecodePublicKey(securityKeyData.PublicKey), signedBytes, signature)) { throw new U2FException("Signature is invalid"); } dataStore.UpdateSecurityKeyCounter(sessionData.AccountName, securityKeyData.PublicKey, counter); log.Info("<< processSignResponse"); return(securityKeyData); }
/// <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); }