Соль ключа для безопасного шифрования какао? - PullRequest
7 голосов
/ 05 сентября 2011

Я читал учебник о том, как подсолить ключ, чтобы сделать ваше шифрование безопасным, но не смог сделать большую его часть. Я мало знаю о криптографии, и мне нужна помощь. Я использую commoncrypto для шифрования файлов, и готово, за исключением того факта, что это не безопасно ...

Вот что у меня есть:

- (NSData *)AES256EncryptWithKey:(NSString *)key
{
   // 'key' should be 32 bytes for AES256, will be null-padded otherwise
   char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused)
   bzero( keyPtr, sizeof( keyPtr ) ); // fill with zeroes (for padding)

    NSLog(@"You are encrypting something...");

   // fetch key data
   [key getCString:keyPtr maxLength:sizeof( keyPtr ) encoding:NSUTF8StringEncoding];

   NSUInteger dataLength = [self length];

   //See the doc: For block ciphers, the output size will always be less than or 
   //equal to the input size plus the size of one block.
   //That's why we need to add the size of one block here
   size_t bufferSize = dataLength + kCCBlockSizeAES128;
   void *buffer = malloc( bufferSize );

   size_t numBytesEncrypted = 0;
   CCCryptorStatus cryptStatus = CCCrypt( kCCEncrypt, kCCAlgorithmAES128,     kCCOptionPKCS7Padding,
                                      keyPtr, kCCKeySizeAES256,
                                      NULL /* initialization vector (optional) */,
                                      [self bytes], dataLength, /* input */
                                      buffer, bufferSize, /* output */
                                      &numBytesEncrypted );
   if( cryptStatus == kCCSuccess )
   {
      //the returned NSData takes ownership of the buffer and will free it on deallocation
  return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];

   }

   free( buffer ); //free the buffer
   return nil;
}

Если бы кто-нибудь смог мне помочь и показать мне, как именно я буду применять соль, это было бы здорово! Еще раз спасибо!

Ответы [ 3 ]

15 голосов
/ 24 сентября 2011

dYhG9pQ1qyJfIxfs2guVoU7jr9oniR2GF8MbC9mi

Шифрование текста

Ака перемешивает, чтобы попытаться сделать его неразборчивым. Это игра, в которую вы играете в криптографии. Для этого вы используете детерминированные функции.

Шифрование включает использование функции, которая принимает два параметра: обычно короткий, фиксированной длины и произвольной длины. Он производит вывод того же размера, что и второй параметр.

Первый параметр мы называем ключом; второй - открытый текст; и вывод, зашифрованный текст.

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

Очевидно, что свойство хорошей функции шифрования состоит в том, что открытый текст не может быть легко определен из зашифрованного текста без знания ключа. Еще лучше будет создавать зашифрованный текст, который неотличим от случайного шума.

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

Проблема с детерминизмом

Все вышеперечисленное очень хорошо, но у нас есть проблема с нашими конечными целями неразборчивости при разработке реализаций этих функций: они детерминированы! Это бесполезно для получения случайного вывода.

Хотя мы можем разрабатывать функции, которые по-прежнему выдают очень случайный результат, благодаря путанице и диффузии , они все равно будут давать тот же результат при одинаковом входе. Нам обоим это нужно, и нам это не нравится. Мы никогда не сможем ничего расшифровать с помощью недетерминированной криптосистемы, но нам не нравятся повторяющиеся результаты! Повторяемое означает анализируемое ... определяемое (да). Мы не хотим, чтобы противник видел те же два зашифрованных текста и знал, что они поступили с одного и того же входа, который будет давать им информацию (и полезные методы взлома криптосистем, таких как радужные таблицы ). Как мы решаем эту проблему?

Ввод: некоторые случайные элементы вставляются в начало.

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

Как мне применить это знание?

OK. Таким образом, у каждого есть свое приложение, а внутри него - криптосистема, защищающая части приложения.

