使用 Django 的 HMAC 身份验证 - 共享密钥

HMAC Authentication using Django - Shared Secret

对于那些后来读到这篇文章的人:这是我正在做的一个业余爱好项目的一部分,那时我还不知道有一个叫 Let's Encrypt 的东西!另外,我不想购买 SSL 证书;所以我试图在没有 https 的情况下获得一些安全性。签名不会取代加密。如果你想做我想做的事,请不要。从 Let's Encrypt 获取证书。更简单、更安全!


我正在使用 Django 为移动应用程序实施 Web 服务。我决定使用 Hash-MAC 来验证请求(没有 Oath,没有 https)但挑战是我应该使用什么作为共享密钥?

首先我考虑使用用户密码,但它需要在服务器端数据库中以纯文本形式存储密码。我想到的另一个解决方案是在移动应用程序中对密码进行加盐和哈希处理,就像 Django auth 应用程序为了在客户端计算哈希密码所做的那样。

  1. Django 使用什么作为盐?他们是"secret"吗?将它们作为纯文本发送给用户有什么问题吗?一般情况下,我们不必将盐保存为"secret",但是Django可能会使用一些应该保密的东西作为盐,我不知道,这是关于Django如何实现的。

  2. 用户必须知道他们的盐值才能计算散列密码,因此服务器应该向他们提供。对手可以向所有用户索取盐分,最终他可以获得所有的盐分(即使某人在特定时间段内可以要求的次数有限制)。尽管盐不是秘密,但我想知道其中的 "all" 可能很危险。 (或者我可能过于担心安全问题!)

请求格式:

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 用于验证消息块。它用于验证 cipher/Text 的块在传输过程中没有被更改。您将需要使用非对称加密(RSA、DH 等)来传输您的共享密钥。

使用纯文本而不使用数字签名是没有用的。您将容易受到 MITM 攻击。除非你设法在没有互联网的情况下将共享密钥放在移动应用程序上(GSM SIM 卡在 sim 本身内部有共享密钥,它用于加密 GSM 通话)。

Django 使用随机函数生成其 secret_key。 Linux 上的随机函数将调用 /dev/urandom,windows 上的随机函数将调用与之等效的函数。

在您的情况下,创建一个 rest api 以创建用户名和密码,然后 return 用于访问您的视图的哈希值。

如果要计算自定义哈希值,可以调用make_password函数,直接保存在User

的密码属性中

读这个:https://docs.djangoproject.com/en/1.8/topics/auth/passwords/

示例:Django make_password too slow for creating large list of users programatically