34/SRPZMQ
- 状态:稳定
- 编辑:Diego Duclos diego.duclos@palmstonegames.com
本文档描述了 ZeroMQ 安全机制的一个扩展,使得客户端无需预先生成私钥即可进行身份验证。取而代之的是,密钥由服务器端预先生成的私钥(在某种注册过程中生成)和客户端的用户/密码组合生成。
另见:http://pythonhosted.org/srp/srp.html#srp-6a-protocol-description, http://srp.stanford.edu/。
Preamble
版权所有 (c) 2013 Palm Stone Games。
本规范是自由软件;您可以根据自由软件基金会发布的 GNU 通用公共许可证的条款重新分发和/或修改它;无论是许可证的第 3 版,还是(由您选择)任何更高版本。分发本规范是希望它有用,但没有任何担保;甚至没有对适销性或特定用途适用性的默示担保。有关更多详细信息,请参阅 GNU 通用公共许可证。您应该已经随程序收到了 GNU 通用公共许可证的副本;如果没有,请参阅 https://gnu.ac.cn/licenses。
本规范是一个自由开放标准,并受数字标准组织共识导向规范系统的管辖。
SRPZMQ 规范
SRPZMQ 是一种用于互联网上安全消息传递的协议,其方式与 CurveZMQ 非常相似。然而,它不是基于 curveCP,而是基于由斯坦福大学在http://srp.stanford.edu/ 指定的 SRP。
目标
其目标与 CurveZMQ 的目标非常相似,并有一些补充:客户端无需知道任何预共享密钥,用户在运行时输入的用户名/密码组合就足够了。
用户名和密码都必须能够是任意字节数组,以便用户自由选择他们易于记住的组合。
此外,攻击者即使设法获取了用户的密钥,也必须尽可能难以找到该用户的密码。
为何选择 SRP?
当选择一个合理快速的哈希算法和素数 N 时,SRP 有几个吸引人的有利因素,它既快速又非常安全,并且满足 curveZMQ 算法满足的所有安全目标。
总体设计
客户端与服务器建立连接,客户端将用户名以及生成的公共临时值(我们称之为 A)发送给服务器。
服务器使用盐(salt)以及挑战(我们称之为 B)回复,该挑战由预共享的大素数/模数组合、一个随机数以及服务器已知的客户端私钥生成。
使用这些信息,客户端和服务器都必须生成一个会话密钥,这只有在满足以下条件时才可能实现:
- 服务器必须知道对应于客户端使用的密码的私钥
- 客户端必须知道对应于私钥的密码。
如果不满足这两个条件,客户端和服务器将无法生成相同的会话密钥,并且身份验证将失败。
在两端生成会话密钥后,双方需要相互证明他们确实知道该密钥。
为此,客户端向服务器发送一个包含其 K 证明的数据包。此时,服务器知道客户端是它声称的身份,并且可以向客户端发送其自身的 K 证明,这将向客户端证明服务器确实是它们声称的身份。
完成此操作后,客户端和服务器都可以将会话密钥 K 用作进一步通信的对称加密密钥。由于会话密钥 K 基于随机的会话特定信息,因此将在会话结束时丢弃,并且绝不能重复使用。
需要注意的几个关键点
- 客户端和服务器都必须使用相同的大安全素数 N 和生成元 g
- 选择的素数 N 越大,算法的开销就越大,通过网络发送的值也越大,但蛮力破解的难度也越大。
- 必须选择适当大小的 N 值,以使得对服务器的拒绝服务攻击不切实际,并提供足够的安全性。
SRP 规范还包含一些强制性验证,如下所示:
- 如果客户端接收到 B == 0 (mod N) 或 u == 0,它将中止。
- 如果服务器检测到 A == 0 (mod N),它将中止。
- 客户端必须首先显示其 K 的证明。如果服务器检测到此证明不正确,则必须中止而不显示其自身的 K 证明。
详细信息
SRP 6a 中使用的主要变量
Variables Description
N A large, safe prime (N = 2q+1, where q is a Sophie Germain prime) All arithmetic is performed in the field of integers modulo N
g A generator modulo N
s Small salt for the verification key
I Username
p Cleartext password
H() One-way hash function
a,b Secret, random values
K Session key
SRP 6a 中使用的派生值
Derived Values Description
k = H(N,g) Multiplier Parameter
A = g^a Public ephemeral value
B = kv + g^b Public ephemeral value
x = H(s, H( I | ‘:’ | p )) Private key (as defined by RFC 5054)
v = g^x Password verifier
u = H(A,B) Random scrambling parameter
M = H(H(N) xor H(g), H(I), s, A, B, K) Session key verifier
选择的特定算法
目标是尽量减少用户配置的内容。然而,SRP 确实将一些事项留给了用户,即:使用的哈希算法、使用的大安全素数和生成元。
<待办:讨论选择哪个素数和哪个哈希算法>
高级语法
srpzmq = C:hello S:welcome C:proof-m S:proof-hamk
; HELLO command, xxx octets
hello = %d5 "HELLO" hello-version hello-A hello-username hello-padding
hello-version = %x1 %x0 ; SRPZMQ major-minor version
hello-A = 32OCTET ; public ephemereal value
hello-username = *OCTET ; Variable sized username in plaintext
hello-padding = *OCTET; Padding equal in size to the safe prime N / 8, zeros only. This is to prevent amplification attacks
; WELCOME command, xxx octets
welcome = %d7 "WELCOME" welcome-salt welcome-challenge
welcome-salt = *OCTET ; Randomly chosen salt value specific for this user. This value is typically 4 bytes, but larger salts may be chosen if one wants to make it harder to crack passwords from password verifiers.
welcome-challenge = *OCTET ; Variable sized challenge, depending on the picked random values, the size of the prime N and the chosen hash function.
; At this point, the client has to calculate the session key K and send its proof
; PROOF-M command, xxx octets
proof-m = %d7 "PROOF-M" proof
proof-m-proof = *OCTET ; Variable sized proof of K, length depends on the used hash function
; At this point, the server should calculate its own value of K and then verifies the proof from the client, if all is good, it sends a reply, otherwise, it closes the connection
; PROOF-HAMK command, xxx octets
proof-hamk = %d10 "PROOF-HAMK" proof
proof-hamk-proof = *OCTET ; Variable sized proof K, length depends on the user hash function