Что мне нужно, так это зашифровать строку, которая будет отображаться в 2D штрих-коде (PDF-417), чтобы, когда у кого-то появилась идея отсканировать, ничего не читалось.
Другие требования:
- не должно быть сложным
- он не должен состоять из RSA, инфраструктуры PKI, пар ключей и т. д.
Это должно быть достаточно просто, чтобы избавиться от людей, слоняющихся вокруг, и легко расшифровать для других компаний, заинтересованных в получении этих данных. Они звонят нам, мы говорим им стандарт или даем им какой-то простой ключ, который затем можно использовать для расшифровки.
Вероятно, эти компании могут использовать разные технологии, поэтому было бы хорошо придерживаться какого-то стандарта, который не привязан к какой-либо специальной платформе или технологии.
Что ты предлагаешь? Есть ли какой-то класс Java, выполняющий encrypt()
и decrypt()
без особых сложностей в достижении высоких стандартов безопасности?
источник
Ответы:
предисловие
Ниже я опишу основы безопасной симметричной криптографии и укажу на распространенные ошибки, которые я вижу в Интернете, когда люди самостоятельно внедряют криптографию со стандартной библиотекой Java. Если вы хотите просто пропустить все детали, перейдите в новую библиотеку Google. Импортируйте Tink в ваш проект и используйте режим AES-GCM для всех ваших шифрований, и вы будете в безопасности.
Теперь, если вы хотите узнать подробности о том, как зашифровать в Java, читайте дальше :)
Блочные шифры
Первым делом сначала нужно выбрать симметричный ключ Block Cipher. Блочный шифр - это компьютерная функция / программа, используемая для создания псевдослучайности. Псевдослучайность - это ложная случайность, которую ни один компьютер, кроме Квантового Компьютера, не сможет отличить от реальной случайности. Блочный шифр подобен строительному блоку для криптографии, и при использовании с различными режимами или схемами мы можем создавать шифрование.
Что касается алгоритмов блочного шифрования, доступных сегодня, убедитесь, что НИКОГДА , я повторяю, НИКОГДА не используйте DES , я бы даже сказал, НИКОГДА не используйте 3DES . Единственный блочный шифр, который даже в выпуске NSA Сноудена смог подтвердить, что он действительно настолько близок к псевдослучайному, насколько это возможно, - это AES 256 . Там также существует AES 128; Разница в том, что AES 256 работает в 256-битных блоках, а AES 128 работает в 128 блоках. В целом, AES 128 считается безопасным, хотя некоторые недостатки были обнаружены, но 256 настолько же надежен, насколько это возможно.
Забавный факт DES был взломан АНБ еще в то время, когда он был основан и фактически держал в секрете несколько лет. Хотя некоторые люди все еще утверждают, что 3DES безопасен, существует довольно много исследовательских работ, которые обнаружили и проанализировали слабые стороны 3DES .
Режимы шифрования
Шифрование создается, когда вы берете блочный шифр и используете определенную схему, так что случайность сочетается с ключом для создания чего-то, что является обратимым, пока вы знаете ключ. Это называется режимом шифрования.
Вот пример режима шифрования и простейшего режима, известного как ECB, чтобы вы могли визуально понять, что происходит:
Режимы шифрования, которые вы чаще всего видите в Интернете, следующие:
ECB CTR, CBC, GCM
Существуют и другие способы, помимо перечисленных, и исследователи всегда работают над новыми способами, чтобы улучшить существующие проблемы.
Теперь давайте перейдем к реализации и что является безопасным. НИКОГДА не используйте ECB, это плохо для сокрытия повторяющихся данных, как показал знаменитый пингвин Linux .
При реализации в Java обратите внимание, что если вы используете следующий код, режим ECB устанавливается по умолчанию:
... ОПАСНОСТЬ ЭТО УЯЗВИМОСТЬ! и, к сожалению, это видно по всему StackOverflow и онлайн в учебниках и примерах.
Одноразовые и IVs
В ответ на проблему, обнаруженную в режиме ECB, были созданы существительные, также известные как IV. Идея состоит в том, что мы генерируем новую случайную переменную и прикрепляем ее к каждому шифрованию, чтобы при шифровании двух одинаковых сообщений они получались разными. Красота этого заключается в том, что IV или nonce - это общедоступное знание. Это означает, что злоумышленник может получить доступ к этому, но пока у него нет вашего ключа, он ничего не может сделать с этим знанием.
Общие проблемы, которые я увижу, состоят в том, что люди будут устанавливать IV в качестве статического значения, такого же фиксированного значения в своем коде. И вот ловушка для IV в тот момент, когда вы повторяете одно, вы фактически подвергаете риску всю безопасность вашего шифрования.
Генерация случайного IV
Примечание: SHA1 не работает, но я не мог найти, как правильно внедрить SHA256 в этот вариант использования, поэтому, если кто-то захочет воспользоваться этим и обновить его, это будет здорово! Также атаки SHA1 все еще являются нетрадиционными, поскольку для взлома огромного кластера может потребоваться несколько лет. Проверьте детали здесь.
Реализация CTR
Для режима CTR заполнение не требуется.
Реализация CBC
Если вы решили реализовать режим CBC, сделайте это с PKCS7Padding следующим образом:
Уязвимость CBC и CTR и почему вы должны использовать GCM
Хотя некоторые другие режимы, такие как CBC и CTR, являются безопасными, они сталкиваются с проблемой, когда злоумышленник может перевернуть зашифрованные данные, изменив их значение при расшифровке. Допустим, вы зашифровали воображаемое банковское сообщение «Sell 100», ваше зашифрованное сообщение выглядит так: «eu23ng», злоумышленник меняет один бит на «eu53ng», и внезапно, когда расшифровывает ваше сообщение, оно читается как «Sell 900».
Чтобы избежать этого, большинство Интернета использует GCM, и каждый раз, когда вы видите HTTPS, они, вероятно, используют GCM. GCM подписывает зашифрованное сообщение с помощью хэша и проверяет, что сообщение не было изменено с использованием этой подписи.
Я бы избегал внедрения GCM из-за его сложности. Вам лучше использовать новую библиотеку Googles Tink, потому что здесь, если вы случайно повторили IV, вы скомпрометировали ключ в случае с GCM, который является основным недостатком безопасности. Новые исследователи работают над созданием IV устойчивых режимов повторного шифрования, где, даже если вы повторяете IV, ключ не находится в опасности, но это еще не стало массовым явлением.
Теперь, если вы хотите реализовать GCM, вот ссылка на хорошую реализацию GCM . Тем не менее, я не могу обеспечить безопасность или, если она правильно реализована, но она не работает. Также обратите внимание, что с GCM нет заполнения.
Ключи против паролей
Еще одно очень важное замечание: когда речь заходит о криптографии, ключ и пароль - это не одно и то же. Ключ в криптографии должен иметь определенную энтропию и случайность, чтобы считаться безопасным. Вот почему вы должны убедиться, что используете соответствующие криптографические библиотеки для генерации ключа для вас.
Таким образом, у вас действительно есть две реализации, которые вы можете сделать здесь, во-первых, использовать код, найденный в этом потоке StackOverflow, для генерации случайного ключа . Это решение использует безопасный генератор случайных чисел для создания ключа с нуля, который вы можете использовать.
Другой менее безопасный вариант - использовать пользовательский ввод, такой как пароль. Проблема, о которой мы говорили, заключается в том, что паролю не хватает энтропии, поэтому нам придется использовать PBKDF2 , алгоритм, который берет пароль и усиливает его. Вот реализация StackOverflow, которая мне понравилась . Однако в библиотеке Google Tink есть все это, и вы должны воспользоваться этим.
Разработчики Android
Один важный момент, на который следует обратить внимание, это то, что вы знаете, что ваш android-код работает в обратном порядке, и в большинстве случаев большинство java-кодов тоже. Это означает, что если вы храните пароль в виде обычного текста в вашем коде. Хакер может легко получить его. Обычно для такого типа шифрования вы хотите использовать асимметричную криптографию и так далее. Это выходит за рамки этого поста, поэтому я не буду вдаваться в подробности.
Интересное чтение с 2013 года : указывает, что 88% реализаций Crypto в Android было сделано неправильно.
Последние мысли
Еще раз я бы рекомендовал избегать реализации библиотеки java для crypto напрямую и использовать Google Tink , это избавит вас от головной боли, поскольку они действительно проделали хорошую работу по реализации всех алгоритмов должным образом. И даже тогда убедитесь, что вы проверили проблемы, поднятые на GitHub Tink, уязвимости всплывают здесь и там.
Если у вас есть какие-либо вопросы или отзывы, не стесняйтесь комментировать! Безопасность всегда меняется, и вам нужно делать все возможное, чтобы не отставать от нее :)
источник
getInstanceStrong()
методCipher
предпочтительнее, чем SHA1PRNGЯ бы рекомендовал использовать некоторые стандартные симметричные шифры, которые широко доступны, такие как DES , 3DES или AES . Хотя это не самый безопасный алгоритм, существует множество реализаций, и вам просто нужно дать ключ любому, кто должен расшифровать информацию в штрих-коде. javax.crypto.Cipher - это то, с чем вы хотите работать здесь.
Давайте предположим, что байты для шифрования находятся в
Далее вам понадобятся ключ и байты вектора инициализации
Теперь вы можете инициализировать шифр для выбранного вами алгоритма:
Шифрование будет выглядеть так:
И расшифровка, как это:
источник
DESede
алгоритм? Поскольку это популярный вопрос (и ответ), было бы стыдно поощрять людей использовать DES, поскольку шифр настолько слаб по современным стандартам.Я использую Sun Base64Encoder / Decoder, который можно найти в Sun JRE, чтобы избежать еще одного JAR в lib. Это опасно с точки зрения использования OpenJDK или какой-либо другой JRE. Кроме того, есть ли еще одна причина, по которой я должен рассмотреть возможность использования Apache commons lib с Encoder / Decoder?
источник
спасибо, я сделал этот класс, используя ваш код, может быть, кто-то найдет его полезным
объект шифратора
источник
Обновление от 12 декабря 2019 года
В отличие от некоторых других режимов, таких как CBC, режим GCM не требует, чтобы IV был непредсказуемым. Единственное требование заключается в том, что IV должен быть уникальным для каждого вызова с данным ключом. Если это повторяется один раз для данного ключа, безопасность может быть поставлена под угрозу. Простой способ добиться этого - использовать случайный IV от сильного генератора псевдослучайных чисел, как показано ниже.
Использование последовательности или метки времени в качестве IV также возможно, но это может быть не так тривиально, как может показаться. Например, если система неправильно отслеживает последовательности, уже использованные в качестве IV, в постоянном хранилище, вызов может повторить IV после перезагрузки системы. Точно так же нет идеальных часов. Компьютерные часы перенастраиваются и т. Д.
Кроме того, ключ должен поворачиваться после каждых 2 ^ 32 вызовов. Для получения дополнительной информации о требованиях IV, обратитесь к этому ответу и рекомендациям NIST .
Это код шифрования и дешифрования, который я только что написал в Java 8, учитывая следующие моменты. Надеюсь, кто-нибудь найдет это полезным:
Алгоритм шифрования : блочный шифр AES с 256-битным ключом считается достаточно безопасным. Чтобы зашифровать полное сообщение, необходимо выбрать режим. Рекомендуется использовать аутентифицированное шифрование (которое обеспечивает как конфиденциальность, так и целостность). GCM, CCM и EAX являются наиболее часто используемыми аутентифицированными режимами шифрования. GCM обычно предпочтительнее, и он хорошо работает в архитектурах Intel, которые предоставляют специальные инструкции для GCM. Все эти три режима являются режимами на основе CTR (счетчик) и, следовательно, они не требуют заполнения. В результате они не уязвимы для атак, связанных с отступами.
Вектор инициализации (IV) требуется для GCM. IV не секрет. Единственное требование - быть случайным или непредсказуемым. В Java
SecuredRandom
класс предназначен для создания криптографически сильных псевдослучайных чисел. Алгоритм генерации псевдослучайных чисел может быть указан вgetInstance()
методе. Однако, начиная с Java 8, рекомендуется использоватьgetInstanceStrong()
метод, который будет использовать самый сильный алгоритм, настроенный и предоставленныйProvider
NIST рекомендует 96-битный IV для GCM для обеспечения функциональной совместимости, эффективности и простоты конструкции
Чтобы обеспечить дополнительную безопасность, в следующей реализации
SecureRandom
выполняется повторное заполнение после создания каждых 2 ^ 16 байтов генерации псевдослучайных байтовПолучатель должен знать IV, чтобы иметь возможность расшифровать зашифрованный текст. Поэтому IV необходимо передать вместе с зашифрованным текстом. Некоторые реализации отправляют IV как AD (Associated Data), что означает, что тег аутентификации будет рассчитываться как для текста шифра, так и для IV. Однако это не обязательно. IV можно просто предварительно добавить к зашифрованному тексту, потому что если IV изменяется во время передачи из-за преднамеренной атаки или ошибки сети / файловой системы, проверка тега аутентификации все равно не удастся
Строки не должны использоваться для хранения открытого текста сообщения или ключа, поскольку строки являются неизменяемыми, и поэтому мы не можем их очистить после использования. Эти неочищенные строки задерживаются в памяти и могут появиться в дампе кучи. По той же причине клиент, вызывающий эти методы шифрования или дешифрования, должен очистить все переменные или массивы, содержащие сообщение или ключ, после того, как они больше не нужны.
Ни один провайдер не имеет жестко прописанного кода в соответствии с общими рекомендациями.
Наконец, для передачи по сети или хранилищу ключ или зашифрованный текст должны быть закодированы с использованием кодировки Base64. Подробности Base64 можно найти здесь . Подход Java 8 должен следовать
Байтовые массивы могут быть очищены с помощью:
Тем не менее, в Java 8 нет простого способа очистки,
SecretKeyspec
и,SecretKey
как представляется, реализации этих двух интерфейсов не реализовали методdestroy()
интерфейсаDestroyable
. В следующем коде написан отдельный метод для очисткиSecretKeySpec
иSecretKey
использования отражения.Ключ должен генерироваться с использованием одного из двух подходов, упомянутых ниже.
Обратите внимание, что ключи - это такие же секреты, как пароли, но в отличие от паролей, предназначенных для использования человеком, ключи предназначены для использования криптографическими алгоритмами и, следовательно, должны генерироваться только указанным выше способом.
Ключ шифрования может быть сгенерирован в основном двумя способами:
Без пароля
С паролем
Обновление на основе комментариев
Как указал @MaartenBodewes, мой ответ не справился ни с одним,
String
как того требует вопрос. Поэтому я попытаюсь восполнить этот пробел на тот случай, если кто-то наткнется на этот ответ и не решится с этим справитьсяString
.Как указывалось ранее в ответе, обработка конфиденциальной информации в a
String
, как правило, не очень хорошая идея, посколькуString
она неизменна, и поэтому мы не можем ее очистить после использования. И, как мы знаем, даже когда aString
не имеет сильной ссылки, сборщик мусора не сразу бросается удалять его из кучи. Таким образом,String
продолжает оставаться в памяти в течение неизвестного периода времени, даже если это не доступно для программы. Проблема в том, что дамп кучи в течение этого периода времени может раскрыть конфиденциальную информацию. Поэтому всегда лучше обрабатывать всю конфиденциальную информацию в байтовом массиве или массиве символов, а затем заполнять массив нулями, как только их цель будет достигнута.Тем не менее, со всеми этими знаниями, если мы до сих пор в конечном итоге в ситуации , когда секретная информация должна быть зашифрована в виде
String
, в первую очередь необходимо преобразовать его в массив байт и вызовencrypt
иdecrypt
функция , введенная выше. (Другой ключ ввода может быть сгенерирован с использованием приведенного выше фрагмента кода).А
String
можно преобразовать в байты следующим образом:Начиная с Java 8,
String
внутренне хранится в куче сUTF-16
кодировкой. Тем не менее, мы использовалиUTF-8
здесь, поскольку это обычно занимает меньше места, чемUTF-16
, особенно для символов ASCII.Аналогично, зашифрованный байтовый массив также может быть преобразован в строку, как показано ниже:
источник
String
использованием функций, созданных выше, будет тривиальным. Однако после второго взгляда после прочтения вашего комментария я понимаю, что это может быть неочевидно. Я обязательно отредактирую, чтобы добавить эти детали.Как насчет этого:
У меня отлично работает и довольно компактно.
источник
input.length <= secret.length
удерживается и неsecret
используется повторно, это безопасно и называетсяone-time-pad
. В случаяхinput.length > secret.length
это вариант шифра Vigenère и считается очень слабым.Вы можете использовать Jasypt
С Jasypt шифрование и проверка пароля могут быть такими простыми, как ...
Шифрование:
Дешифрирование:
Gradle:
Особенности:
источник
Jasypt
? Я не могу понять это с их сайта. Это неразличимо при атаках с открытым текстом? Целостность? Конфиденциальность?Вот моя реализация от meta64.com как Spring Singleton. Если вы хотите создать экземпляр Ciper для каждого вызова, который также будет работать, а затем вы можете удалить «синхронизированные» вызовы, но будьте осторожны, «Cipher» не является поточно-ориентированным.
источник
Здесь простое решение только с
java.*
иjavax.crypto.*
зависимостями для шифрования байтов, обеспечивающее конфиденциальность и целостность . Он должен быть неотличим при выбранной атаке открытым текстом для коротких сообщений порядка килобайт.Он использует
AES
вGCM
режиме без заполнения, ключ 128bit получается путемPBKDF2
с большим количеством итераций и статической солью из предоставленного пароля. Это гарантирует, что перебор паролей сложен и распределяет энтропию по всему ключу.Генерируется случайный вектор инициализации (IV), который будет добавлен к зашифрованному тексту. Кроме того, статический байт
0x01
добавляется как первый байт как «версия».Все сообщение отправляется в код аутентификации сообщения (MAC), сгенерированный
AES/GCM
.Вот и все, класс шифрования с нулевыми внешними зависимостями обеспечивает конфиденциальность и целостность :
Здесь весь проект с симпатичным CLI: https://github.com/trichner/tcrypt
Изменить: теперь с соответствующими
encryptString
иdecryptString
источник
encryptString
иdecryptString
:)Я хотел бы подумать об использовании чего-то вроде https://www.bouncycastle.org/ Это встроенная библиотека, которая позволяет вам шифровать все, что вам нравится, с использованием нескольких различных шифров. Я понимаю, что вы хотите защитить только от отслеживания, но если вы действительно хотите защитить информацию, использование Base64 на самом деле не защитит вас.
источник
Вот несколько ссылок, которые вы можете прочитать о том, что поддерживает Java
Шифрование / дешифрование потока данных.
JCERefGuide
Примеры шифрования Java
источник
Как уже говорили многие парни, вы должны использовать стандартный шифр, который используется слишком часто, как DES или AES.
Простой пример того, как вы можете зашифровать и расшифровать строку в Java с помощью AES .
источник
Вот решение для копирования / вставки. Я также рекомендую прочитать и проголосовать за ответ @ Konstantino, хотя он не содержит никакого кода. Вектор инициализации (IV) подобен соли - его не нужно хранить в секрете. Я новичок в GCM и, очевидно, AAD не является обязательным и используется только при определенных обстоятельствах. Установите ключ в переменной среды
SECRET_KEY_BASE
. Используйте что-то вроде KeePass для генерации 32-символьного пароля. Это решение смоделировано после моего решения на Ruby.Вот пример:
источник
Возможно, вы захотите использовать какой-нибудь автоматизированный инструмент для генерации кода шифрования / дешифрования, например. https://www.stringencrypt.com/java-encryption/
Он может генерировать разные коды шифрования и дешифрования каждый раз для шифрования строки или файла.
Это очень удобно, когда дело доходит до быстрого строкового шифрования без использования RSA, AES и т. Д.
Пример результатов:
Мы постоянно используем его в нашей компании.
источник
источник
источник