Как шифровать String в Java

Мне нужно зашифровать строку, которая будет отображаться в 2D-штрих-коде (PDF-417), поэтому, когда кто-то получит представление о сканировании, он не получит ничего читаемого.

Другие требования:

  • не должно быть сложным
  • он не должен состоять из RSA, инфраструктуры PKI, пар ключей и т. д.

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

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

Что ты предлагаешь? Есть ли какой-нибудь Java-class, который делает encrypt () decrypt () без особых сложностей при достижении высоких стандартов безопасности?

Я бы рекомендовал использовать стандартный симметричный шифр, который широко доступен как DES , 3DES или AES . Хотя это не самый безопасный алгоритм, есть множество реализаций, и вам просто нужно предоставить ключ всем, кто должен расшифровать информацию в штрих-коде. javax.crypto.Cipher – это то, с чем вы хотите работать.

Предположим, что байты для шифрования находятся в

byte[] input; 

Затем вам понадобятся байты ключа и инициализации

 byte[] keyBytes; byte[] ivBytes; 

Теперь вы можете инициализировать шифр для выбранного вами алгоритма:

 // wrap key data in Key/IV specs to pass to cipher SecretKeySpec key = new SecretKeySpec(keyBytes, "DES"); IvParameterSpec ivSpec = new IvParameterSpec(ivBytes); // create the cipher with the algorithm you choose // see javadoc for Cipher class for more info, eg Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); 

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

 cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); byte[] encrypted= new byte[cipher.getOutputSize(input.length)]; int enc_len = cipher.update(input, 0, input.length, encrypted, 0); enc_len += cipher.doFinal(encrypted, enc_len); 

И расшифровка:

 cipher.init(Cipher.DECRYPT_MODE, key, ivSpec); byte[] decrypted = new byte[cipher.getOutputSize(enc_len)]; int dec_len = cipher.update(encrypted, 0, enc_len, decrypted, 0); dec_len += cipher.doFinal(decrypted, dec_len); 

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

Кроме того, обратите внимание, что для конкретной ситуации может быть обеспечена большая реализация, но зачем использовать ее и, возможно, случайно совершить ошибку? Используйте самые сильные инструменты, которые у вас есть, если у вас нет особых причин. В целом я очень советую использовать библиотеку и, если можно, избегать подробных подробностей.

ОБНОВЛЕНИЕ 4/5/18: я переписал некоторые части, чтобы упростить их понимание и изменить рекомендованную библиотеку от Jasypt до новой библиотеки Google Tink , я бы рекомендовал полностью удалить Jasypt из существующей установки.

предисловие

Я расскажу об основах безопасной симметричной криптографии ниже и укажу на распространенные ошибки, которые я вижу в Интернете, когда люди используют криптографию самостоятельно со стандартной библиотекой Java. Если вы хотите просто пропустить все детали, которые запускаются в новой библиотеке Google, импортируйте Tink в проект и используйте режим AES-GCM для всех ваших шифров, и вы должны быть в безопасности.

Теперь, если вы хотите узнать подробные подробные сведения о том, как шифровать в java, читайте дальше 🙂

Блочные шифры

Прежде всего вам нужно выбрать симметричный ключ Block Cipher. Блок-шифр – это компьютерная функция / программа, используемая для создания псевдо-случайности. Псевдо-случайность – это фальшивая случайность, что ни один компьютер, кроме квантового компьютера, не сможет отличить его от реальной случайности. Блок-шифр подобен строительному блоку для криптографии, а при использовании с различными режимами или схемами мы можем создавать шифровки.

Теперь о алгоритмах блочного шифрования, доступных сегодня, обязательно НИКОГДА , я НИКОГДА не использую DES , я бы даже сказал, что НИКОГДА не используйте 3DES . Единственный блок-шифр, который позволил даже релизу NSW Сноудена подтвердить, что он по-настоящему близок к Pseudo-Random, является AES 256 . Существует также AES 128, разница в AES 256 работает в 256-битных блоках, а AES 128 работает в 128 блоках. В целом AES 128 считается безопасным, хотя некоторые недостатки были обнаружены, но 256 так же прочно, как и получается.

