将登录凭据发送到另一台服务器

时间:2014-06-14 21:51:23

标签: django encryption rsa pycrypto bytestring

我有两个运行django的服务器。我打电话给我的一台服务器"记录"服务器和另一个我的客户"服务器。客户端服务器希望通过在Internet上传递用户名,密码和消息来记录日志服务器的消息。在我当前的实现中,我尝试解密通过网络发送的加密消息,用户名和密码时遇到错误。看起来我应该尝试解密一个"字节字符串"根据pycrypto文档,但我似乎无法正确创建一个字节串,因为我还没有能够解决这个问题。此外,感觉就像我的实现让我陷入了安全漏洞和编解码器混淆的漏洞。是否有一个我应该看看的包已经实现了这种类型的功能?如果是这样,那个实现会是什么样的?

客户端:

from Crypto.Hash import MD5
from Crypto.PublicKey import RSA
from base64 import b64decode
import urllib2
import urllib

#I realize recreating the hash everytime is slow.  I just included it here for simplicity.
logger_public_signature_message = "I am a client :)"
logger_public_signature_hash = MD5.new(logger_public_signature_message).digest()

client_private_key = #private key
logger_public_key = #public key
client_private = RSA.importKey(client_private_key)
client_public = client_private.publickey()
logger_public = RSA.importKey(logger_public_key)

message = "my message"
username = "user"
password = "password"

encrypted_message = logger_public.encrypt(message, "ignored_param")
encrypted_username = logger_public.encrypt(username, "ignored_param")
encrypted_password = logger_public.encrypt(password, "ignored_param")
signature = client_private.sign(logger_public_signature_hash, '')

params = { "message": encrypted_message, "username": encrypted_username, "password": encrypted_password, "signature": signature }
url_encoded_params = urllib.urlencode(params)
url = 'http://localhost:8000/url/to/logger/'
req = urllib2.Request(url, url_encoded_params)

记录器:

from Crypto.Hash import MD5
from Crypto.PublicKey import RSA
from base64 import b64decode

def log(request):
    #I realize recreating the hash everytime is slow.  I just included it here for simplicity.
    logger_public_signature_message = "I am a client :)"
    logger_public_signature_hash = MD5.new(logger_public_signature_message).digest()

    client_public_key = #client public key
    logger_private_key = #logger private key
    client_public = RSA.importKey(client_public_key)
    logger_private = RSA.importKey(logger_private_key)

    p = request.POST

    encrypted_message = urllib2.unquote(p["message"])
    encrypted_username = urllib2.unquote(p["username"])
    encrypted_password = urllib2.unquote(p["password"])
    signature = urllib2.unquote(p["signature"])


    #I'm hitting exceptions when trying to decrypt the encrypted messages.
    #The exceptions are: "ValueError: Message too large"  I think the issue is that
    #I'm trying to decrypt a base64 string where I should be trying to decrypt a byte
    #string from reading the documentation.  But I haven't been able I guess to correctly
    #create a byte string because I can't get it to work.
    decrypted_message = logger_private.decrypt(encrypted_message.encode("base64"))
    decrypted_username = logger_private.decrypt(encrypted_username.encode("base64"))
    decrypted_password = logger_private.decrypt(encrypted_password.encode("base64"))
    verified = client_public.verify(logger_public_signature_hash, signature)

3 个答案:

答案 0 :(得分:4)

我认为你正在投入大量精力,不需要由Django处理。

以下是我通常会做的事情:

  1. 使用HTTPS作为传输加密层
  2. 使用HTTP Basic Auth。基本身份验证在urllib2以及requests
  3. 中实施

    但是有一个更好的解决方案:Django REST framework

    它为您提供了一个完整的REST API,包括不同的身份验证解决方案。

    如果您需要任何帮助,请设置其中一个选项,请告诉我,我会添加一个示例。

答案 1 :(得分:1)

是否可以使用sentry进行日志记录?当然,如果它不是训练任务。

