对于那些后来读到这篇文章的人:这是我正在做的一个业余爱好项目的一部分,那时我还不知道有一个叫 Let's Encrypt 的东西!另外,我不想购买 SSL 证书;所以我试图在没有 https 的情况下获得一些安全性。签名不会取代加密。如果你想做我想做的事,请不要。从 Let's Encrypt 获取证书。更简单、更安全!
我正在使用 Django 为移动应用程序实现网络服务。我决定使用 Hash-MAC 来验证请求(没有 Oath,没有 https),但挑战是我应该使用什么作为共享 key ?
首先我考虑使用用户密码,但它需要在服务器端数据库中以纯文本形式存储密码。我想到的另一个解决方案是在移动应用程序中对密码进行加盐和哈希处理,就像 Django auth 应用程序为了在客户端计算哈希密码所做的那样。
Django 使用什么作为盐?他们是“ secret ”的吗?将它们作为纯文本发送给用户有什么问题吗?一般来说,我们不必将盐作为“ secret ”来保密,但是 Django 可能会使用一些应该作为盐保密的东西,我不知道,这是关于 Django 如何实现的。
用户必须知道他们的盐值才能计算散列密码,因此服务器应该向他们提供。对手可以向所有用户索取盐分,最终他可以获得所有的盐分(即使某人在特定时间段内可以要求的次数有限制)。尽管盐不是 secret ,但我想知道“所有”盐可能很危险。 (或者我可能过于担心安全问题!)
请求格式:
HTTP request header:
x-mac-digest: 1d186b9c0fd5cd393f23623f0d167f7b17ac7d1cd74d8442647991d61e756c19
HTTP request body:
{
"username": "mjafar",
... rest of request in json
}
认证请求(简化):
hash_digest = request.META['HTTP_X_MAC_DIGEST']
request_body = request.body.decode('utf-8')
request_json = json.loads(request_body)
user = UserModel.objects.get(username=request_json['username'])
sharedKey = getSharedKey(user) # What should it return?
hash = hmac.new(sharedKey, request_body, hashlib.sha256).hexdigest()
if hash != hash_digest:
return HttpResponseBadRequest('MAC authentication failed')
请您参考如下方法:
HMAC 用于验证消息 block 。它用于验证密码/文本 block 在传输过程中未更改。您将需要使用非对称加密(RSA、DH 等)来传输您的共享 key 。
使用纯文本而不使用数字签名是没有用的。您将容易受到 MITM 攻击。除非你设法在没有互联网的情况下将共享 key 放在移动应用程序上(GSM SIM 卡在 sim 本身内部有共享 key ,它用于加密 GSM 调用)。
Django 使用随机函数生成它的 secret_key。 Linux 上的随机函数将调用/dev/urandom,在 Windows 上将调用与之等效的函数。
在您的情况下,创建一个 rest api 来创建用户名和密码,然后返回一个哈希值以用于访问您的 View 。
如果想计算自定义的hash值,可以调用make_password函数,直接保存在User的password属性中
阅读:https://docs.djangoproject.com/en/1.8/topics/auth/passwords/
示例:Django make_password too slow for creating large list of users programatically
