客户端到C ++使用套接字进行服务器认证 [英] Client to Server Authentication in C++ using sockets

查看:143
本文介绍了客户端到C ++使用套接字进行服务器认证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为我的小型服务器 - 客户端程序实现登录/验证系统。我想知道如何解决这个问题,而且我一直希望从Stack Overflow中获得一些很棒的提示/建议。这是我想象的那样。

I'm implementing a login/authentication system for my little server-client program. I'm wondering how to go about this, and I was hoping to get some great tips/advice from Stack Overflow as always. This is how I imagine I'll do it.


  • 客户端连接到服务器。


  • 客户端返回用户名和sha1加密密码以及令牌。

  • 服务器接收它们并将用户认证为服务器端数据库中的凭据。

  • 令牌现在已被验证,用户使用令牌登录。 >
  • Client connects to the server.
  • Server sends a 'token' to the Client (based on time probably and whatever)
  • Client returns the username and a sha1 encrypted password, along with the token.
  • Server receives them and authenticates the user to the credentials in the server-side database.
  • The token is now verified and the user is signed in with the token.

这是一个安全的方式吗?我认为客户端还发送一个串行密钥或一些这样的字符串来形成一个串行/令牌对,这样另一个客户端就不能伪造相同的令牌(虽然令牌是由服务器端生成的)。

Is this at all a secure way of doing it? I figured the client also sends a serial key or some such to form a serial / token pair, so that another client cannot fake the same token (though the token is generated by the server-side).

执行细节不需要,因为我有能力执行。

Implementation details aren't required, as I am capable of doing the implementation.

我的问题将是两个问题:

My question would, rather, two questions:


  • 使用套接字实现登录/验证系统的方式有哪些?

  • 有什么方法来保护我的客户端到服务器的连接

  • 编辑:我忘记问,因为这是一个C ++问题,有没有可以帮助加密/认证的库?

  • What ways are there to achieve a login/authentication system with sockets
  • What ways are there to secure my client-to-server connection
  • EDIT: I forgot to ask, as this is a C++ question, are there any libraries that can assist in encryption/authentication?

安全是我的一个问题,所以我想确保我做的正确。

Security is an issue for me, so I want to be sure I do it right.

也许有一些背景信息。它是一个游戏服务器,一个人用他的帐户登录,并被带到一个大厅,在那里他可以选择一个世界服务器玩。世界服务器是在同一个网络中的不同机器上运行(可能)的一个单独的进程。

Maybe some background information. It's a game server, a person logs in with his account and is taken to a 'Lobby', where he can pick a 'World Server' to play on. The world server is a separate process running (possibly) on a different machine in the same network.

因此,我想在这个会话中有一个概念,用户登录并生成会话,登录服务器将会话中继到用户选择的世界服务器,以便世界服务器知道用户实际登录。

For that reason, I want to have a concept of a session in this, the user logs in and a session is generated, the login server relays the session to the world server the user picks, so that world server knows that the user is actually logged in.

我认为客户端将必须确认会话到世界服务器和所有这些,但是我稍后会担心。

I reckon the client will have to confirm the session to the world server and all that, but I'll worry about that later.

真诚的,
Jesse

推荐答案

您通常不要发送密码通过链接,甚至没有加密。通常的方法是一个挑战 - 响应协议。

