Как заставить jCryption работать с django и python-rsa (или другой библиотекой python)

Я хочу отправить некоторые секретные данные клиенту, поэтому я хочу зашифровать их.

Я использую jCryption на стороне клиента. Он использует рукопожатие в начале соединения, процедуры происходят следующим образом:

  1. клиент генерирует случайный пароль AES.
  2. запрос клиента RSA publicKey сервер форм
  3. сервер отправь
  4. Клиент использует открытый ключ RSA для шифрования пароля и отправки его на сервер.
  5. Теперь оба используют этот пароль для шифрования данных, которые они посылают друг другу.

Моя проблема в том, чтобы отправить пароль, зашифрованный с помощью RSA (шаг 4), так как jCryption отправляет его в шестнадцатеричном формате, но python-rsa ожидает двоичное целое число,,

Как преобразовать вывод jCryption в формат, с которым может работать python-rsa, или есть другая библиотека, которая может это сделать?

зашифрованный текст RSA выглядит следующим образом:

К \xa75[\ X9a \ x07s4 \ x86 \ XBC \ XAE \ XE3\xd5s)1\x0cd5\xdfY\xf7\xeds9\xf3~\ п \x9fA$\xA9 \ XFB;\x04\x1e\x18\ XF4 \ хеа \x7f\x91\xd9\xb7[\ XD3 \ x138 \ xb6b \ x9c \ XB6 \ X1B \xe7\x11\x9aB\x1d@`у \ x9c0 \ X Е8 \ XB6!\x8b~ Л.Г. \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

1 ответ

Хорошо, я выполнил этот квест, но сначала хочу сказать, что гораздо проще получить бесплатный сертификат LetsEncrypt для https, что я и сделал позже.

Для этого решения вам нужно установить 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() 

Давайте выберем URL для просмотров в urls.py

    url('^pubkey', public_key, name = 'publickey'),
    url('^handshake', handshake, name = 'handshake'),

И самая сложная часть. Наше собственное промежуточное программное обеспечение. Вам нужно добавить его в MIDDLEWARE_CLASSES в settings.py. Что-то вроде "myapp.views.JCryptionMiddleware", если вы поместите его в файл views.py вашего приложения.

Хитрость в том, что мы отправляем неправильные данные POST только с атрибутом jCryption. Промежуточное программное обеспечение дешифрует соответствующие данные в этом атрибуте и перезаписывает вместе с ним данные 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>

Смотрите URL-адреса из нашего urls.py.

Например, вы можете зашифровать форму входа администратора. Скопируйте файл login.html из django contrib admin в templates / admin / login.html и добавьте этот код JavaScript в шаблон.

та да! Не используйте это, используйте HTTPS.

Другие вопросы по тегам