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); }
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))); }
internal static FidoClientData CreateGoodClientData() { return(new FidoClientData { Challenge = WebSafeBase64Converter.ToBase64String(Encoding.Default.GetBytes("random challenge")), Origin = "http://localhost", Type = "type" }); }
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))); }
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()); }
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)); }
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); }
/// <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"); } }
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); } } }