Python 使用Django共享秘密的HMAC身份验证

Python 使用Django共享秘密的HMAC身份验证,python,django,authentication,hmac,Python,Django,Authentication,Hmac,对于那些后来读到这篇文章的人来说:这是我正在做的一个爱好项目的一部分,而那时我还没有意识到有一个叫做Let's Encrypt的东西!另外,我不想购买SSL证书;因此,我试图在没有https的情况下获得一些安全性。签名不能取代加密。如果你想做我想做的事,不要。获取证书,让我们加密。它更容易,更安全 我正在为一个移动应用程序使用Django实现一个web服务。我决定使用哈希MAC来验证请求(没有誓言,没有https),但问题是我应该使用什么作为共享密钥 首先,我考虑使用用户的密码,但它需要在服务

对于那些后来读到这篇文章的人来说:这是我正在做的一个爱好项目的一部分,而那时我还没有意识到有一个叫做Let's Encrypt的东西!另外,我不想购买SSL证书;因此,我试图在没有https的情况下获得一些安全性。签名不能取代加密。如果你想做我想做的事,不要。获取证书,让我们加密。它更容易,更安全


我正在为一个移动应用程序使用Django实现一个web服务。我决定使用哈希MAC来验证请求(没有誓言,没有https),但问题是我应该使用什么作为共享密钥

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

  • Django用什么做盐?它们是“秘密”吗?将它们作为纯文本发送给用户是否有任何问题?一般来说,我们不必把盐作为“秘密”来保存,但Django可能会使用一些应该保密的东西作为盐,我不知道,这是关于Django如何实现的

  • 用户必须知道他们的密码才能计算散列密码,因此服务器应该向他们提供该密码。对手可以向所有用户索要盐分,最终他可以得到所有盐分(即使在特定时间段内有人索要盐分的次数限制)。虽然盐不是秘密,但我想知道“所有”盐可能是危险的。(或者可能我过于担心安全!)

  • 请求格式:

    HTTP request header:
    x-mac-digest: 1d186b9c0fd5cd393f23623f0d167f7b17ac7d1cd74d8442647991d61e756c19
    
    HTTP request body:
    {
      "username": "mjafar",
      ... rest of request in json
    }
    
    验证请求(简化):


    HMAC用于对消息块进行身份验证。它用于验证密码/文本块在传输过程中未更改。您需要使用非对称加密(RSA、DH等)来传输共享密钥

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

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

    在您的情况下,创建一个RESTAPI来创建用户名和密码,然后返回用于访问视图的哈希值

    如果要计算自定义哈希值,可以调用make_password函数,并将其直接保存在User中的password属性中

    请阅读以下内容:


    示例:

    还有,这里有什么问题,你想做什么?@Ahmed我正在尝试验证对web服务器的请求,而不发送密码或以明文形式访问令牌。发送到服务器的内容:(消息、用户名、哈希(消息| |密码))你首先要如何传输密码?@Ahmed这就是重点,由于用户和服务器都知道密码,因此不会进行任何传输。我想在客户端实现make_密码这回答了我的第一个问题(向上投票),如果你能回答第二个问题(甚至在评论中),这将非常有用。你可以通过DH传输salt,然后在客户端和服务器之间共享salt。但是,您需要了解,您的邮件将在网络中显示,如果您未使用数字签名,则可能会在传输salt时第一次执行MITM攻击。第一次在电话和服务器中传输salt。如果手机用户需要登录或在新手机上安装应用程序,请要求用户提交密码,然后用salt进行哈希运算,如果正确,则通过DH(不是DH,而是RSA)再次将salt发送回用户(如果您想再次使用旧的salt)。
    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')