2009-07-17 1 views
4

По умолчанию Ruby on Rails хранит данные сеанса в файлах cookie. Это имеет много преимуществ, таких как отсутствие необходимости в настройке любых уровней сохранения на стороне сервера. Однако данные сеанса не зашифрованы, а приложение Rails, которое я пишу, помещает потенциально конфиденциальные данные в сеанс. Я хотел бы избежать хранения серверных данных сеанса, если это возможно, и единственная существующая реализация зашифрованного хранилища файлов cookie для Rails, похоже, заброшена, поэтому я пишу свой собственный зашифрованный магазин cookie.Запись зашифрованного хранилища файлов cookie для Rails; мой подход безопасен?

рельсы печенья сессия магазин работает следующим образом:

  1. Он упорядочивает данные сеанса в строку байт.
  2. Сериализованные данные преобразуются в base64.
  3. Данные base64 добавляются HMAC. Rails требует, чтобы секретный ключ HMAC составлял не менее 30 байт; по умолчанию Rails генерирует 128-байтовую случайную строку в качестве секретного ключа, полученную из/dev/urandom. Алгоритмом хэширования по умолчанию, используемым для HMAC, является SHA-1.
  4. Данные base64 + HMAC отправляются клиенту HTTP в виде файла cookie.
  5. Когда клиент выполняет запрос, Rails сначала проверяет, прошла ли проверка HMAC. Если нет, то он будет молча отбрасывать данные сеанса в cookie, как если бы пользователь вообще не отправлял никаких данных сеанса. Это также означает, что если администратор изменяет секретный ключ HMAC, все старые сеансы автоматически становятся недействительными.
  6. Данные base64 де-base64'ed и unmarshalled в структуры данных Ruby.

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

  • Вставляет шаг 3.5: после шага 3 он будет шифровать данные.
  • Он изменяет шаг 5: перед проверкой HMAC он расшифровывает данные.
  • Алгоритм шифрования - AES-256 в режиме CFB. Я понимаю, что EBC будет подвергать повторяющиеся шаблоны.
  • Код требует, чтобы администратор задал ключ шифрования ровно 32 байта. Ключ шифрования не хеширован. По умолчанию он предлагает произвольно сгенерированный ключ шифрования ровно 32 байта, полученный из/dev/urandom.
  • Он также требует от администратора указать вектор инициализации ровно 16 байт. IV не хэшируется, и по умолчанию он предлагает случайное генерирование IV, полученное из/dev/urandom.

Причина, по которой я HMAC перед шифрованием (вместо HMAC после шифрования), заключается в том, что я хочу иметь возможность обнаруживать изменения ключа шифрования или IV. Я хочу, чтобы программное обеспечение автоматически аннулировало старые сессии, если был изменен ключ шифрования или IV. Если я HMAC после шифрования, то проверка HMAC будет проходить, если я изменю ключ шифрования или IV, что нежелательно.

Является ли мой подход безопасным? Если нет, то чего не хватает?

Несколько замечаний:

  • Я хочу использовать CTR, как это было рекомендовано http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html, но, к сожалению, OpenSSL (который входит в стандартную библиотеку Ruby) не поддерживает CTR, и я не хочу потребовать от моих пользователей установки отдельных сторонних криптографических библиотек.
  • Я хочу использовать SHA-256 для HMAC. daemonology.net рекомендует против SHA-512 из-за потенциальных «побочных атак на 32-битные системы» (что бы это ни значило). Однако SHA-256 как алгоритм хеширования для HMAC не поддерживается на каждой платформе. В частности, Ruby, поставляемый в OS X, не поддерживает HMAC + SHA256. Я хочу, чтобы мой код работал из коробки на OS X.

ответ

1

Я не уверен, что читаю вас на 100% правильно, но если да, то вам, кажется, не хватает смысла использовать IV. Кажется, вы планируете иметь секретный IV, который вы будете использовать для каждого файла cookie.

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

Кроме этого, я не вижу существенных недостатков. Это не означает, что они не существуют.

+0

