private async Task Process(EncryptStringRequest args) { SendCommand(new EncryptStringDone() { StringToEncrypt = args.StringToEncrypt, EncryptedString = RsaSignatures.Encrypt(args.StringToEncrypt, args.ServerPubKey) }); }
private async Task Process(SignStringRequest args) { SendCommand(new SignStringDone() { StringToSign = args.StringToSign, SignedString = RsaSignatures.Sign(args.StringToSign, args.PrivKey) }); }
public void TestRsaSignatures() { var keys = RsaSignatures.GenerateKeys(); Assert.AreNotEqual(keys.PrivKey, keys.PubKey); Assert.IsTrue(keys.PubKey.Length < keys.PrivKey.Length); var dataToSign = "some super secret data we need to sign"; var signature = RsaSignatures.Sign(dataToSign, keys.PrivKey); var resultOk = RsaSignatures.VerifySignature(dataToSign, signature, keys.PubKey); Assert.AreEqual(true, resultOk); var resultFail = RsaSignatures.VerifySignature(dataToSign + "modify", signature, keys.PubKey); Assert.AreEqual(false, resultFail); var dataToEncrypt = "some super secret data we need to encrypt"; var encrypted = RsaSignatures.Encrypt(dataToEncrypt, keys.PubKey); Assert.AreNotEqual(encrypted, dataToEncrypt); var decrypted = RsaSignatures.Decrypt(encrypted, keys.PrivKey); Assert.AreEqual(decrypted, dataToEncrypt); }
private async Task Process(GenerateKeysRequest args) { var keys = RsaSignatures.GenerateKeys(); SendCommand(new GenerateKeysDone() { PrivKey = keys.PrivKey, PubKey = keys.PubKey }); }
public LoginChecker(ZkLobbyServer server, string geoipPath) { this.server = server; geoIP = new DatabaseReader(Path.Combine(geoipPath, "GeoLite2-Country.mmdb"), FileAccessMode.Memory); var keys = RsaSignatures.GenerateKeys(); ServerPubKey = keys.PubKey; passwordDecryptor = new RsaSignatures(keys.PrivKey); }
public async Task <LoginCheckerResponse> DoLogin(Login login, string ip, List <ulong> dlc, string challengeToken) { var limit = MiscVar.ZklsMaxUsers; if (limit > 0 && server.ConnectedUsers.Count >= limit) { return(new LoginCheckerResponse(LoginResponse.Code.ServerFull)); } await semaphore.WaitAsync(); try { var userID = login.UserID; var installID = login.InstallID; var lobbyVersion = login.LobbyVersion; using (var db = new ZkDataContext()) { if (!VerifyIp(ip)) { return(new LoginCheckerResponse(LoginResponse.Code.BannedTooManyConnectionAttempts)); } if (!string.IsNullOrEmpty(login.ClientPubKey) || !string.IsNullOrEmpty(login.SignedChallengeToken)) { if (!RsaSignatures.VerifySignature(challengeToken, login.SignedChallengeToken, login.ClientPubKey)) { return(new LoginCheckerResponse(LoginResponse.Code.InvalidRsaSignature)); } } if (!string.IsNullOrEmpty(login.EncryptedPasswordHash)) { login.PasswordHash = passwordDecryptor.Decrypt(login.EncryptedPasswordHash); // a bit hacky but preserves other code } SteamWebApi.PlayerInfo info = null; if (!string.IsNullOrEmpty(login.SteamAuthToken)) { info = await server.SteamWebApi.VerifyAndGetAccountInformation(login.SteamAuthToken); if (info == null) { Trace.TraceWarning("Failed to verify steam token {0} for account {1}", login.SteamAuthToken, login.Name); // we ignore it and wait RSA check below } } Account accBySteamID = null; Account accByLogin = null; if (info != null) { accBySteamID = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.SteamID == info.steamid); } if (!string.IsNullOrEmpty(login.Name)) { accByLogin = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name == login.Name) ?? db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name.Equals(login.Name, StringComparison.CurrentCultureIgnoreCase)); } if (accBySteamID == null) { if (accByLogin == null) { LogIpFailure(ip); if (!string.IsNullOrEmpty(login.Name)) { return(new LoginCheckerResponse(LoginResponse.Code.InvalidName)); } else { return(new LoginCheckerResponse(LoginResponse.Code.SteamNotLinkedAndLoginMissing)); } } // here we have account by login, but no verified steam if (string.IsNullOrEmpty(login.PasswordHash)) // login attempted but with no password, check RSA signature { if (string.IsNullOrEmpty(accByLogin.LastPubKey) || accByLogin.LastPubKey != login.ClientPubKey) { return(new LoginCheckerResponse(LoginResponse.Code.RsaSignatureCouldNotBeVerified)); } } else if (!accByLogin.VerifyPassword(login.PasswordHash)) { LogIpFailure(ip); return(new LoginCheckerResponse(LoginResponse.Code.InvalidPassword)); } } var acc = accBySteamID ?? accByLogin; var ret = new LoginCheckerResponse(LoginResponse.Code.Ok); ret.LoginResponse.Name = acc.Name; var user = ret.User; acc.Country = ResolveCountry(ip); if ((acc.Country == null) || string.IsNullOrEmpty(acc.Country)) { acc.Country = "??"; } acc.LobbyVersion = lobbyVersion; acc.LastLogin = DateTime.UtcNow; acc.LastPubKey = login.ClientPubKey; if (info != null) { if (db.Accounts.Any(x => x.SteamID == info.steamid && x.Name != acc.Name)) { LogIpFailure(ip); return(new LoginCheckerResponse(LoginResponse.Code.SteamLinkedToDifferentAccount)); } acc.SteamID = info.steamid; acc.SteamName = info.personaname; } user.LobbyVersion = login.LobbyVersion; user.IpAddress = ip; acc.VerifyAndAddDlc(dlc); UpdateUserFromAccount(user, acc); LogIP(db, acc, ip); LogUserID(db, acc, userID, installID); if (String.IsNullOrEmpty(installID) && !acc.HasVpnException) { await server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format("{0} just logged in with an unsupported lobby https://zero-k.info/Users/AdminUserDetail/{1}", acc.Name, acc.AccountID)); } db.SaveChanges(); ret.LoginResponse.SessionToken = Guid.NewGuid().ToString(); // create session token var banPenalty = Punishment.GetActivePunishment(acc.AccountID, ip, userID, installID, x => x.BanLobby); if (banPenalty != null) { return (BlockLogin( $"Banned until {banPenalty.BanExpires} (match to {banPenalty.AccountByAccountID.Name}), reason: {banPenalty.Reason}", acc, ip, userID, installID)); } if (!acc.HasVpnException && GlobalConst.VpnCheckEnabled) { if (HasVpn(ip, acc, db)) { return(BlockLogin("Connection using proxy or VPN is not allowed! (You can ask for exception)", acc, ip, userID, installID)); } } return(ret); } } finally { semaphore.Release(); } }