我想确保请求不能被伪造并发送到我的服务器。为了做到这一点,我需要在我的系统上为每个用户生成一个 API 密钥。密钥的目的是在客户端签署请求并在服务器上验证它们。
问题是,API 密钥通常由什么组成?它们只是一个加密安全的随机数(类似于密码盐)吗?或者它们背后是否有一些逻辑,例如它们是否应该由特定于用户的数据组成。
在我的系统中,每个用户已经有一个不公开的唯一 ID (GUID),我可以使用它作为我的“密钥”还是 API 密钥与用户 ID 不同?
我想确保请求不能被伪造并发送到我的服务器。为了做到这一点,我需要在我的系统上为每个用户生成一个 API 密钥。密钥的目的是在客户端签署请求并在服务器上验证它们。
问题是,API 密钥通常由什么组成?它们只是一个加密安全的随机数(类似于密码盐)吗?或者它们背后是否有一些逻辑,例如它们是否应该由特定于用户的数据组成。
在我的系统中,每个用户已经有一个不公开的唯一 ID (GUID),我可以使用它作为我的“密钥”还是 API 密钥与用户 ID 不同?
这取决于您想要分离角色的程度。
基本系统:您的“签名”是MAC。“API 密钥”是一个秘密值,在服务器和用户之间共享。像HMAC这样的普通 MAC 算法可以使用任意位序列作为密钥,因此可以通过使用/dev/urandom
(Linux, *BSD, MacOS X)、调用CryptGenRandom()
(Win32) 或使用java.security.SecureRandom
(Java) 轻松生成密钥。
增强系统:您的签名是真正的数字签名。如果您想将密钥生成器(谁可以生成将被服务器接受的密钥)与服务器本身(谁验证传入的签名)分开,这是有道理的。签名算法的密钥是具有大量内部结构的数学对象,每个算法都隐含着特定的密钥生成算法。使用已经实现所需位的库(例如OpenSSL)。
无论哪种方式,它不仅仅是密钥生成和签名。例如,您可能希望避免重放攻击:恶意的第三方监视网络,并记录由普通用户签名的有效请求。稍后,攻击者再次发送请求,并完成其签名,以复制效果。为了避免重放攻击,您必须添加某种外部协议,而这些事情很难做到(定义协议并不难;定义安全协议非常困难)。因此,明智的做法是重用现有的、经过严格审查的协议,在实践中,这意味着SSL/TLS。
使用 SSL,“基本系统”简化为在会话开始时在标头中发送 API 密钥(这正是 HTTPS 网站上的密码验证所发生的情况)。然后,“增强系统”是“带有客户端证书的 SSL”。