Насколько я знаю, IV предназначен для семян для процесса рандомизации данных CFB.И да, нынешний подход сохраняет секрет IV, потому что нет необходимости раскрывать его. Ключ шифрования и IV используются для шифрования каждого файла cookie. Это не должно быть проблемой, не так ли? – Hongli

+0

@Hongli Я думаю, что oggy означает, что вы должны создать уникальный IV для каждого файла cookie и добавить его (незашифрованный) в этот файл cookie. – Inshallah

+0

@Hongli Ваш IV не должен генерироваться/dev/urandom, потому что это может привести к тому, что один и тот же IV используется для двух файлов cookie. – Inshallah

0

Как уже указывалось, вы должны создать уникальный IV и добавить его в каждый файл cookie. Чтобы создать уникальный IV,/dev/urandom недостаточно хорош, так как возможно, что он будет генерировать один и тот же IV для двух отдельных файлов cookie.

Хотя я не эксперт, я считаю, что один правильный метод генерации уникального IV - это шифрование счетчика, который увеличивается для каждого файла cookie с ключом, который не совпадает с ключом, используемым для шифрования файла cookie данные с.


Добавлено много позже:

Существует еще одна причина, которую я только думал позже, почему это не может быть такой хорошей идеей использовать/DEV/(и) случайным образом исключительно для капельницы в сценарий, обозначенный ОП. В manpage random (4) говорится, что пользователи должны быть экономичными в использовании/dev/urandom, или они могут ухудшить качество случайности для других пользователей устройства. Поскольку количество прочитанных данных пропорционально клиентским запросам, вы должны предположить, что в сценарии OP в конечном итоге будет считываться большое количество случайности.

Ключи-генераторы, вероятно, будут считывать из/dev/random, которые блокируют, но другие более законные пользователи этих устройств (более заинтересованные в случайности) будут деградировать в случайном порядке. Ну, не так хорошо блокировать генераторы ключей.

Итак, поскольку ОП не хочет зависеть от библиотек 3 участника так, что он может повторно использовать функции шифрования AES, используя их в режиме счетчика, как я изложил выше (также в wikipedia article under the heading Designs based on cryptographic primitives.

+1

Что значит вы говорите/dev/urandom не достаточно хорошо, так как «его возможно» генерировать те же 2 IV. Можете ли вы количественно определить его возможные фактические шансы? OpenSSL использует/dev/urandom по умолчанию, чтобы засеять его генератор случайных чисел. Так что, когда все в этом вопросе получают представление о том, что/dev/urandom не безопасно, это за меня ... – mox1

+0

@James: Я вижу, что/dev/urandom - это практический способ сделать это, и что это возможно * также очень безопасно. Тем не менее, существует концептуальная разница между криптографическим nonce и * очень * случайным числом (-ами). Оба они используют, и хотя криптографический nonce лучше всего подходит как IV, вы не захотите использовать его там, где необходимы * истинные * случайные числа (одинаковое число, которое никогда не появляется дважды, не очень случайное :). Вы сказали, что OpenSSL использует/dev/urandom для засеивания своего генератора случайных чисел, а не для того, чтобы использовать его как источник для своих IV; знаете ли вы, что OpenSSL фактически использует non-nonce IVs? – Inshallah

+1

@James на Linux,/dev/urandom не блокирует, но будет повторно использовать доступную энтропию в семени, тогда как/dev/random будет блокироваться до тех пор, пока пул энтропии не станет достаточно полным, чтобы создать больше байтов. В OSX алгоритм Yarrow не налагает такого ограничения за счет меньших случайных чисел по большим образцам данных (1 мб). – yonkeltron

1

OpenSSL не нуждается в отдельном режиме CTR. Чтобы реализовать режим CTR, вы храните счетчик размера блока и шифруете этот счетчик в режиме ECB. Затем вы XOR зашифрованный счетчик с блоком открытого текста и увеличиваете счетчик. (так что файл cookie должен содержать значение его начального счетчика). Вы должны never повторно использовать одно и то же значение счетчика с тем же ключом, поэтому убедитесь, что счетчик равен когда-либо сброс, если ключ является chan ВГО.

Смежные вопросы