You generally do not want to send the password over the link at all, not even with encryption. The usual method is a challenge-response protocol.


  1. 客户端连接到服务器,以用户名发送(但是

  2. 服务器通过发送唯一的随机数进行响应

  3. 客户端使用密码的哈希密码对该随机数进行加密作为密钥

  4. 客户端将加密的随机数发送到服务器

  5. 服务器使用用户密码的正确散列加密随机数

  6. 服务器比较两个加密的随机数字

  1. The client connects to the server, sending in the user-name (but not password)
  2. The server responds by sending out unique random number
  3. The client encrypts that random number using the hash of their password as the key
  4. The client sends the encrypted random number to the server
  5. The server encrypts the random number with the correct hash of the user's password
  6. The server compares the two encrypted random numbers

这有两个优点。首先,这意味着密码永远不会以任何形式出现在链接上。第二,它不受重播攻击的影响 - 如果攻击者记录对话,则无法重新登录客户端的回复,因为随机数将会更改。

This has a couple of advantages. First, it means the password never goes over the link in any form. Second, it's immune to a replay attack -- if an attacker records the conversation, they can't replay the client's replies later to log in, because the random number will have changed.

保护连接(即加密内容)有点简单。通常情况下,两者中的一个(不太重要)选择一个随机数,用另一个公钥加密,并将其发送给另一个。另一个解密它,并且它们使用它作为对称加密的密钥来加密会话的其余部分。

Securing the connection (i.e., encrypting the content) is a little simpler. Typically, one of the two (doesn't really matter much which) picks a random number, encrypts it with the other's public key, and sends it to the other. The other decrypts it, and they encrypt the rest of the session using that as a key for symmetric encryption.

库: Beecrypt OpenSSL 是几个明显的。除非你有一个相当具体的理由去做,否则TLS是你可能想要使用的(它比上面概述的还要多一些,包括双向身份验证,所以不仅服务器知道客户端是,但是客户端也知道服务器是谁,所以它被合理地验证,它没有连接到可能只是收集他的信用卡号码并运行的其他人)。

Libraries: Beecrypt and OpenSSL are a couple of obvious ones. Unless you have a fairly specific reason to do otherwise, TLS is what you probably want to use (it does quite a bit more than what I've outlined above, including two-way authentication, so not only does the server know who the client is, but the client also knows who the server is, so it's reasonably verified that it's not connected to somebody else who might just collect his credit card number and run with it).

编辑:

为了对每个数据包进行身份验证,无需加密所有内容,您可以执行以下操作:

To authenticate each packet without the overhead of encrypting everything, you could do something like this:


  1. 服务器发送其公钥询问

  2. 客户端生成一个随机数,用服务器的公钥加密,并将其发送回回复

  3. 该号码是用于反模式加密的第一个数字。

  4. 客户端包含一个计数器模式结果, li>
  1. The server sends its public key with the challenge
  2. The client generates a random number, encrypts it with the server's public key, and sends it back with its response
  3. The number is the first number used for counter-mode encryption
  4. The client includes one counter-mode result with each packet it sends

计数器模式意味着你只需生成连续的数字,并依次使用右键对每个数字进行加密。在这种情况下,密钥将是客户端密码的哈希值。这意味着每个数据包将包含客户端和服务器可以生成的唯一随机数,但没有其他可以。通过使用反模式加密,每个数据包将具有唯一的随机数。通过从一个随机数开始,每个会话将有一个唯一的随机数序列。

Counter mode means you just generate consecutive numbers, and encrypt each in turn, using the right key. In this case, the key would be the hash of the client's password. What this means is that each packet will contain a unique random number that both the client and the server can generate, but nobody else can. By using the counter-mode encryption, each packet will have a unique random number. By starting from a random number, each session will have a unique sequence of random numbers.

为了最大限度地减少开销,您可以只发送每个数据包的一部分结果 - 例如,如果在计数器模式下使用AES,则会为每个加密的数字生成16个字节的结果。每个数据包只包含(说)两个字节,所以你只需要每8个数据包加密一次。在理论上,这样做可以减少安全性 - 一个攻击者可以尝试一个数据包的65536个可能的值,但如果假设连接在(比如说)两次不好的尝试之后被破坏,那么攻击者得到正确值的机会变得相当小(当然,您可以通过控制您允许的不良尝试次数和每个数据包中包含的身份验证大小,几乎可以选择您愿意生活的机会)。

To minimize overhead, you could send just a part of the result with each packet -- e.g., if you use AES in counter mode, it'll generate 16 bytes of result for each number you encrypt. Include only (say) two bytes of that with each packet, so you only have to encrypt a number once every 8 packets. In theory, this cuts security -- an attacker could just try all 65536 possible values for a packet, but if you assume the connection has been compromised after (say) two bad attempts, the chances of an attacker getting the right value become pretty small (and, of course, you can pretty much pick the chances you're willing to live with by controlling the number of bad attempts you allow and the size of authentication you include in each packet).

这篇关于客户端到C ++使用套接字进行服务器认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