Теперь мы не хотим изобретать велосипед с помощью криптосистем (Worst. Idea. Ever.), Поэтому некоторые действительно знающие люди уже придумали хорошие компоненты, которые могут построить любую систему (например, AES, RSA, SHA2 , HMAC, PBKDF2). Но если все используют одни и те же компоненты, то это все равно вводит некоторую повторяемость! К счастью, если каждый использует разные ключи и уникальные начальные случайные входы в своих собственных криптосистемах, с ними все должно быть в порядке.

Хватит уже! Поговорим о реализации!

Давайте поговорим о вашем примере. Вы хотите сделать простое шифрование. Что мы хотим для этого? Ну, а) нам нужен хороший случайный ключ, и б) нам нужен хороший случайный IV. Это сделает наш зашифрованный текст максимально безопасным. Я вижу, что вы не предоставили случайную капельницу - лучше это сделать. Получите несколько байтов из случайного источника [secure / crypto] и добавьте его. Вы сохраняете / отправляете эти байты вместе с зашифрованным текстом. Да, это означает, что зашифрованный текст имеет постоянную длину, большую, чем открытый текст, но это небольшая цена.

А как насчет этого ключа? Иногда нам нужен запоминающийся ключ (например, пароль), а не хороший случайный ключ, который нравится компьютерам (если у вас есть возможность просто использовать случайный ключ - сделайте это вместо этого). Можем ли мы получить компромисс? Да! Должны ли мы преобразовывать пароли символов ASCII в байты для создания ключа? АД НЕТ!

Символы ASCII совсем не случайны (черт, они обычно используют только 6-7 бит из 8). Во всяком случае, то, что мы хотим сделать, это сделать наш ключ по крайней мере выглядеть случайным. как нам это сделать? Ну, хэширование хорошо для этого. Что если мы хотим повторно использовать наш ключ? Мы получим тот же хеш ... повторяемость снова!

К счастью, мы используем другую форму уникального случайного ввода - соль. Сделайте уникальную случайную соль и добавьте ее к своему ключу. Тогда хэш это. Затем используйте байты для шифрования ваших данных. Добавьте соль И IV вместе с вашим зашифрованным текстом, когда вы отправите его, и вы сможете расшифровать на конце.

Почти готово? НЕТ! Вы видите решение для хеширования, которое я описал в параграфе выше? Реальные криптографы назвали бы это любительским . Доверяете ли вы системе, которая является дилетантской? Нет! Собираюсь ли я обсуждать, почему это любительское? Нет, потому что тебе не нужно знать. По сути, он просто НЕ ДЕЙСТВИТЕЛЬНО СУПЕР-ЗАХВАТЕН на их вкус.

Что вам нужно знать, так это то, что они уже разработали лучшую систему для этой самой проблемы. Это называется PBKDF2 . Найдите его реализацию и [научитесь] использовать его вместо этого.

Теперь все ваши данные в безопасности.

1 голос
/ 20 сентября 2011

Как обычно используется случайная соль:

@ Ca1icoJack совершенно правильно сказал, что все, что вам нужно сделать, - это сгенерировать случайные данные и добавить их в конец. Данные обычно двоичные, а не буквенно-цифровые. Затем соль хранится в незашифрованном виде вместе с каждым хешированным паролем и объединяется с открытым парольным паролем пользователя для проверки хэша при каждом вводе пароля.

Какой смысл ОС, если он хранится в незашифрованном виде рядом с хешированным паролем?

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

Редактировать: Но я сказал, зашифрованный, а не хэшированный:

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

Несмотря на это, уловка заключается в для объединения соли и хранения ее вместе с каждым битом зашифрованных данных.

1 голос
/ 19 сентября 2011

Соление включает в себя добавление случайной строки в конец клавиши ввода.

Итак, сгенерируйте случайную строку некоторой длины:

Создайте случайную буквенно-цифровую строку в какао

А затем просто добавьте его к ключу, используя:

NSString *saltedKey = [key stringByAppendingString:salt];

Если в статье, которую вы читаете, соль не используется по-другому, это должно быть правильно.

...