我想向客户端发送一些秘密数据,所以我想加密它。
我在客户端使用jCryption。它在连接开始时使用握手,程序如下:
我的问题是在发送用RSA加密的密码的步骤(步骤4),因为jCryption以十六进制格式发送,但是python-rsa期望二进制整数,
如何将jCryption输出转换为格式python-rsa可以处理,还是有另一个库可以做到?
RSA密文如下所示:
要\ xa75 [\ x9a \ x07s4 \ 86 \ XBC \ XAE \ XE3 \ xd5s)1 \ x0cd5 \ xdfY \ XF7 \ xeds9 \ XF3〜\ n \ x9fA $版权所有\ xA9 \ XFB; \ X04 \ X1E \ X18 \ XF4 \ XEA \ 0x7F部分\ X91 \ xd9 \ XB7 [\ XD3 \ X138 \ xb6b \ x9c \ XB6 \ X1B \ XE7 \ X11 \ x9aB \ X1D @`Y \ x9c0 \ xe8 \ XB6!\ x8b〜LG \ xabO \ xbeny \ xf7Xu \ x89YW \ XB0 \ XDA @ \ X10 \ X0C \ XE7 \ X85 \ x9bX \ X8F \ x02e \ xdalf | \ xa6 \ x0e \ x8e \ x8e \ x9d \ XD8 = \ x9bQLO7 \ x0fd \ X19 /]吨? \ XF1 \ X96 \ X1B \ xb9 \ x8bv \ XB4 \ xb4rS \ X1C \ xb9
从jCryption发送的数据如下所示:
11a6ebb863c379255df711aba86ad3986d6ecc33402a1596e6036b8d33f41932909a3e8c10cc4e0d2ece5f369808020ac7241a4285c80e6e483a1f6b43d933149961f50b72a808c769d39215ce08c33cfdb543b68bb0cf644f32dccf7eb90547290d47b96758449df3e7d4ec 2b50aef21ff4735c79f74bf5214ff356e4338ff2b292110ad537d160e41e34b350c7bc857601a943f915285e62f308fb6bd61d275321b68fbf27a52fbffc27b9ad15810795ccdea6d9776246b84b00503c2711d49a3f101af6f2c822d697a71aeca684e20328071ce84da907
答案 0 :(得分:0)
好的,我已经完成了这个任务,但首先我想说更容易获得https的LetsEncrypt免费证书我之后做的事情。
对于此解决方案,您需要安装openssl。
让我们的ajaxes写视图
获取公钥。如果我们在项目目录中没有,那么生成该对。
def public_key(req):
if not os.path.isfile(os.path.join(settings.BASE_DIR, 'form_key.pem')) or not os.path.isfile(os.path.join( settings.BASE_DIR,'form_key_pub.pem')):
check_call(['openssl', 'genrsa', '-out', os.path.join(settings.BASE_DIR,'form_key.pem'), '4096'])
check_call(['openssl', 'rsa', '-pubout', '-in', os.path.join(settings.BASE_DIR,'form_key.pem'), '-out', os.path.join(settings.BASE_DIR,'form_key_pub.pem')])
f = open(os.path.join(settings.BASE_DIR,'form_key_pub.pem'))
key = f.read()
f.close()
return JsonResponse({"publickey": key})
好的,握手。为了CSRF保护这个视图,我们需要修补jCryption javascript库,我没有。 我在这里将AES密钥保存在会话存储中。
@csrf_exempt
def handshake(req):
if req.method == 'POST':
encb64key = req.POST['key']
encb64key = re.sub(r'[^a-zA-Z0-9/=+]', '', encb64key)
enckey = b64decode(encb64key)
openssl = Popen(['openssl', 'rsautl', '-decrypt', '-inkey', os.path.join(settings.BASE_DIR,'form_key.pem')], stdin = PIPE, stdout=PIPE, stderr=PIPE)
key, stderr = openssl.communicate(enckey)
print stderr
key = re.sub(r'[^a-zA-Z0-9]', '', key)
req.session['form_key'] = key
openssl = Popen(['openssl', 'enc', '-aes-256-cbc', '-pass', 'pass:'+key, '-a', '-e'], stdin = PIPE, stdout = PIPE, stderr = PIPE)
enckey , stderr = openssl.communicate(key)
print stderr
enckey = re.sub('[^a-zA-Z0-9/+=]', '' , enckey)
return JsonResponse({'challenge': enckey})
raise Http404()
让我们为urls.py
中的视图选择网址 url('^pubkey', public_key, name = 'publickey'),
url('^handshake', handshake, name = 'handshake'),
最棘手的部分。我们自己的中间件。您需要将它添加到settings.py中的MIDDLEWARE_CLASSES。如果你把它放在你的myapp的views.py文件中,就像'myapp.views.JCryptionMiddleware'。
诀窍是我们只用'jCryption'attr发送错误的POST数据。中间件解密此attr中的适当数据,并使用它重写请求对象中的POST数据。 阅读Django文档中的中间件。
class JCryptionMiddleware(object):
def process_view(self, request, callback, callback_args, callback_kwargs):
jcryptedb64 = request.POST.get('jCryption', '')
if jcryptedb64:
try:
jcrypted = b64decode(jcryptedb64)
p = Popen(['openssl', 'enc', '-aes-256-cbc', '-pass', 'pass:'+request.session['form_key'], '-d'], stdin = PIPE, stdout = PIPE, stderr = PIPE)
qstr, stderr = p.communicate(jcrypted)
print stderr
wasmutable = request.POST._mutable
request.POST._mutable = True
request.POST.__init__(qstr)
request.POST._mutable = wasmutable
except Exception as e:
print e
return None
页面中的客户端代码包含表单模板。
<script src="{{ STATIC_URL }}js/jquery.min.js"></script>
<script src="{{ STATIC_URL }}js/jcryption.js"></script>
<script>
$(function() {
$('form').jCryption({"getKeysURL": "/pubkey", "handshakeURL": "/handshake"});
});
</script>
请参阅我们的urls.py网址。
例如,您可以加密管理员登录表单。将login.html从django contrib admin复制到templates / admin / login.html,并将此javascript代码添加到模板中。