我看看哨兵,因为它是django应用程序,现在它肯定是出色的生产就绪解决方案。 我们在银行业领域的软件开发中使用它。

答案 2 :(得分:1)

您非常接近解密服务器上的值。客户端加密的结果是一个元组。当你urllib2.unquote服务器上的项目时,你然后从它们重新创建元组。

例如:

>>> c = public.encrypt('Hello', "ignored")
>>> c
('3\xae0\x1f\xd7\xe4b\xd4\xf1\xf4\x88!Be\xff!\x1e\xda\x82\x10\x9bRy\x0c\xa0v\xed\x84\xf9\xe35\xc6QG\xcf\xb7\x1b\xea\x9fe\t\x9b\x8d\xd6\xf3\x8cw\xde\x17\xb5\xf7\x9a+\x84i%@\x8a\xdf\xf4\xdd\xc8wY',)

在你的代码中你打包成这样的参数:

>>> params = { "message" : c }
>>> params
{'message': ('3\xae0\x1f\xd7\xe4b\xd4\xf1\xf4\x88!Be\xff!\x1e\xda\x82\x10\x9bRy\x0c\xa0v\xed\x84\xf9\xe35\xc6QG\xcf\xb7\x1b\xea\x9fe\t\x9b\x8d\xd6\xf3\x8cw\xde\x17\xb5\xf7\x9a+\x84i%@\x8a\xdf\xf4\xdd\xc8wY',)}
>>> urllib.urlencode(params)
'message=%28%273%5Cxae0%5Cx1f%5Cxd7%5Cxe4b%5Cxd4%5Cxf1%5Cxf4%5Cx88%21Be%5Cxff%21%5Cx1e%5Cxda%5Cx82%5Cx10%5Cx9bRy%5Cx0c%5Cxa0v%5Cxed%5Cx84%5Cxf9%5Cxe35%5Cxc6QG%5Cxcf%5Cxb7%5Cx1b%5Cxea%5Cx9fe%5Ct%5Cx9b%5Cx8d%5Cxd6%5Cxf3%5Cx8cw%5Cxde%5Cx17%5Cxb5%5Cxf7%5Cx9a%2B%5Cx84i%25%40%5Cx8a%5Cxdf%5Cxf4%5Cxdd%5Cxc8wY%27%2C%29'

我猜想urllib2.unquote(p [" message"])会返回此信息(但我没试过):

"('3\\xae0\\x1f\\xd7\\xe4b\\xd4\\xf1\\xf4\\x88!Be\\xff!\\x1e\\xda\\x82\\x10\\x9bRy\\x0c\\xa0v\\xed\\x84\\xf9\\xe35\\xc6QG\\xcf\\xb7\\x1b\\xea\\x9fe\\t\\x9b\\x8d\\xd6\\xf3\\x8cw\\xde\\x17\\xb5\\xf7\\x9a+\\x84i%@\\x8a\\xdf\\xf4\\xdd\\xc8wY',)"

然后您可以像这样在服务器上重新创建元组(m是未加引号的消息):

>>> from ast import literal_eval
>>> literal_eval(m)
('3\xae0\x1f\xd7\xe4b\xd4\xf1\xf4\x88!Be\xff!\x1e\xda\x82\x10\x9bRy\x0c\xa0v\xed\x84\xf9\xe35\xc6QG\xcf\xb7\x1b\xea\x9fe\t\x9b\x8d\xd6\xf3\x8cw\xde\x17\xb5\xf7\x9a+\x84i%@\x8a\xdf\xf4\xdd\xc8wY',)

一旦你有了元组,你可以解密它:

>>> private.decrypt(literal_eval(m))
'Hello'

最好找一个经过审查的标准机制来做这件事,而不是自己动手。例如,在您的方案中,我可以在客户端和服务器之间捕获不同的消息,然后混合并匹配消息和用户名/密码对,使消息看起来来自不同的用户。

但是,只需要进行一次小调整(重新创建#34;未加引号和#34;字符串中的元组),您的代码就可以解密了。