Как зашифровать в Node.js?

Я пытаюсь выполнить шифрование в Node.js 7.5.0, используя алгоритм «des-cbc». Согласно RFC 1423, для этого алгоритма требуется 64-битный криптографический ключ и 64-битный криптографический ключ. -битный вектор инициализации.

Я пытаюсь использовать ключ и iv, состоящий из 8 символов Latin-1; однако Node говорит: «Ошибка: недопустимая длина IV». Вот пример кода:

let crypto = require('crypto');

let key = '\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8',
     iv = '\xb8\xb7\xb6\xb5\xb4\xb3\xb2\xb1';

let cipher = crypto.createCipheriv('des-cbc', Buffer.from(key), Buffer.from(iv));

Если я изменю iv на 8 символов ASCII, то Node скажет: «Ошибка: неверная длина ключа»:

let crypto = require('crypto');

let key = '\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8',
     iv = 'abcdefgh';

let cipher = crypto.createCipheriv('des-cbc', Buffer.from(key), Buffer.from(iv));

Но если и ключ, и iv имеют 8 символов ASCII, это работает:

let crypto = require('crypto');

let key = 'hgfedcba',
     iv = 'abcdefgh';

let cipher = crypto.createCipheriv('des-cbc', Buffer.from(key), Buffer.from(iv));

Почему символы Latin-1 нельзя использовать для ключа и iv?


person Rob Johansen    schedule 01.04.2017    source источник
comment
Вероятно, вам следует использовать Buffer.from(key, "binary")   -  person Artjom B.    schedule 01.04.2017
comment
Не используйте DES, он небезопасен, был заменен AES, и использование AES по сути то же самое. Также DES не использует младший бит каждого байта, поэтому xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8 на самом деле \xb0\xb2\xb2\xb4\xb4\xb6\xb6\xb8.   -  person zaph    schedule 01.04.2017
comment
Или вы бы использовали массив: const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);. Я предполагаю, что текущий буфер интерпретируется как строка, а не двоичный массив (и я предполагаю, что Артем так и делает).   -  person Maarten Bodewes    schedule 01.04.2017
comment
@ArtjomB.: Спасибо, это было именно то, что мне было нужно. Если вы добавите, что это ответ, я отмечу его как принятый.   -  person Rob Johansen    schedule 01.04.2017


Ответы (1)


Решение

Вы должны либо использовать

Buffer.from('\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8', 'binary')

или даже чище, как указывает Маартен Бодевес

Buffer.from([0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8'])

То же самое касается вашего IV.

Причина

Buffer.from('\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8').length приводит к 16, что не является допустимой длиной для ключа DES. DES ожидает точно 64 бита или 8 байтов в качестве ключа. Именно поэтому DES очень небезопасен. Размер ключа просто слишком мал.

Причина, по которой указанный выше буфер имеет размер 16 байт вместо 8, заключается в том, что по умолчанию используется кодировка UTF-8. Если кодовая точка больше 127 (десятичная) или 0x7F (шестнадцатеричная), она будет кодироваться как минимум в два байта вместо одного. Каждая кодовая точка (символ) вашего ключа больше 0x7F. Итак, каждый из них кодируется двумя байтами.

О чем подумать

В настоящее время не используйте DES. Он обеспечивает только 56-битную безопасность. AES был бы намного лучше, потому что он более безопасен с наименьшим размером ключа 128 бит. Существует также практическое ограничение на максимальный размер зашифрованного текста с DES. См. Сравнение безопасности 3DES и AES.

IV должен быть непредсказуемым (читай: случайным). Не используйте статический IV, потому что это делает шифр детерминированным и, следовательно, небезопасным семантически. Злоумышленник, который наблюдает за зашифрованными текстами, может определить, когда тот же префикс сообщения был отправлен ранее. IV не является секретом, поэтому вы можете отправить его вместе с зашифрованным текстом. Обычно он просто добавляется к зашифрованному тексту и отсекается перед расшифровкой.

Ключ должен быть неотличим от случайного шума. Лучше всего просто сгенерировать его случайным образом и использовать в коде в закодированном виде.

Лучше аутентифицировать ваши зашифрованные тексты, чтобы такие атаки, как атака оракула заполнения, были невозможны. Это можно сделать с помощью режимов аутентификации, таких как GCM или EAX, или с помощью схемы зашифровать-затем-MAC.

person Artjom B.    schedule 01.04.2017