总而言之,保护密钥的最佳方法是不传输密钥。
也就是说,我们通常使用一种方案,其中每个“ API密钥”都有两个部分:非秘密ID(例如1234)和秘密密钥(例如byte [64])。
- 如果提供API密钥,请将其(加盐和散列)存储在服务的数据库中。
- 如果提供用户帐户(受密码保护),则将密码(加盐和散列)存储在服务的数据库中
现在,当消费者 首次 访问您的API进行连接时,请他
- 发送“用户名”参数(“ john.doe”不是秘密)
- 发送“ APIkeyID”参数(“ 1234”,不是秘密)
还给他
- 数据库中的盐(如果其中一个参数错误,只需返回一些可重复的盐-例如sha1(username +“ notverysecret”)。
- 服务器的时间戳
消费者应在会话期间存储盐,以使事情变得快速顺畅,并且他应计算并保持客户端与服务器之间的时间偏移。
消费者现在应该计算API密钥和密码的哈希值。这样,使用者就可以使用与存储在数据库中的密码和API密钥完全相同的哈希值,而不会遇到任何秘密问题。
现在,当消费者 subseqently 访问您的API,做实事,让他
- 发送“用户名”参数(“ john.doe”不是秘密)
- 发送“ APIkeyID”参数(“ 1234”,不是秘密)
- 发送“ RequestSalt”参数(字节[64],随机,不是秘密)
- 发送“ RequestTimestamp”参数(根据客户端时间和已知偏移量计算)
- 发送“ RequestToken”参数(哈希(密码哈希+ request_salt + request_timestamp + apikeyhash))
服务器不应接受过去超过2秒钟的时间戳记,以使其免受重放攻击的影响。
服务器现在可以计算与客户端相同的哈希(passwordhash + request_salt + request_timestamp +
apikeyhash),并确保
- 客户端知道API密钥,
- 客户知道正确的密码



