我试图设计一个小api但是我有点坚持如何保护api。我已经阅读了一些关于如何执行此操作的文章:登录并检索apikey然后使用此apikey散列一些值并将散列字符串与请求一起发回,因此可以在服务器级别再次完成。 / p>
这是一个好方法还是这样做很危险?
如果没有错过理解,为了避免中间的人,我可以将请求网址添加到将被散列的变量,或者不是合适的方式
此外,我的大脑仍然坚持如何使用时间戳来避免使用相同的数据向同一个网址发出大量请求。
对不起,如果我的问题被问了1000次。不过我现在已经阅读了一些文章,但我仍然不清楚我的小api会怎么样。
根据我的阅读和理解,这应该是方法。
对于hasing数据是一种创建哈希的好方法吗?
$l_sPrivateKey = 'something returned by database when user loged in';
$l_aData = array();
foreach($_POST as $key => $value){
if($key == 'signature') continue;
$l_aData[$key] = $value;
}
//This should then be the same as $_POST['signature'];
hash_hmac('sha256',serialize($l_aData),$l_sPrivateKey, false);
您的意见将不胜感激。 亲切的问候和提前谢谢
答案 0 :(得分:2)
以下假设您的API是浏览器到服务器,因此JavaScript-to-PHP不是仅使用PHP的服务器到服务器。 SRP将适用于这两种方案,但下面的答案讨论了浏览器到服务器库。
使用Secure Remote Password协议对API的用户进行身份验证,这会产生创建强会话密钥的副作用。然后,您可以使用共享强会话密钥使用HMAC对API请求和响应进行签名。
RFC5054使用SRP而不是公钥来创建共享会话密钥来加密TLS流量。有一个implementation in OpenSSL。这表明SRP身份验证是公钥创建安全共享密钥的绝对安全替代品。恕我直言,使用SRP更方便解决您的问题。
Thinbus SRP库是一个JavaScript SRP库,它有一个对PHP服务器进行身份验证的演示。 PHP演示没有使用共享会话密钥显示,但是一旦身份验证协议完成,它就只是服务器上的$srp->getSessionKey()
和浏览器中的client.getSessionKey()
。默认的Thinbus配置产生256位共享密钥。您可以将此与HMAC一起使用,请参阅下面的脚注1,了解如何使用签名的JSON。
注册流程为:
API使用流程将从客户端的SRP身份验证开始,该身份验证具有生成会话密钥的副作用。请注意,所有这些都在Thinbus演示代码中作为"标准用法"但这里解释的是介绍STP身份验证的工作原理。此身份验证协议显示在thinbus page的序列图中,并在联机演示中运行:
B
。 A
,然后使用密码,salt和两个一次性号码生成会话密钥K
,并使用两个一次性数字哈希创建一个密码证明M
,将其与随机A
一起发布到服务器。 K
,然后确认客户端发送的密码证明M
是好的。如果这一切都很好,它会将自己的证明M2
发送回客户端。此时,客户端已使用STP作为zero-knowledge proof密码进行了身份验证。 M2
。如果一切都很好,双方都有一个共享秘密K
,这是一个一次性的256位会话密钥,来自随机A
和B
,没有中间人可以切实可行知道。 以上所有内容都包含在Thinbus的PHP演示中,减去实际上在末尾调用$srp->getSessionKey()
以获得可用于使用HMAC签名的密钥。
让SRP用密码的零知识密码证明替换密码验证令人惊讶的是并非所有开发人员都默认使用它。它还为API签名生成共享会话密钥这一事实只是一个额外的好处。
脚注1: 大多数API都希望发布一个包含所有数据的JSON值。这是因为JSON很简单但功能更强大,在PHP和JavaScript中都内置了API,可以将对象转换为字符串并再次返回。正如@dbrumann在评论中指出的那样,签署JSON的标准是JWT。谷歌建议这里有PHP和JavaScript的库。因此,如果您升级为传递一个JSON输入值并为API中的每个命令返回一个JSON输出,则可以使用JWT库来签署和验证API的JSON输入和输出。其中一个JWS算法是" JWSAlgorithm.HS256 - HMAC与SHA-256,256+位密码"。这些库将理清实际签名和验证的机制,因此您不必编写该代码并担心可能存在的安全漏洞。
脚注2: Thinbus的建议是通过HTTPS将密码验证程序传输到服务器,以使验证者保密。这是为了防止拦截然后对密码验证程序进行离线字典攻击以恢复密码(即密码被加密到验证程序中,因此您需要通过验证程序生成代码运行16G crackstation password dictionary并使用用户salt来查找一场比赛)。使用API时,浏览器window.crypto API可以生成真正随机的" API密钥"。通常,Windows键是向用户显示的16个大写字母,格式为XXXX-XXXX-XXXX-XXXX。检查GRC password search space page它说一个随机的16字母大写密码,这个大小将需要政府14年才能彻底搜索。鉴于这种估计,您可以安全地通过普通HTTP传输为这么长的随机密码生成的密码验证程序,而无需加密,因为没有人可以通过验证器生成算法(使用随机数)运行如此多的密码猜测。客户端盐所以无法预先计算)找到匹配来恢复客户端API密码。