Beispiel #1
0
        public JObject SaveToJson()
        {
            var result = new JObject();

            var keys = new JObject();

            foreach (var key in securityKeyDataBase)
            {
                var keyDatas = new JArray();
                foreach (var keyData in key.Value)
                {
                    var attestationCert = keyData.AttestationCertificate.GetEncoded();
                    var transports      = keyData.Transports?.Select(t => (object)t.ToString()).ToArray();

                    var keyDataJson = new JObject
                    {
                        ["enrollmentTime"]  = keyData.EnrollmentTime,
                        ["keyHandle"]       = WebSafeBase64Converter.ToBase64String(keyData.KeyHandle),
                        ["publicKey"]       = WebSafeBase64Converter.ToBase64String(keyData.PublicKey),
                        ["attestationCert"] = WebSafeBase64Converter.ToBase64String(attestationCert),
                        ["counter"]         = keyData.Counter,
                        ["transports"]      = transports != null ? new JArray(transports) : null
                    };

                    keyDatas.Add(keyDataJson);
                }
                keys[key.Key] = keyDatas;
            }
            result["keys"] = keys;

            return(result);
        }
Beispiel #2
0
        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 static FidoKeyHandle FromWebSafeBase64(string keyHandle)
        {
            if (keyHandle == null)
            {
                throw new ArgumentNullException("keyHandle");
            }

            return(new FidoKeyHandle(WebSafeBase64Converter.FromBase64String(keyHandle)));
        }
Beispiel #4
0
 internal static FidoClientData CreateGoodClientData()
 {
     return(new FidoClientData
     {
         Challenge = WebSafeBase64Converter.ToBase64String(Encoding.Default.GetBytes("random challenge")),
         Origin = "http://localhost",
         Type = "type"
     });
 }
Beispiel #5
0
        public static FidoPublicKey FromWebSafeBase64(string publicKey)
        {
            if (publicKey == null)
            {
                throw new ArgumentNullException("publicKey");
            }

            return(new FidoPublicKey(WebSafeBase64Converter.FromBase64String(publicKey)));
        }
        public static FidoSignature FromWebSafeBase64(string signature)
        {
            if (signature == null)
            {
                throw new ArgumentNullException("signature");
            }

            return(new FidoSignature(WebSafeBase64Converter.FromBase64String(signature)));
        }
Beispiel #7
0
        SignInfo GenerateSignInfo(SignRequest signRequest)
        {
            var clientDataB64 = ClientDataCodec.EncodeClientData(ClientDataCodec.RequestTypeAuthenticate, signRequest.Challenge,
                                                                 sender.Origin, sender.ChannelId);
            var clientDataSha256 = crypto.ComputeSha256(clientDataB64);
            var appIdSha256      = crypto.ComputeSha256(signRequest.AppId);
            var keyHandle        = WebSafeBase64Converter.FromBase64String(signRequest.KeyHandle);
            var authRequest      = new KeySignRequest(U2FVersion.V2,
                                                      clientDataSha256, appIdSha256, keyHandle);

            return(new SignInfo(signRequest, clientDataB64, authRequest));
        }
 public override string ToString()
 {
     return(new StringBuilder()
            .AppendFormat("public_key: {0}\n", WebSafeBase64Converter.ToBase64String(PublicKey))
            .AppendFormat("key_handle: {0}\n", WebSafeBase64Converter.ToBase64String(KeyHandle))
            .AppendFormat("counter: {0}\n", Counter)
            .AppendFormat("attestation certificate:\n")
            .Append(SafeCertificateToString(AttestationCertificate))
            .Append("\n")
            .AppendFormat("transports: {0}\n", Transports == null ? "(null)" : string.Join(", ", Transports.Select(t => t.ToString())))
            .ToString());
 }
Beispiel #9
0
        public RegisterRequest GetRegistrationRequest(string accountName, string appId)
        {
            log.Info(">> getRegistrationRequest " + accountName);

            var challenge       = challengeGenerator.GenerateChallenge(accountName);
            var sessionData     = new EnrollSessionData(accountName, appId, challenge);
            var sessionId       = dataStore.StoreSessionData(sessionData);
            var challengeBase64 = WebSafeBase64Converter.ToBase64String(challenge);

            log.Info("-- Output --");
            log.Info("  sessionId: " + sessionId);
            log.Info("  challenge: " + challenge.ToHexString());
            log.Info("<< getRegistrationRequest " + accountName);

            return(new RegisterRequest(U2FConsts.U2Fv2, challengeBase64, appId, sessionId));
        }
        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));
        }
Beispiel #12
0
        public IList <SignRequest> GetSignRequests(string accountName, string appId)
        {
            log.Info(">> getSignRequest " + accountName);
            var securityKeyDataList = dataStore.GetSecurityKeyData(accountName);
            var result = new List <SignRequest>();

            foreach (var securityKeyData in securityKeyDataList)
            {
                var challenge   = challengeGenerator.GenerateChallenge(accountName);
                var sessionData = new SignSessionData(accountName, appId, challenge, securityKeyData.PublicKey);
                var sessionId   = dataStore.StoreSessionData(sessionData);
                var keyHandle   = securityKeyData.KeyHandle;
                log.Info("-- Output --");
                log.Info("  sessionId: " + sessionId);
                log.Info("  challenge: " + challenge.ToHexString());
                log.Info("  keyHandle: " + keyHandle.ToHexString());
                var challengeBase64 = WebSafeBase64Converter.ToBase64String(challenge);
                var keyHandleBase64 = WebSafeBase64Converter.ToBase64String(keyHandle);
                log.Info("<< getSignRequest " + accountName);
                result.Add(new SignRequest(U2FConsts.U2Fv2, challengeBase64, appId, keyHandleBase64, sessionId));
            }
            return(result);
        }
Beispiel #13
0
        /// <exception cref="U2FException" />
        private void VerifyBrowserData(JObject browserData, string messageType, EnrollSessionData sessionData)
        {
            // check that the right "typ" parameter is present in the browserdata JSON
            var typeProperty = browserData.Property(TYPE_PARAM);

            if (typeProperty == null)
            {
                throw new U2FException($"bad browserdata: missing '{TYPE_PARAM}' param");
            }
            var type = typeProperty.Value.ToString();

            if (messageType != type)
            {
                throw new U2FException("bad browserdata: bad type " + type);
            }

            var originProperty = browserData.Property(ORIGIN_PARAM);

            if (originProperty != null)
            {
                VerifyOrigin(originProperty.Value.ToString());
            }

            // check that the right challenge is in the browserdata
            var challengeProperty = browserData.Property(CHALLENGE_PARAM);

            if (challengeProperty == null)
            {
                throw new U2FException($"bad browserdata: missing '{CHALLENGE_PARAM}' param");
            }
            var challengeFromBrowserData = WebSafeBase64Converter.FromBase64String(challengeProperty.Value.ToString());

            if (!challengeFromBrowserData.SequenceEqual(sessionData.Challenge))
            {
                throw new U2FException("wrong challenge signed in browserdata");
            }
        }
Beispiel #14
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);
                }
            }
        }