Забавный факт DES был нарушен NSA назад, когда он был первоначально основан и фактически хранился в секрете на несколько лет, и хотя некоторые люди по-прежнему утверждают, что 3DES безопасен, существует немало исследовательских работ, которые нашли и проанализировали слабости в 3DES .

Режимы шифрования

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

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

Режим ECB

Режимы шифрования, которые вы увидите чаще всего в Интернете, следующие:

ЕЦБ CTR, CBC, GCM

Существуют другие режимы вне перечисленных, и исследователи всегда работают над новыми режимами для улучшения существующих проблем.

Теперь давайте перейдем к реализациям и тому, что безопасно. НИКОГДА не используйте ECB, это плохо, скрывая повторяющиеся данные, как показано знаменитым пингвином Linux . Пример Linux Penguin

При реализации на Java обратите внимание, что если вы используете следующий код, режим ECB устанавливается по умолчанию:

 Cipher cipher = Cipher.getInstance("AES"); 

… ОПАСНО ЭТО УЯЗВИМОСТЬ! и, к сожалению, это видно по всему StackOverflow и онлайн в учебниках и примерах.

Nonces и IVs

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

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

Создание случайного IV

 SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG"); byte[] iv = new byte[cipher.getBlockSize()]; randomSecureRandom.nextBytes(iv); IvParameterSpec ivParams = new IvParameterSpec(iv); 

Примечание: SHA1 сломан, но я не мог найти, как правильно использовать SHA256 в этом случае использования, поэтому, если кто-то хочет взломать это и обновить, это будет потрясающе! Кроме того, атаки SHA1 все еще нетрадиционны, так как это может занять несколько лет на огромном кластере. Ознакомьтесь с деталями здесь.

Внедрение CTR

Для режима CTR не требуется прокладка.

  Cipher cipher = Cipher.getInstance("AES/NoPadding"); 

Внедрение CBC

Если вы решите реализовать режим CBC, сделайте это с помощью PKCS7Padding следующим образом:

  Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); 

Уязвимость CBC и CTR и почему вы должны использовать GCM

Хотя некоторые другие режимы, такие как CBC и CTR, безопасны, они сталкиваются с проблемой, когда злоумышленник может переворачивать зашифрованные данные, изменяя их значение при расшифровке. Итак, допустим, вы зашифровали воображаемое банковское сообщение «Продать 100», ваше зашифрованное сообщение выглядит так: «eu23ng» злоумышленник меняет один бит на «eu53ng», и внезапно при расшифровке вашего сообщения он читается как «Продать 900».

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

Из-за его сложности я бы избегал реализации GCM. Вам лучше использовать новую библиотеку Googles Tink, потому что здесь, если вы случайно повторите IV, вы ставите под угрозу ключ в случае с GCM, что является основным недостатком безопасности. Новые исследователи работают над IV повторителями устойчивых режимов шифрования, где, даже если вы повторяете IV, ключ не находится в опасности, но это еще впереди.

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

 Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); 

Ключи против паролей

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

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

Другой менее надежный вариант – использовать пользовательский ввод, такой как пароль. Проблема, о которой мы говорили, заключается в том, что у пароля недостаточно энтропии, поэтому нам придется использовать PBKDF2 , алгоритм, который берет пароль и укрепляет его. Реализация StackOverflow мне понравилась . Однако библиотека Google Tink имеет все это, и вы должны воспользоваться ею.

Разработчики Android

Один из важных моментов, чтобы указать здесь, – это знать, что ваш код Android имеет обратную инженерию, и в большинстве случаев большинство java-кода тоже. Это означает, что если вы храните пароль в текстовом виде в своем коде. Хакер может легко получить его. Обычно для такого типа шифрования вы хотите использовать асимметричную криптографию и так далее. Это выходит за frameworks этого сообщения, поэтому я не буду погружаться в него.

Интересное чтение с 2013 года : указывает, что 88% реализаций Crypto в Android были выполнены ненадлежащим образом.

Последние мысли

Еще раз я бы предложил избегать реализации java-библиотеки для криптографии напрямую и использовать Google Tink , это избавит вас от головной боли, поскольку они действительно хорошо выполнили все алгоритмы. И даже тогда убедитесь, что вы проверяете проблемы, возникающие в ginkub Tink, всплывающие windows уязвимостей здесь и там.

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

