我对网址签名很感兴趣(例如http://.../?somearg=value&anotherarg=anothervalue&sig=aSKS9F3KL5xc),但我有一些要求让我没有解决方案。
PHP
或Python
页面,因此我需要能够使用其中一个签名并验证签名。somearg=value&anotherarg=anothervalue
)我的第一直觉是使用OpenSSL,例如使用RSA密钥对,按照以下方式执行以下操作:openssl rsautl -sign -inkey private.pem -in sensitive -out privsigned
并根据privsigned
数据和密钥进行验证:openssl rsautl -verify -inkey public.pem -in privsigned -pubin
。
使用PHP的openssl_get_privatekey()
和openssl_sign()
标记数据就好了,但我需要知道(解密的!)数据才能验证(我不会拥有):openssl_get_publickey()
和来自http://php.net/openssl_verify的openssl_verify($data, $signature, $pubkeyid);
。
或者我在这里遗漏了什么?
所以我调查了HMAC,但是虽然Python
和PHP
都提供了很多哈希函数,但我对于如何进行 验证<感到困惑/ em> 哈希。
PHP
的{{1}}允许我使用“密钥”(或者在本例中为字符串密钥)创建哈希。但是,我该如何验证散列是否有效(即hash_hmac()
并非由最终用户&sig=
手动输入。
总结一下(抱歉这个长问题):如何验证我的服务器(证书/字符串)密钥是否已经签名/哈希(假设我无法通过重做所述数据的哈希来验证) ?你对我应该选择哪条路线,Priv / pub-key或HMAC有什么偏好?
任何大小指针都非常感谢! 提前谢谢,
答案 0 :(得分:9)
正如Henning Makholm指出的那样,HMAC是比公钥更好的选择。您应该针对特定情况考虑一些最佳实践,这些实践会影响您的选择:
在计算签名时,您需要以URL友好的方式对其进行编码(base64和base32是流行的选择)并选择HMAC算法(例如SHA-256),并确定签名的位数你想保持(将HMAC值减半)通常是安全的。如果您选择base64,请注意url-safe与非url-safe实现使用的不同字母。
这是用于签名路径+查询字符串的伪代码实现(没有错误检查或腌制等):
const secret = ...;
def sign(path, querystring):
return path + "?" + querystring + "&sig=" + url_encode(base64_encode(hmacsha256(secret, path + "?" + querystring).truncate(16)))
def verify(path, querystring):
querystring_without_sig = remove_query_parameter(querystring, "sig")
sig = base64_decode(url_decode(get_query_parameter(querystring, "sig")))
if hmacsha256(secret, path + "?" + querystring_without_sig)[:16] != sig:
raise "invalid sig"
建议使用HMAC SHA256,并提供所有常用语言。
爪哇:
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secret);
return mac.doFinal(value.getBytes());
的Python:
hmac.new(secret, input, hashlib.sha256).digest()
PHP:
hash_hmac("sha256", value, secret);
答案 1 :(得分:5)
HMAC是一种对称算法,因此没有单独的创建和检查算法。要检查,您只需计算应该最初计算的哈希值,并检查结果是否等于您实际从客户端获得的值。安全性取决于仅存在于服务器上的HMAC密钥。
除非您需要不知道密钥的人可以验证签名,否则出于效率原因,HMAC可能是比公钥系统更好的选择。创建或验证公钥签名可能需要几毫秒(几年前,我每次操作时间为15毫秒,而一个实现时间为15毫秒),而HMAC则非常快。
(哦,你不能在不知道它应该签名的数据的情况下验证任何类型的签名。就我所见,这没有任何意义。)
答案 2 :(得分:0)
如果您想使用HMAC和Python,那么:
$ pip install ska
from ska import sign_url
signed_url = sign_url(
auth_user='user',
secret_key='your-secret_key',
url='http://e.com/api/'
)
生成的URL如下所示。
http://e.com/api/?valid_until=1378045287.0&auth_user=user&signature=YlZpLFsjUKBalL4x5trhkeEgqE8%3D
注意,下面以request.GET
为例给出了示例。它很可能与您框架中使用的内容不同(除非您使用Django)。
from ska import validate_signed_request_data
validation_result = validate_signed_request_data(
data = request.GET, # Note, that ``request.GET`` is given as example.
secret_key = 'your-secret_key'
)
validate_signed_request_data生成一个SignatureValidationResult对象,该对象基本上包含两个属性: