delatbabel / apisecurity
API安全助手。
Requires
- php: >=5.4.0
Requires (Dev)
- phpunit/phpunit: ~4.0
Suggests
- illuminate/cache: Required to use the Laravel cache facade.
- illuminate/support: Required to use the Laravel cache facade.
This package is not auto-updated.
Last update: 2024-09-11 22:38:24 UTC
README
API安全助手是为API连接的安全设计的,通常用于REST或其他基于HTTP的API,其中认证过程通常涉及共享密钥,可能是一个公私钥对,而不是在Web应用中更常见的用户名/密码/cookie类型的安全。
最近更改
v1.0
首次稳定版本。
v1.1
增加了缓存和非ces的验证(服务器和客户端)。
v1.2
增加了一个新的密钥生成类来生成和存储共享密钥。现有的密钥类(用于处理公私钥对)已重命名为KeyPair -- 所以如果你直接使用该类,则应使用KeyPair而不是Key。
特性
- 构建加密非ces
- 构建公私钥对
- 签名API请求
- 验证API请求的签名
安装
composer require delatbabel/apisecurity
完成这些后,运行composer update命令
composer update
示例
简单的客户端或服务器端nonce生成
// Generate a nonce $nonce = new Nonce(); echo "Nonce is " . $nonce->getNonce() . "\n";
签名计算(客户端)
签名使用RSA密钥对。要生成签名,需要知道密钥对中的私钥。
$client = new Client(); // $private_key_data can be the file name of the private key or the text of the key itself. // This should be known only to the client. $client->setPrivateKey($private_key_data); $client->createSignature($request_data);
将生成并存储客户端nonce作为 $request_data['cnonce']
。将生成并存储签名作为 $request_data['sig']
。
HMAC计算(客户端)
HMAC使用共享密钥。
$client = new Client(); // $shared_key_data can be the file name of the shared key or the text of the key itself. // This should be known to both the client and server. $client->setSharedKey($shared_key_data); $client->createHMAC($request_data);
将生成并存储客户端nonce作为 $request_data['cnonce']
。将生成并存储HMAC作为 $request_data['hmac']
。
签名验证(服务器)
验证签名需要知道客户端的公钥。
$server = new Server(); // $public_key can be the file name of the client's public key or the text of the key itself. $server->setPublicKey($public_key); $server->verifySignature($request_data);
如果签名无效,将抛出SignatureException。
HMAC验证(服务器)
验证HMAC需要知道共享密钥。
$server = new Server(); // $shared_key can be the file name of the key or the text of the key itself. $server->setSharedKey($shared_key); $server->verifyHMAC($request_data);
如果HMAC无效,将抛出SignatureException。
服务器nonce生成(服务器)
这一步是可选的,并将特定请求与客户端的IP地址关联起来。这需要额外的API调用,如下所示
Client Server
| |
| Request server nonce |
| ---------------------------> |
| |
| Server nonce provided |
| <--------------------------- |
| |
| |
| API call including snonce |
| ---------------------------> |
| |
| Verify |
| |
| API response |
| <--------------------------- |
| |
在服务器端,可以使用实现\Delatbabel\ApiSecurity\Interfaces\CacheInterface的任何类来创建或验证nonce。在\Delatbabel\ApiSecurity\Implementations命名空间内提供了两个参考类
- LaravelCache -- 使用Laravel Cache外观进行添加/获取。
- MemcachedCache -- 使用PHP本机的Memcached类提供添加/获取。
要执行nonce验证,使用实现CacheInterface接口的对象初始化Server类,例如
$server = new Server(null, new MemcachedCache());
要创建nonce,这是正确的调用
$server->createNonce($ip_address);
$ip_address
是客户端的IP地址,例如来自$_SERVER数组或类似。
nonce验证(服务器)
在服务器端,nonce验证需要初始化服务器对象的缓存对象,如下面的nonce创建示例所示
$server = new Server(null, new MemcachedCache());
nonce验证规则如下
- 客户端nonce必须存在,并且从未被使用过。
- 服务器nonce可能存在。如果存在,它必须是为客户端的特定IP地址在服务器上创建的。
如果客户端nonce或服务器nonce无效,将抛出NonceException。
nonce验证在verifySignature
或verifyHMAC
调用期间自动发生。
适用的框架
- Laravel
- Yii
- Zend Framework
- Symfony
这需要一个相对较新的PHP版本,其中openssl库已编译或作为模块加载。
架构
我并未提供所有API安全功能的可能选项。例如,我无法生成DSA或DH密钥(PHP的openssl扩展尚不支持),默认密钥是2048位的RSA密钥(1024位密钥已被破解)。我没有提供所有可能的签名哈希算法——SHA256是推荐使用的。
另一个例子是在创建签名之前,会自动将客户端随机数添加到每个请求中——这可以防止两个具有相同数据的请求有相同的签名(从而导致拒绝服务攻击)。您可以选择不验证客户端随机数,但如果您这样做,它始终会存在。
这是为了提供最佳实践,而不是完全灵活的安全措施。
之所以这样做的原因是我看到太多API在安全方面存在限制或不足。例如,有一个用户名/密码对,并且将它们作为API数据的一部分以明文形式传递,这不是一个有效的安全解决方案。
需要关注的是实际可行性和最高安全性之间的平衡。理想情况下,应对每个API请求进行公钥加密,然而,进行这种加密所需的时间将开始变得显著。另一个选择是将数据密封(使用共享密钥加密,并在公钥加密的数据包中传递共享密钥),然而,这仍然有缺点,即它会破坏各种框架中期望在将数据传递到其他地方之前解析HTTP POST数据的HTTP处理库。
当然,仍然可以在POST体中加密或密封特别敏感的数据,但这可能是在未来版本中的一个练习。