Предупреждение

Не используйте это как какое-то измерение безопасности.

Механизм шифрования в этом сообщении представляет собой одноразовый блок, что означает, что секретный ключ может быть легко восстановлен злоумышленником с использованием 2 зашифрованных сообщений. XOR 2 зашифрованные сообщения, и вы получите ключ. Так просто!

Указанный Мусой


Я использую Sun Base64Encoder / Decoder, который можно найти в JRE Sun, чтобы избежать еще одного JAR в lib. Это опасно с точки зрения использования OpenJDK или JRE другого. Кроме того, есть ли еще одна причина, по которой я должен рассмотреть возможность использования Apache commons lib с Encoder / Decoder?

 public class EncryptUtils { public static final String DEFAULT_ENCODING = "UTF-8"; static BASE64Encoder enc = new BASE64Encoder(); static BASE64Decoder dec = new BASE64Decoder(); public static String base64encode(String text) { try { return enc.encode(text.getBytes(DEFAULT_ENCODING)); } catch (UnsupportedEncodingException e) { return null; } }//base64encode public static String base64decode(String text) { try { return new String(dec.decodeBuffer(text), DEFAULT_ENCODING); } catch (IOException e) { return null; } }//base64decode public static void main(String[] args) { String txt = "some text to be encrypted"; String key = "key phrase used for XOR-ing"; System.out.println(txt + " XOR-ed to: " + (txt = xorMessage(txt, key))); String encoded = base64encode(txt); System.out.println(" is encoded to: " + encoded + " and that is decoding to: " + (txt = base64decode(encoded))); System.out.print("XOR-ing back to original: " + xorMessage(txt, key)); } public static String xorMessage(String message, String key) { try { if (message == null || key == null) return null; char[] keys = key.toCharArray(); char[] mesg = message.toCharArray(); int ml = mesg.length; int kl = keys.length; char[] newmsg = new char[ml]; for (int i = 0; i < ml; i++) { newmsg[i] = (char)(mesg[i] ^ keys[i % kl]); }//for i return new String(newmsg); } catch (Exception e) { return null; } }//xorMessage }//class 

спасибо ive сделал этот class, используя ваш код, может быть, кто-то найдет его userfull

объект криптера

 import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.ShortBufferException; import javax.crypto.spec.DESKeySpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public class ObjectCrypter { private Cipher deCipher; private Cipher enCipher; private SecretKeySpec key; private IvParameterSpec ivSpec; public ObjectCrypter(byte[] keyBytes, byte[] ivBytes) { // wrap key data in Key/IV specs to pass to cipher ivSpec = new IvParameterSpec(ivBytes); // create the cipher with the algorithm you choose // see javadoc for Cipher class for more info, eg try { DESKeySpec dkey = new DESKeySpec(keyBytes); key = new SecretKeySpec(dkey.getKey(), "DES"); deCipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); enCipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchPaddingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvalidKeyException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public byte[] encrypt(Object obj) throws InvalidKeyException, InvalidAlgorithmParameterException, IOException, IllegalBlockSizeException, ShortBufferException, BadPaddingException { byte[] input = convertToByteArray(obj); enCipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); return enCipher.doFinal(input); // cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); // byte[] encypted = new byte[cipher.getOutputSize(input.length)]; // int enc_len = cipher.update(input, 0, input.length, encypted, 0); // enc_len += cipher.doFinal(encypted, enc_len); // return encypted; } public Object decrypt( byte[] encrypted) throws InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException, ClassNotFoundException { deCipher.init(Cipher.DECRYPT_MODE, key, ivSpec); return convertFromByteArray(deCipher.doFinal(encrypted)); } private Object convertFromByteArray(byte[] byteObject) throws IOException, ClassNotFoundException { ByteArrayInputStream bais; ObjectInputStream in; bais = new ByteArrayInputStream(byteObject); in = new ObjectInputStream(bais); Object o = in.readObject(); in.close(); return o; } private byte[] convertToByteArray(Object complexObject) throws IOException { ByteArrayOutputStream baos; ObjectOutputStream out; baos = new ByteArrayOutputStream(); out = new ObjectOutputStream(baos); out.writeObject(complexObject); out.close(); return baos.toByteArray(); } } 

Как насчет этого:

 private static byte[] xor(final byte[] input, final byte[] secret) { final byte[] output = new byte[input.length]; if (secret.length == 0) { throw new IllegalArgumentException("empty security key"); } int spos = 0; for (int pos = 0; pos < input.length; ++pos) { output[pos] = (byte) (input[pos] ^ secret[spos]); ++spos; if (spos >= secret.length) { spos = 0; } } return output; } 

Прекрасно подходит для меня и довольно компактен.

Вот моя реализация от meta64.com как Spring Singleton. Если вы хотите создать экземпляр ciper для каждого вызова, который будет работать, а затем вы можете удалить «синхронизированные» вызовы, но будьте осторожны, «шифр» не является streamобезопасным.

 import java.security.Key; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import javax.xml.bind.DatatypeConverter; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @Component @Scope("singleton") public class Encryptor { @Value("${aeskey}") private String keyStr; private Key aesKey = null; private Cipher cipher = null; synchronized private void init() throws Exception { if (keyStr == null || keyStr.length() != 16) { throw new Exception("bad aes key configured"); } if (aesKey == null) { aesKey = new SecretKeySpec(keyStr.getBytes(), "AES"); cipher = Cipher.getInstance("AES"); } } synchronized public String encrypt(String text) throws Exception { init(); cipher.init(Cipher.ENCRYPT_MODE, aesKey); return toHexString(cipher.doFinal(text.getBytes())); } synchronized public String decrypt(String text) throws Exception { init(); cipher.init(Cipher.DECRYPT_MODE, aesKey); return new String(cipher.doFinal(toByteArray(text))); } public static String toHexString(byte[] array) { return DatatypeConverter.printHexBinary(array); } public static byte[] toByteArray(String s) { return DatatypeConverter.parseHexBinary(s); } /* * DO NOT DELETE * * Use this commented code if you don't like using DatatypeConverter dependency */ // public static String toHexStringOld(byte[] bytes) { // StringBuilder sb = new StringBuilder(); // for (byte b : bytes) { // sb.append(String.format("%02X", b)); // } // return sb.toString(); // } // // public static byte[] toByteArrayOld(String s) { // int len = s.length(); // byte[] data = new byte[len / 2]; // for (int i = 0; i < len; i += 2) { // data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + // 1), 16)); // } // return data; // } } 

Я бы подумал об использовании чего-то вроде https://www.bouncycastle.org/ Это готовая библиотека, которая позволяет вам шифровать все, что вам нравится, с помощью множества разных шифров. Я понимаю, что вы только хотите защитить от отслеживания, но если вы действительно хотите защитить информацию, использование Base64 фактически не защитит вас.

Вот некоторые ссылки, которые вы можете прочитать, что поддерживает Java

Шифрование / дешифрование streamа данных.

В этом примере показано, как шифровать (используя симметричный алгоритм шифрования, такой как AES, Blowfish, RC2, 3DES и т. Д.) Большой объем данных. Данные передаются в кусках одному из методов шифрования: EncryptBytes, EncryptString, EncryptBytesENC или EncryptStringENC. (Имя метода указывает тип ввода (строковый или байтовый массив) и тип возврата (закодированная строка или массив байтов). Свойства FirstChunk и LastChunk используются для указания того, является ли кусок первым, средним или последним в streamе чтобы быть зашифрованным. По умолчанию оба FirstChunk и LastChunk равны true, а это означает, что данные переданы всей суммой.

JCERefGuide

Примеры шифрования Java

Вы можете использовать Jasypt

С помощью Jasypt шифрование и проверка пароля могут быть такими же простыми, как …

 StrongTextEncryptor textEncryptor = new StrongTextEncryptor(); textEncryptor.setPassword(myEncryptionPassword); 

Шифрование:

 String myEncryptedText = textEncryptor.encrypt(myText); 

Дешифрирование:

 String plainText = textEncryptor.decrypt(myEncryptedText); 

Gradle:

 compile group: 'org.jasypt', name: 'jasypt', version: '1.9.2' 

Особенности:

Jasypt предоставляет вам простые однонаправленные (дайджест) и двунаправленные методы шифрования.

Открытый API для использования с любым поставщиком JCE, а не только по умолчанию Java VM. Jasypt можно легко использовать с известными поставщиками, такими как Bouncy Castle. Выучить больше.

Повышенная безопасность паролей пользователей. Выучить больше.

Поддержка двоичного шифрования. Jasypt разрешает дайджест и шифрование двоичных файлов (байтовые массивы). Шифруйте ваши объекты или файлы при необходимости (например, для отправки по сети).

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

Полностью поточно-безопасный.

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

Включает легкую («облегченную») версию библиотеки для лучшей управляемости в средах с ограниченным размером, таких как мобильные платформы.

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

Hibernate 3 и 4 необязательная интеграция для сохранения полей ваших сопоставленных объектов в зашифрованном виде. Шифрование полей определяется в файлах сопоставления Hibernate и остается прозрачным для остальной части приложения (полезно для конфиденциальных персональных данных, баз данных со многими пользователями с включенной поддержкой чтения …). Шифровать тексты, двоичные файлы, числа, логические значения, даты … Подробнее.

Легко интегрируется в приложение Spring, с особыми функциями интеграции Spring 2, Spring 3.0 и Spring 3.1. Все дайджестеры и шифры в jasypt предназначены для легкого использования (инстанцированные, зависимые …) от Spring. И из-за того, что они являются streamобезопасными, их можно использовать без проблем синхронизации в одноэлементной среде, такой как Spring. Подробнее: Spring 2, Spring 3.0, Spring 3.1.

Spring Security (ранее Acegi Security) – дополнительная интеграция для выполнения шифрования паролей и сопоставления задач для системы безопасности, повышения безопасности паролей пользователей с использованием более безопасных механизмов шифрования паролей и обеспечения более высокой степени настройки и контроля. Выучить больше.

Предоставляет расширенные функции для шифрования всех или части файлов конфигурации приложения, включая конфиденциальную информацию, такую ​​как пароли базы данных. Плавно интегрируйте зашифрованную конфигурацию в простые приложения с поддержкой Spring и / или Hibernate. Выучить больше.

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

Интегрируется в Apache Wicket для более надежного шифрования URL-адресов в ваших защищенных приложениях.

Всеобъемлющие руководства и документацию javadoc, чтобы позволить разработчикам лучше понять, что они действительно делают с их данными.

Надежная поддержка кодировки, предназначенная для адекватного шифрования и переваривания текстов в зависимости от исходной кодировки. Полная поддержка языков, таких как японский, корейский, арабский … без кодирования или проблем с платформой.

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

Здесь простое решение с только java.* И javax.crypto.* Зависимостями для шифрования байтов, обеспечивающих конфиденциальность и целостность . Он должен быть неотличимым при выбранной атаке открытого текста .

Он использует AES в режиме GCM без дополнения, 128-битный ключ выведен PBKDF2 с большим количеством итераций и статической солью из предоставленного пароля. Это гарантирует, что грубые принудительные пароли будут сложными и распределяют энтропию по всему ключу.

Производится случайный вектор инициализации (IV) и будет добавлен к зашифрованному тексту. Кроме того, статический байт 0x01 добавляется в качестве первого байта как «версия».

Все сообщение переходит в код аутентификации сообщения (MAC), созданный AES/GCM .

Здесь идет нулевой class шифрования внешних зависимостей, обеспечивающий конфиденциальность и целостность :

 package cryptor; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; /** * This class implements AES-GCM symmetric key encryption with a PBKDF2 derived password. * It provides confidentiality and integrity of the plaintext. * * @created 2018-02-25 */ public class AesGcmCryptor { // https://crypto.stackexchange.com/questions/26783/ciphertext-and-tag-size-and-iv-transmission-with-aes-in-gcm-mode private static final byte VERSION_BYTE = 0x01; private static final int VERSION_BYTE_LENGTH = 1; private static final int AES_KEY_BITS_LENGTH = 128; private static final int GCM_IV_BYTES_LENGTH = 12; private static final int GCM_TAG_BYTES_LENGTH = 16; private static final int PBKDF2_ITERATIONS = 16384; private static final byte[] PBKDF2_SALT = hexStringToByteArray("4d3fe0d71d2abd2828e7a3196ea450d4"); /** * Decrypts an AES-GCM encrypted ciphertext and is * the reverse operation of {@link AesGcmCryptor#encrypt(char[], byte[])} * * @param password passphrase for decryption * @param ciphertext encrypted bytes * * @return plaintext bytes * * @throws NoSuchPaddingException * @throws NoSuchAlgorithmException * @throws NoSuchProviderException * @throws InvalidKeySpecException * @throws InvalidAlgorithmParameterException * @throws InvalidKeyException * @throws BadPaddingException * @throws IllegalBlockSizeException * @throws IllegalArgumentException if the length or format of the ciphertext is bad */ public byte[] decrypt(char[] password, byte[] ciphertext) throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, BadVersionException { // input validation if (ciphertext == null) { throw new IllegalArgumentException("Ciphertext cannot be null."); } if (ciphertext.length <= VERSION_BYTE_LENGTH + GCM_IV_BYTES_LENGTH + GCM_TAG_BYTES_LENGTH) { throw new IllegalArgumentException("Ciphertext too short."); } // the version must match, we don't decrypt other versions if (ciphertext[0] != VERSION_BYTE) { throw new BadVersionException(); } // input seems legit, lets decrypt and check integrity // derive key from password SecretKey key = deriveAesKey(password, PBKDF2_SALT, AES_KEY_BITS_LENGTH); // init cipher Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE"); GCMParameterSpec params = new GCMParameterSpec(GCM_TAG_BYTES_LENGTH * 8, ciphertext, VERSION_BYTE_LENGTH, GCM_IV_BYTES_LENGTH ); cipher.init(Cipher.DECRYPT_MODE, key, params); final int ciphertextOffset = VERSION_BYTE_LENGTH + GCM_IV_BYTES_LENGTH; // add version and IV to MAC cipher.updateAAD(ciphertext, 0, ciphertextOffset); // decipher and check MAC return cipher.doFinal(ciphertext, ciphertextOffset, ciphertext.length - ciphertextOffset); } /** * Encrypts a plaintext with a password. * * The encryption provides the following security properties: * Confidentiality + Integrity * * This is achieved my using the AES-GCM AEAD blockmode with a randomized IV. * * The tag is calculated over the version byte, the IV as well as the ciphertext. * * Finally the encrypted bytes have the following structure: * 
 * +-------------------------------------------------------------------+ * | | | | | * | version | IV bytes | ciphertext bytes | tag | * | | | | | * +-------------------------------------------------------------------+ * Length: 1B 12B len(plaintext) bytes 16B * 

* Note: There is no padding required for AES-GCM, but this also implies that * the exact plaintext length is revealed. * * @param password password to use for encryption * @param plaintext plaintext to encrypt * * @throws NoSuchAlgorithmException * @throws NoSuchProviderException * @throws NoSuchPaddingException * @throws InvalidAlgorithmParameterException * @throws InvalidKeyException * @throws BadPaddingException * @throws IllegalBlockSizeException * @throws InvalidKeySpecException */ public byte[] encrypt(char[] password, byte[] plaintext) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidKeySpecException { // initialise random and generate IV (initialisation vector) SecretKey key = deriveAesKey(password, PBKDF2_SALT, AES_KEY_BITS_LENGTH); final byte[] iv = new byte[GCM_IV_BYTES_LENGTH]; SecureRandom random = SecureRandom.getInstanceStrong(); random.nextBytes(iv); // encrypt Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE"); GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_BYTES_LENGTH * 8, iv); cipher.init(Cipher.ENCRYPT_MODE, key, spec); // add IV to MAC final byte[] versionBytes = new byte[] { VERSION_BYTE }; cipher.updateAAD(versionBytes); cipher.updateAAD(iv); // encrypt and MAC plaintext byte[] ciphertext = cipher.doFinal(plaintext); // prepend VERSION and IV to ciphertext byte[] encrypted = new byte[1 + GCM_IV_BYTES_LENGTH + ciphertext.length]; int pos = 0; System.arraycopy(versionBytes, 0, encrypted, 0, VERSION_BYTE_LENGTH); pos += VERSION_BYTE_LENGTH; System.arraycopy(iv, 0, encrypted, pos, iv.length); pos += iv.length; System.arraycopy(ciphertext, 0, encrypted, pos, ciphertext.length); return encrypted; } /** * We derive a fixed length AES key with uniform entropy from a provided * passphrase. This is done with PBKDF2/HMAC256 with a fixed count * of iterations and a provided salt. * * @param password passphrase to derive key from * @param salt salt for PBKDF2 if possible use a per-key salt, alternatively * a random constant salt is better than no salt. * @param keyLen number of key bits to output * * @return a SecretKey for AES derived from a passphrase * * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ private SecretKey deriveAesKey(char[] password, byte[] salt, int keyLen) throws NoSuchAlgorithmException, InvalidKeySpecException { if (password == null || salt == null || keyLen <= 0) { throw new IllegalArgumentException(); } SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); KeySpec spec = new PBEKeySpec(password, salt, PBKDF2_ITERATIONS, keyLen); SecretKey pbeKey = factory.generateSecret(spec); return new SecretKeySpec(pbeKey.getEncoded(), "AES"); } /** * Helper to convert hex strings to bytes. * * May be used to read bytes from constants. */ private static byte[] hexStringToByteArray(String s) { if (s == null) { throw new IllegalArgumentException("Provided `null` string."); } int len = s.length(); if (len % 2 != 0) { throw new IllegalArgumentException("Invalid length: " + len); } byte[] data = new byte[len / 2]; for (int i = 0; i < len - 1; i += 2) { byte b = (byte) toHexDigit(s, i); b <<= 4; b |= toHexDigit(s, i + 1); data[i / 2] = b; } return data; } private static int toHexDigit(String s, int pos) { int d = Character.digit(s.charAt(pos), 16); if (d < 0) { throw new IllegalArgumentException("Cannot parse hex digit: " + s + " at " + pos); } return d; } }

Here the entire project with a nice CLI: https://github.com/trichner/tcrypt

This is method i used.this is simple but it has better protection. https://github.com/chamikaras/simpleEncryptor

Read readme on this project.This is simple to used.

 public SimpleEncryptor(int MaximumLength) { //initialize encryption Key pattern variable pattern = new Integer[MaximumLength]; //Generate pattern pattern =GenarateEncryptionPattern(MaximumLength); } private Integer[] GenarateEncryptionPattern(int Length) { Integer[] randomPattern = new Integer[Length]; //generate encryption pattern for (int i = 0; i < Length; i++) { //make random encrypt key Random random = new Random(); randomPattern[i] = random.nextInt(9); } return randomPattern; } public void simpleEncryptData(String data) { for (int i=0; i 

}

I Have made this Simple Solution for You.

Main Point is Encrypt String by shifting ASCII Value of the Integer by the secret key you Provide.

Here is the Solution:

 public String encryptText(String toEncrypt) { String tempEn = toEncrypt + ""; String encryptText =""; for(int i=0;i 

Steps to Encode:

  1. Scan each character of String, Read ASCII of that character and add it with secret key as 148113 in this case.
  2. Convert shifted Integer into Character and concatenate to the String encryptText and finally return it.

Steps to Decode:

  1. Scan each character of String, Read ASCII of that character and subtract it with secret key as previous.
  2. Convert that value to character and concatenate with decodeText .

As previous encode output is always String '???' and vary according to number of character of input String .

 String s1="arshad"; char[] s2=s1.toCharArray(); int s3= s2.length; System.out.println(s3); int i=0; // for(int j=0;j 
 public static String encryptParams(String myTextInput) { String myKey = "40674244454045cb9a70040a30e1c007"; String myVector = "@1B2c3D4e5F6g7H8"; String encData = ""; try{ JavaEncryprtionUtil encUtil = new JavaEncryprtionUtil(); encData = Base64.encodeToString(encUtil.encrypt(myTextInput.getBytes("UTF-8"), myKey.getBytes("UTF-8"), myVector.getBytes("UTF-8")),Base64.DEFAULT); System.out.println(encData); }catch(NoSuchAlgorithmException ex){ ex.printStackTrace(); }catch(NoSuchPaddingException ex){ ex.printStackTrace(); }catch(InvalidKeyException ex){ ex.printStackTrace(); }catch(InvalidAlgorithmParameterException ex){ ex.printStackTrace(); }catch(IllegalBlockSizeException ex){ ex.printStackTrace(); }catch(BadPaddingException ex){ ex.printStackTrace(); }catch(UnsupportedEncodingException ex){ ex.printStackTrace(); } return encData; } 

You might want to consider some automated tool to do the encryption / decryption code generation eg. https://www.stringencrypt.com/java-encryption/

It can generate different encryption and decryption code each time for the string or file encryption.

It’s pretty handy when it comes to fast string encryption without using RSA, AES etc.

Sample results:

 // encrypted with https://www.stringencrypt.com (v1.1.0) [Java] // szTest = "Encryption in Java!" String szTest = "\u9E3F\uA60F\uAE07\uB61B\uBE1F\uC62B\uCE2D\uD611" + "\uDE03\uE5FF\uEEED\uF699\uFE3D\u071C\u0ED2\u1692" + "\u1E06\u26AE\u2EDC"; for (int iatwS = 0, qUJQG = 0; iatwS < 19; iatwS++) { qUJQG = szTest.charAt(iatwS); qUJQG ++; qUJQG = ((qUJQG << 5) | ( (qUJQG & 0xFFFF) >> 11)) & 0xFFFF; qUJQG -= iatwS; qUJQG = (((qUJQG & 0xFFFF) >> 6) | (qUJQG << 10)) & 0xFFFF; qUJQG ^= iatwS; qUJQG -= iatwS; qUJQG = (((qUJQG & 0xFFFF) >> 3) | (qUJQG << 13)) & 0xFFFF; qUJQG ^= 0xFFFF; qUJQG ^= 0xB6EC; qUJQG = ((qUJQG << 8) | ( (qUJQG & 0xFFFF) >> 8)) & 0xFFFF; qUJQG --; qUJQG = (((qUJQG & 0xFFFF) >> 5) | (qUJQG << 11)) & 0xFFFF; qUJQG ++; qUJQG ^= 0xFFFF; qUJQG += iatwS; szTest = szTest.substring(0, iatwS) + (char)(qUJQG & 0xFFFF) + szTest.substring(iatwS + 1); } System.out.println(szTest); 

We use it all the time in our company.

  • Определения Truststore и Keystore
  • Почему неправильный пароль приводит к тому, что «Заполнение недопустима и не может быть удалено»?
  • шифрование sqlite для Android
  • Как увидеть зашифрованный ключ в wirehark, во время обмена ключами ssl?
  • Любой исходный код cocoa для расшифровки шифрования AES?
  • Как безопасно отправлять пароль через HTTP?
  • Безопасность MD5 в порядке?
  • javax.crypto.BadPaddingException
  • Шифрование и расшифровка большой строки в java с помощью RSA
  • Преобразование Java Keystore в формат PEM
  • Хранение зашифрованных данных в Postgres
  • Interesting Posts

    Как удалить программу, которая не отображается в программах и функциях?

    Преобразование символа в верхний регистр с использованием регулярных выражений (EditPad Pro)

    Использование файлов .html как JSP

    Хорошие причины запретить наследование Java?

    Как я могу назвать функцию javascript с помощью MonoTouch и наоборот?

    Должен ли я установить свою операционную систему на SSD или HDD?

    Оператор PowerShell и -contains

    Беспроводная медленная, но очень странная

    Определите, существует ли приложение и запускает это приложение в iOS

    Декартово произведение произвольных множеств в Java

    Почему скорость уменьшается при копировании с внешнего жесткого диска?

    Как создать матрицу корреляции в R?

    Как добавить один месяц к текущей дате в Java?

    Java: разделите строку, когда найдена заглавная буква

    Используйте обычные клавиши в качестве клавиш-модификаторов, например, нажмите S и F вместе вместо Ctrl + S, чтобы сохранить файл

    Давайте будем гением компьютера.