I want to send some secret data to the client, so I want to encrypt it.
I'm using jCryption in client side. It uses handshaking in the beginning of the connection, the procedures happen as follows:
My problem is in the step of sending the password encrypted with RSA (step 4), since jCryption sends it in hex format, but python-rsa expect binary integer ,,
How to convert the jCryption output to a format python-rsa can deal with, or is there are another library that can do it ?
the RSA ciphertext is look like this:
TO\\xa75[\\x9a\\x07s4\\x86\\xbc\\xae\\xe3\\xd5s)1\\x0cd5\\xdfY\\xf7\\xeds9\\xf3~\\n\\x9fA$\\xa9\\xfb;\\x04\\x1e\\x18\\xf4\\xea\\x7f\\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/]t?\\xf1\\x96\\x1b\\xb9\\x8bv\\xb4\\xb4rS\\x1c\\xb9
and data send from jCryption is looked like this:
11a6ebb863c379255df711aba86ad3986d6ecc33402a1596e6036b8d33f41932909a3e8c10cc4e0d2ece5f369808020ac7241a4285c80e6e483a1f6b43d933149961f50b72a808c769d39215ce08c33cfdb543b68bb0cf644f32dccf7eb90547290d47b96758449df3e7d4ec 2b50aef21ff4735c79f74bf5214ff356e4338ff2b292110ad537d160e41e34b350c7bc857601a943f915285e62f308fb6bd61d275321b68fbf27a52fbffc27b9ad15810795ccdea6d9776246b84b00503c2711d49a3f101af6f2c822d697a71aeca684e20328071ce84da907
Ok I've done this quest but first I want to say that it's much easier to obtain LetsEncrypt free cert for https what i did later.
For this solution you need openssl to be installed.
Lets write views for our ajaxes
Getting public key. If we don't have one in project directory then generate the pair.
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})
Ok, and the handshake. To CSRF protect this view we need to patch the jCryption javascript library what i didn't. I save AES key in session storage here.
@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()
Lets choose urls for the views in urls.py
url('^pubkey', public_key, name = 'publickey'),
url('^handshake', handshake, name = 'handshake'),
And the most tricky part. Our own middleware. You need to add it to MIDDLEWARE_CLASSES in settings.py . Something like 'myapp.views.JCryptionMiddleware' if you place it in your myapp's views.py file.
The trick is that we send the wrong POST data with only 'jCryption' attr. The middleware decrypts apropriate data in this attr and rewrites the POST data in the request object with it. Read about middlewares in Django documentation.
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
And the client code in the page with the form template.
<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>
See the urls from our urls.py .
For example you can encrypt your admin login form. Copy login.html from django contrib admin to templates/admin/login.html and add this javascript code to the template.
ta da! Don't use this, use HTTPS.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.