Почему криптомодуль Node ограничивает ключи и IV до 16 байтов? - PullRequest
0 голосов
/ 21 июня 2019

Итак, я писал простую программу командной строки для шифрования и дешифрования файлов с помощью встроенного в Node модуля crypto:

        if( deciphered_object.multibase_digest != null ){
            ciphered_object.multibase_digest = deciphered_object.multibase_digest;
            try{
                iv_buffer = Crypto.randomBytes(32);
                try{
                    cipher = Crypto.createCipheriv( 'aes-256-ofb', secret_keyobject, iv_buffer );
                    if( cipher != null && typeof(cipher) === 'object' ){
                        encrypted_buffer = cipher.update( deciphered_object.deciphered_data_buffer );
                        encrypted_buffer += cipher.final();
                        if( encrypted_buffer != null && Buffer.isBuffer(encrypted_buffer) === true ){
                            try{
                                ciphered_object.ciphered_data_buffer = Buffer.alloc( (1 + iv_buffer.length + encrypted_buffer.length) );
                                buffer_offset = ciphered_object.ciphered_data_buffer.writeUInt8( iv_buffer.length, 0 );
                                buffer_offset += iv_buffer.copy( ciphered_object.ciphered_data_buffer, buffer_offset );
                                buffer_offset += encrypted_buffer.copy( ciphered_object.ciphered_data_buffer, buffer_offset );
                                if( buffer_offset === ciphered_object.ciphered_data_buffer.length ){
                                    _return = [0, ciphered_object];
                                } else{
                                    _return = [-256, 'Error: "buffer_offset" is not equal to "ciphered_object.ciphered_data_buffer.length"'];
                                }
                            } catch(error){
                                _return = [-128, Utility.format('Buffer.alloc threw: %s', error)];
                            }
                        } else{
                            _return = [-64, 'Error: "ciphered_buffer" is either null or not a buffer.'];
                        }
                    } else{
                        _return = [-32, 'Error: "cipher" is either null or not an object.'];
                    }
                } catch(error){
                    _return = [-16, Utility.format('Crypto.createCipheriv threw: %s', error)];
                }
            } catch(error){
                _return = [-8, Utility.format('Crypto.randomBytes threw: %s', error)];
            }
        } else{
            _return = [-4, 'Error: "deciphered_object.multibase_digest" is either null or undefined.'];
        }

Однако, как я обнаружил при тестировании методом грубой силы, очевидно, createCipheriv принимает только длину ключа и IV ровно 16 байтов; против 32 байтов для IV и 4096 байтов для секретного ключа, полученного из Scrypt, я изначально планировал использовать:

        password = function_return[1];
        function_return = SaltFile.LoadSaltFile();
        if( function_return[0] === 0 ){
            try{
                scrypt_buffer = Crypto.scryptSync( password, function_return[1], 4096 );
                secret_keyobject = Crypto.createSecretKey( scrypt_buffer );
                if( secret_keyobject != null && typeof(secret_keyobject) === 'object' ){
                    _return = [0, secret_keyobject];
                } else{
                    _return = [-32, 'Error: "secret_keyobject" is either null or not an object.'];
                }
            } catch(error){
                _return = [-16,Utility.format('Crypto.scryptSync threw: %s', error)];
            }
        } else{
            _return = [function_return[0], 'SaltFile.LoadSaltFile: '+function_return[1]];
        }

Хуже всего то, что ни одно из этих ограничений размера не упоминается в документации для createCipheriv: https://nodejs.org/api/crypto.html#crypto_crypto_createcipheriv_algorithm_key_iv_options

Итак, на самом деле меня интересует, почему: почему эти произвольные ограничения? Зачем иметь криптографический пакет, который заставляет использовать смехотворно-слабые ключи, которые любой старый компьютер может перебить силой за считанные минуты? Почему эти оговорки не упомянуты в документации? Этот 16-байтовый предел ключа кажется мне настолько абсурдным, что делает весь модуль crypto бесполезным. Можно ли это обойти, используя другой алгоритм или что-то еще? Эти ограничения не имеют никакого смысла ....

Edit:

Ключи AES имеют размер 16, 24 и 32 байта, что составляет 128, 192 и 256 бит соответственно. IV всегда 16 байтов. Это спецификация AES. (@Jww)

Почему ключи RSA обычно 4096 бит (512 байт), но AES ограничен 32 байтами? Почему битовой энтропии 256 достаточно для AES, но не для RSA? Что делает ключи AES менее восприимчивыми к атакам методом перебора, чем ключ RSA?

Если вам нужен 32-байтовый iv, то вам нужно переключиться на Rijndael. (@Jww)

Но я думал, что AES - это Рейндаэль.

Совершенствование базовой симметричной криптографии может помочь вам определить, почему этот вопрос не имеет особого смысла. (@ Люк Джошуа Парк)

Действительно, не полезно; какое чтение по «базовой симметричной криптографии» мне следовало сделать, прежде чем задавать этот вопрос? Очевидно, что я не эксперт, и я не претендовал на это, но в том, что я прочитал о симметричной криптографии, не имеет смысла, что 128-битный ключ достаточно безопасен для AES, но не RSA. Если вы хотите, чтобы я перешел на RTFM, это нормально, но где это руководство, которое я должен был прочитать, прежде чем задавать этот вопрос? Я надеялся, что кто-нибудь сможет объяснить, почему размер ключа в 16 байт защищен, несмотря на то, что это не имеет особого интуитивного смысла.

1 Ответ

3 голосов
/ 21 июня 2019

Зачем нужен криптографический пакет, который заставляет использовать смехотворно слабые ключи, которые любой старый компьютер может перебить за считанные минуты?

Вы серьезно недооцениваете, насколько велико число 2 ^ 128. Если бы вы могли пробовать один триллион ключей в секунду, вам потребовалось бы 10-18 лет, чтобы попробовать все ключи, дать или взять. Вселенной меньше 14е9 лет. Вы видите проблему.

Ключи AES (или, в более общем смысле, все ключи для симметричных шифров) должны выбираться совершенно случайно. Один ключ так же хорош, как и другой, если источник случайности достаточно непредсказуем. Поэтому нет «умной» атаки на ключ. Это либо исчерпывающий поиск в пространстве ключей, либо атака на сам алгоритм (т. Е. Независимо от какого-либо ключа).

RSA - это совершенно другая история, а именно асимметричная криптография. Ключ не может быть выбран совершенно случайно. Это результат серии вычислений, которые начинаются с двух чисел, которые имеют определенные свойства . Это вычисление обратимо, по крайней мере, в принципе. В случае RSA это хорошо известная проблема факторизации (учитывая число найти все ее основные факторы). Выбранные числа должны быть достаточно большими, чтобы в течение разумного промежутка времени невозможна факторизация.

Таким образом, размеры ключей для AES и RSA несопоставимы, потому что AES и RSA - это очень разные криптографические алгоритмы, а виды атак на соответствующие ключи сильно различаются.

...