通过更改签名来保护 HMAC 授权
secure HMAC authorization with changing signature
我有一个 Rails 应用程序,它提供 JSON API 由 python 脚本使用。安全性很重要,我一直在使用 HMAC 来做到这一点。 rails 应用程序和 python 脚本都知道密钥和他们用它加密的签名是 URL 和请求的正文。
我的问题是请求的签名不是每次都改变。如果它被拦截,那么攻击者可以使用相同的摘要发送完全相同的请求,我认为它会进行身份验证,尽管攻击者不知道密钥。
所以我想我需要在签名中包含请求的时间戳之类的东西 - 问题是我不知道如何在 python 和 ruby 中得到它。
这是我的 python 代码:
import hmac
import hashlib
import requests
fetch_path = url_base + '/phone_messages/pending'
fetch_body = '{}'
fetch_signature = fetch_path + ':' + fetch_body
fetch_hmac = hmac.new(api_key.encode('utf-8'), fetch_signature.encode('utf-8'), haslib.sha1).hexdigest()
这是我的 ruby 代码:
signature = "#{request.url}:#{request.body.to_json.to_s}"
hmac_digest = OpenSSL::HMAC.hexdigest('sha1', secret_key, signature)
Question: I need to have something like a timestamp of the request included in the signature
例如:
import hmac, hashlib, datetime
api_key = 'this is a key'
fetch_path = 'http://phone_messages/pending'
fetch_body = '{}'
fetch_data = fetch_path + ':' + fetch_body
for n in range(3):
fetch_signature = fetch_data + str(datetime.datetime.now().timestamp() )
fetch_hmac = hmac.new(api_key.encode('utf-8'), fetch_signature.encode('utf-8'), hashlib.sha1).hexdigest()
print("{}:{} {}".format(n, fetch_signature, fetch_hmac))
Output:
0:http://phone_messages/pending:{}1538660666.768066 cfa49feaeaf0cdc5ec8bcf1057446c425863e83a
1:http://phone_messages/pending:{}1538660666.768358 27d0a5a9f33345babf0c824f45837d3b8863741e
2:http://phone_messages/pending:{}1538660666.768458 67298ad0e9eb8bb629fce4454f092b74ba8d6c66
我建议在 security.stackexchange.com.
讨论 安全性
作为起点,请阅读:what-is-a-auth-key-in-the-security-of-the-computers
我通过将时间戳(自纪元以来的秒数)放在 post 请求的正文或 get 请求的参数中来解决这个问题。我只是简单地使用了时间戳作为编码的签名,这意味着 HMAC 哈希对于在不同秒内到来的每个请求都是不同的。
然后为了防止攻击者只使用以前看到的时间戳,我在服务器上验证了时间戳不超过当前时间之前 5 秒。
攻击者在拦截通信和发送攻击方面的周转速度非常快,但仍然可以通过,但我无法将超时降低到 5 秒以下,因为它已经让一些请求超时了。
既然整个事情都是在 SSL 下完成的,我认为它应该足够安全。
我有一个 Rails 应用程序,它提供 JSON API 由 python 脚本使用。安全性很重要,我一直在使用 HMAC 来做到这一点。 rails 应用程序和 python 脚本都知道密钥和他们用它加密的签名是 URL 和请求的正文。
我的问题是请求的签名不是每次都改变。如果它被拦截,那么攻击者可以使用相同的摘要发送完全相同的请求,我认为它会进行身份验证,尽管攻击者不知道密钥。
所以我想我需要在签名中包含请求的时间戳之类的东西 - 问题是我不知道如何在 python 和 ruby 中得到它。
这是我的 python 代码:
import hmac
import hashlib
import requests
fetch_path = url_base + '/phone_messages/pending'
fetch_body = '{}'
fetch_signature = fetch_path + ':' + fetch_body
fetch_hmac = hmac.new(api_key.encode('utf-8'), fetch_signature.encode('utf-8'), haslib.sha1).hexdigest()
这是我的 ruby 代码:
signature = "#{request.url}:#{request.body.to_json.to_s}"
hmac_digest = OpenSSL::HMAC.hexdigest('sha1', secret_key, signature)
Question: I need to have something like a timestamp of the request included in the signature
例如:
import hmac, hashlib, datetime
api_key = 'this is a key'
fetch_path = 'http://phone_messages/pending'
fetch_body = '{}'
fetch_data = fetch_path + ':' + fetch_body
for n in range(3):
fetch_signature = fetch_data + str(datetime.datetime.now().timestamp() )
fetch_hmac = hmac.new(api_key.encode('utf-8'), fetch_signature.encode('utf-8'), hashlib.sha1).hexdigest()
print("{}:{} {}".format(n, fetch_signature, fetch_hmac))
Output:
0:http://phone_messages/pending:{}1538660666.768066 cfa49feaeaf0cdc5ec8bcf1057446c425863e83a 1:http://phone_messages/pending:{}1538660666.768358 27d0a5a9f33345babf0c824f45837d3b8863741e 2:http://phone_messages/pending:{}1538660666.768458 67298ad0e9eb8bb629fce4454f092b74ba8d6c66
我建议在 security.stackexchange.com.
讨论 安全性
作为起点,请阅读:what-is-a-auth-key-in-the-security-of-the-computers
我通过将时间戳(自纪元以来的秒数)放在 post 请求的正文或 get 请求的参数中来解决这个问题。我只是简单地使用了时间戳作为编码的签名,这意味着 HMAC 哈希对于在不同秒内到来的每个请求都是不同的。
然后为了防止攻击者只使用以前看到的时间戳,我在服务器上验证了时间戳不超过当前时间之前 5 秒。
攻击者在拦截通信和发送攻击方面的周转速度非常快,但仍然可以通过,但我无法将超时降低到 5 秒以下,因为它已经让一些请求超时了。
既然整个事情都是在 SSL 下完成的,我认为它应该足够安全。