Шифрование пароля Java


Оглавление

Java cryptography API предоставляется так называемым расширением Java Сryptography Extension(JCE). J CE уже давно является частью платформы Java. Изначально JCE был отделен от Java из-за того, что в США действовали экспортные ограничения на технологии шифрования. Поэтому самые стойкие алгоритмы шифрования не были включены в стандартную платформу Java. Эти более надежные алгоритмы шифрования можно применять, если ваша компания находится в США, но в остальных случаях придется применять более слабые алгоритмы или реализовывать свои собственные алгоритмы шифрования и подключать их к JCE.

С 2017 года правила экспорта алгоритмов шифрования в США были значительно ослаблены и в большей части мира можно пользоваться международными стандартами шифрования через Java JCE.

Архитектура криптографии Java

Java Cryptography Architecture (JCA) — название внутреннего дизайна API криптографии в Java. J CA структурирован вокруг нескольких основных классов и интерфейсов общего назначения. Реальная функциональность этих интерфейсов обеспечивается поставщиками. Таким образом, можно использовать класс Cipher (Шифр) для шифрования и расшифровки некоторых данных, но конкретная реализация шифра (алгоритм шифрования) зависит от конкретного используемого поставщика.

Также можно реализовать и подключить свои собственные провайдеры, но вы должны быть осторожны с этим. Правильно реализовать шифрование без дыр в безопасности сложно! Если вы не знаете, что делаете, вам, вероятно, лучше использовать встроенный поставщик Java или использовать надежного поставщика, такого как Bouncy Castle.

Основные классы и интерфейсы

API криптографии Java состоит из следующих пакетов Java:

Основные классы и интерфейсы этих пакетов:

Provider (Поставщик криптографии)

Класс Provider (java.security. Provider) является центральным классом в Java crypto API. Для того чтобы использовать Java crypto API, вам нужно установить поставщика криптографии. Java SDK поставляется с собственным поставщиком криптографии. Если вы явно не установите поставщик криптографии, то будет использоваться поставщик по умолчанию. Однако этот поставщик криптографии может не поддерживать алгоритмы шифрования, которые вы хотите использовать. Поэтому вам, возможно, придется установить свой собственный поставщик криптографии.

Один из самых популярных поставщиков криптографии для Java crypto API называется Bouncy Castle. Вот пример, где в качестве поставщика криптографии устанавливается BouncyCastleProvider:

Cipher (Шифр)

Класс Cipher (javax.crypto. Cipher) представляет криптографический алгоритм. Шифр может использоваться как для шифрования, так и для расшифровки данных. Класс Cipher объясняется более подробно в следующих разделах, ниже будет его краткое описание.

Создание экземпляра класса шифр, который использует алгоритм шифрования AES для внутреннего использования:

Cipher cipher = Cipher.getInstance(«AES/CBC/PKCS5Padding»);

Инициализация шифра

Перед использованием экземпляра шифра его необходимо инициализировать. Экземпляр шифра инициализируется вызывом метода init(). Метод init() принимает два параметра:

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

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

Чтобы инициализировать экземпляр шифра для расшифровки данных, вы должны использовать Cipher. DECRYPT_MODE, например:

Шифрование или дешифрование данных

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

Пример шифрования данных с помощью метода doFinal():

Чтобы расшифровать данные, нужно передать зашифрованный текст(данные) в метод doFinal() или doUpdate().

Keys (Ключи)

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

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

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

Безопасность ключа

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

Генерация ключа

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

Читайте также:  Белорусский фонд социального страхования и страховые взносы в Фонд социального страхования

KeyGenerator keyGenerator = KeyGenerator.getInstance(«AES»);

SecureRandom secureRandom = new SecureRandom();
int keyBitSize = 256;
keyGenerator.init(keyBitSize, secureRandom);

SecretKey secretKey = keyGenerator.generateKey();

Полученный экземпляр SecretKey можно передать в метод Cipher.init(), например так:

Генерация пары ключей

Алгоритмы асимметричного шифрования используют пару ключей, состоящую из открытого ключа и закрытого ключа, для шифрования и дешифрования данных. Для создания асимметричной пары ключей вы можете использовать KeyPairGenerator (java.security. KeyPairGenerator). KeyPairGenerator будет более подробно описан в следующих главах, ниже простой пример использования Java KeyPairGenerator:

SecureRandom secureRandom = new SecureRandom();
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(«DSA»);
KeyPair keyPair = keyPairGenerator.generateKeyPair();

Хранилище ключей (Key Store)

Java KeyStore — это база данных, которая может содержать ключи. Java KeyStore представлен классом KeyStore (java.security. KeyStore). Хранилище ключей может содержать ключи следующих типов:

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

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

Инструмент управления ключами (Keytool)

Java Keytool — это инструмент командной строки, который может работать с файлами Java KeyStore. Keytool может генерировать пары ключей в файл KeyStore, экспортировать сертификаты и импортировать сертификаты в KeyStore и некоторые другие функции. Keytool поставляется с установкой Java. Keytool более подробно описан далее в отдельной главе по Java Keytool.

Дайджест сообщения (MessageDigest)

Когда вы получаете зашифрованные данные от другой стороны, можете ли вы быть уверенными что никто не изменил зашифрованные данные по пути к вам?

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

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

Java MessageDigest (java.security. MessageDigest) можно использовать для вычисления дайджестов сообщений. Для создания экземпляра MessageDigest вызывается метод MessageDigest.getInstance(). Существует несколько различных алгоритмов дайджеста сообщений. Вам нужно указать, какой алгоритм вы хотите использовать при создании экземпляра MessageDigest. Работа с MessageDigest будет более подробно описана в главе посвященной Java MessageDigest.

Краткое введение в класс MessageDigest

MessageDigest messageDigest = MessageDigest.getInstance(«SHA-256»);

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

Чтобы вычислить дайджест сообщения некоторых данных, вы вызываете метод update() или digest(). Метод update() может вызываться несколько раз, а дайджест сообщения обновляется внутри объекта. Когда вы передали все данные, которые вы хотите включить в дайджест сообщения, вы вызываете digest() и извлекаете итоговые данные дайджеста сообщения.

Пример вызова update() несколько раз с последующим вызовом digest():

Вы также можете вызвать digest() один раз, передав все данные, чтобы вычислить дайджест сообщения. Пример:

Код аутентификации сообщения (MAC)

Класс Java Mac используется для создания MAC(Message Authentication Code) из сообщения. M AC похож на дайджест сообщения, но использует дополнительный ключ для шифрования дайджеста сообщения. Только имея как исходные данные, так и ключ, вы можете проверить MAC. Таким образом, MAC является более безопасным способом защиты блока данных от модификации, чем дайджест сообщения. Класс Mac более подробно описан в главе по Java Mac, ниже приведено краткое введение.

Экземпляр Java Mac создается вызовом метода Mac.getInstance(), передавая в качестве параметра имя используемого алгоритма. Вот как это выглядит:

Mac mac = Mac.getInstance(«HmacSHA256»);

Прежде чем создать MAC из данных, вы должны инициализировать экземпляр Mac ключом. Вот пример инициализации экземпляра Mac ключом:

После инициализации экземпляра Mac вы можете вычислить MAC из данных, вызвав методы update() и doFinal(). Если у вас есть все данные для расчета MAC, вы можете сразу вызвать метод doFinal(). Вот как это выглядит:

Подпись (Signature)

Класс Signature (java.security. Signature) используется для цифровой подписи данных. Когда данные подписаны, цифровая подпись создается из этих данных. Таким образом, подпись отделена от данных.

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

Signature signature = Signature.getInstance(«SHA256WithDSA»);

Подпись данных

После инициализации экземпляра подписи, его можно использовать для подписи данных. Это делается вызовом метода update(), передавая данные для подписи в качестве параметра. Можно вызывать метод update() несколько раз, чтобы дополнить данные для создании подписи. После передачи всех данных в метод update(), вызывается метод sign() для получения цифровой подписи. Вот как это выглядит:

Проверка подписи

Signature signature = Signature.getInstance(«SHA256WithDSA»);
signature.initVerify(keyPair.getPublic());

После инициализации в режиме проверки в метод update() передаются данные, которые подписаны подписью. Вызов метода verify(), возвращает значение true или false в зависимости от того, можно ли проверить подпись или нет. Вот как выглядит проверка подписи:

Полный пример подписи и проверки

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

Читайте также:  Декретный фонд социального страхования

Java Cipher (Шифр)

Класс Java Cipher (javax.crypto. Cipher) представляет собой алгоритм шифрования. Термин «Шифр» является стандартным термином для алгоритма шифрования в мире криптографии. Вот почему класс Java называется Шифр(Cipher), а не Шифратор / Дешифратор или как-то еще. Вы можете использовать экземпляр Cipher для шифрования и расшифровки данных в Java. В этой главе объясняется, как работает класс Cipher.

Создание шифра

Прежде чем использовать шифр, необходимо создать экземпляр класса Cipher, вызывая его метод getInstance() с параметром, указывающим, какой тип алгоритма шифрования вы хотите использовать. Вот пример создания экземпляра Java Cipher:

Cipher cipher = Cipher.getInstance(«AES»);

В этом примере создается экземпляр Cipher с использованием алгоритма шифрования AES.

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

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

Поскольку режим сцепления блоков шифрования также требует «схемы дополнения», схема дополнения (PKCS5Padding) добавляется в конец строки имени алгоритма шифрования.
Важно знать, что не все алгоритмы и режимы шифрования поддерживаются поставщиком шифрования Java SDK по умолчанию. Для создания нужного вам экземпляра шифра с требуемым режимом и схемой заполнения может понадобиться установить сторонний провайдер, такой как Bouncy Castle.

Прежде чем использовать экземпляр Cipher, его необходимо инициализировать. Инициализация шифра выполняется путем вызова его метода init(). Метод init() принимает два параметра:

Пример инициализации экземпляра Cipher в режиме шифрования:

А вот пример инициализации экземпляра Cipher уже в режиме расшифровки:

Шифрование и расшифровка данных

Чтобы зашифровать или расшифровать данные с помощью экземпляра Cipher, вызывается один из этих двух методов:

Существует несколько переопределенных версий методов update() и doFinal(), которые принимают разные параметры. Рассмотрим наиболее часто используемые здесь. Если вам необходимо зашифровать или расшифровать один блок данных, просто вызовите doFinal() с данными для шифрования или расшифровки. Пример:

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

Если вам нужно зашифровать или расшифровать большой файл разбитый на несколько блоков, вызывается update() один раз для каждого блока данных и завершается вызовом метода doFinal() с последним блоком данных. Вот пример шифрования нескольких блоков данных:

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

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

Шифрование / Расшифровка части байтового массива

Методы шифрования и расшифровки класса Cipher могут шифровать или расшифровывать часть данных, хранящихся в байтовом массиве. Методу update() и/или doFinal() нужно передать смещение и длину.

В данном примере будут зашифрованы (или расшифрованы, в зависимости от инициализации шифра) байты с 10 индекса и на 24 байта вперед.

Шифрование / Расшифровка в существующий байтовый массив

Все приведенные в этой главе примеры шифрования и дешифрования возвращают зашифрованные или дешифрованные данные в новом байтовом массиве. Однако также возможно зашифровать или расшифровать данные в существующий байтовый массив. Это может быть полезно для уменьшения количества созданных байтовых массивов. Для этого необходимо передать целевой массив байтов в качестве параметра методу update() и/или doFinal().

В этом примере данные шифруются с 10 индекса на 24 байта вперед в байтовый массив dest со смещением 0. Если вы хотите установить другое смещение для байтового массива dest, существуют версии update() и doFinal(), которые принимают дополнительный параметр смещения. Пример вызова метода doFinal() со смещением в массиве dest:

Повторное использование экземпляра шифра

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

Пример повторного использования экземпляра Java Cipher:

Сначала создается и инициализируется экземпляр Cipher, а затем используется для шифрования двух блоков согласованных данных. Обратите внимание на вызов update(), а затем doFinal() для этих двух блоков данных. После этого экземпляр Cipher может быть снова использован для шифрования данных. Это делается с помощью вызова doFinal() с третьим блоком данных. После этого вызова doFinal() вы можете зашифровать еще один блок данных с тем же экземпляром Java Cipher.

Читайте также:  Телефоны горячей линии и график работы филиалов - Государственное учреждение - Московское областное региональное отделение Фонда социального страхования Российской Федерации

Определение шифра

Рассмотрим реализацию симметричного шифрования в java на примере алгоритма AES. В первую очередь нам понадобится
определяющий алгоритм шифрования класс javax.crypto. Cipher, реализующий базовые функции популярных
криптографических алгоритомов. Для получения экземпляра данного класса используется статистический метод
Cipher.getInstance(), которому в качестве параметра передается наименование криптографического алгоритма
шифрования. В простейшем случае пример создания экземпляра Java Cipher мог бы выглядеть следующим образом :

Однако, согласно документации JCA (Java Cryptography Architecture), в разделе «Creating a Cipher Object» указано, что
для того, чтобы получить экземпляр Cipher нужно указать не просто алгоритм шифрования, а «трансформацию». Формат
описания «трансформации» выглядит следующим образом: «algorithm/mode/padding» :

Параметр «padding» определяет, какой объём данных составляет 1 блок. Каждый блок данных шифруется отдельно.
Так, например, padding, равный PKCS5Padding, определяет размер одного блока в 2 байта (16 бит).

Режим шифрования определяет детали шифрования данных, которые косвенно влияют на алгоритм шифрования. Режимы
шифрования могут использоваться в нескольких различных алгоритмах шифрования как метод, добавляемый к основному
алгоритму. Поэтому режимы шифрования рассматриваются не отдельно от самих алгоритмов шифрования, а скорее как их
«дополнения». Наиболее известные режимы шифрования :

Отдельные алгоритмы шифрования могут работать в разных режимах.

В примере, рассмотренном ниже, при создании экземпляра Cipher будем использовать трансформацию
«AES/ECB/PKCS5Padding». То есть, алгоритм шифрования – AES, режим шифрования – ECB, размер блока
– 2 байта (PKCS5Padding).

Прежде чем использовать Cipher для шифрования или дешифрирования текста, его необходимо инициализировать.
Инициализация Cipher выполняется вызовом его метода init(int opmode, Key key), принимающего два
параметра :

Следующий код формирует экземпляр cipher для шифрования текста. Для дешифрирования текста необходимо
определить режим Cipher. DECRYPT_MODE.

Cipher cipher = Cipher.getInstance(«AES/ECB/PKCS5Padding»);

// Экземпляр cipher для шифрования текста
cipher.init(Cipher. ENCRYPT_MODE, secretKey);

Создание секретного ключа

Рассмотрим метод создания секретного ключа createSecretKey(), листинг которого представлен ниже. В методе сначала
формируется массив bytes с использованием генератора псевдослучайныйх значений
SecureRandom. После этого для массива bytes создается дайджест сообщения
MessageDigest. Размер дайджеста составляет 20 байт, из которых выделяются первые 16
байт методом копирования в новый массив (copyOf) утилитой Arrays. Экземпляр секретного ключа SecretKeySpec
создается для алгоритма «AES». Закомментированный в методе код позволяет вывести в консоль сгенерированный массив
псевдослучайных значений.

Ключ алгоритма симметричного шифрования должен храниться в тайне обеими участниками. Алгоритм шифрования выбирается
сторонами до начала обмена криптованными сообщениями. В методе createSecretKey таким ключом является переменная key.
Ключ используется для создания SecretKeySpec, который необходим для инициализации Cipher.

Java Cryptography

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

В этой статье объясняются основы того, как пользоваться Java Cryptography API для выполнения различных задач в которых требуется безопасное шифрование.

В этой статье не объясняются основы криптографической теории. Вам придется посмотреть эту информацию где-нибудь еще.

Шифрование и дешифрирование

Для шифрования и дешифрования данных с помощью экземпляра Cipher, используется один из методов update()
или doFinal(). Класс Cipher имеет несколько переопределенных методов update() и doFinal(),
которые принимают разные параметры. Следующий пример демонстрирует использование метода doFinal() для шифрования
текста :

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

Листинг примера CryptoExample

В примере CryptoExample представлены 2 метода : encrypt и decrypt. Исходный код метода createSecretKey рассмотрен
выше. Алгоритм функционирования данных методов понятен из представленного выше описания. Дополнительно в методах encrypt
и decrypt представлен код шифрования и дешифрирования с использованием утилиты java.util. Base64, которая
появилась в Java 8.

Base64 — стандарт кодирования двоичных данных при помощи только 64 символов ASCII. Алфавит кодирования
содержит текстово-цифровые латинские символы A-Z, a-z и 0-9 (62 знака) и 2 дополнительных символа, зависящих от системы
реализации. Т.е. весь диапазон закодированных символов укладывается в английский алфавит, цифры и двух спецсимволов.
Таким образом, из каждых 3 исходных байтов утилита Base64 формирует 4 символа, увеличивая размер текста на &#x2153.

В примере для криптования использован текст «decrypt!decrypt!decrypt!decrypt!», представляющий 4 повторяющихся
размером 8 символов/байт слов «decrypt!». Т.е., кодируемый текст из 32 байт включает 2 повторяющихся выражения
«decrypt!decrypt!» по 16 байт. А, как мы помним, режим PKCS5Padding определяет размер кодируемого блока в 2 байта.

Ну, и теперь смотрим на результат выполнения примера. В консоль были выведены следующие сообщения :

random : 992DE79A44047FCD641EC2F9F1A2056D

Original text: ‘decrypt!decrypt!decrypt!decrypt!’

Encrypted text :
CF2949AFAA65F0E2E8926364D56FBBFA CF2949AFAA65F0E2E8926364D56FBBFA 6C1647F049941345172F0083EF997201

Text after decryption: ‘decrypt!decrypt!decrypt!decrypt!’

Кодированный текст (Encrypted text) для наглядности, разделен на 3 части. После первых 2-х частей из 32 символов
вставлены символы пробела и переносом », далее остальная часть кодированного текста.

Режим шифрования CBC вводит понятие Initialization Vector, представленный классом IvParameterSpec. В
данном режиме результат генерации предыдущего блока используется для генерации следующего.

Но чтобы использовать режим шифрования CBC требуется несложная доработка кода, связанная с инициализацией шифра
Cipher. Для этого определяем массив из 16 байт sec_bytes, которые будем заполнять псевдослучайными значениями
в конструкторе класса. При нициализации шифра будем использовать этот массив для формирования IvParameterSpec.
Ниже представлены изменения кода примера для использования режима CBC.

После доработки повторения в кодированном тексте отсутствуют, результат шифрования и дешифрирования радует.

random : 5B1E804043C2068B9602285172800C3E

Original text: ‘decrypt!decrypt!decrypt!decrypt!’

Encrypted text :
F0802F50C5E41CFEE3F1F5EA71224771 8F1BCDF65519472EDCD6DE11FB0E14A1 D3A493CF59D7F2BB197CA90025E05203

Text after decryption: ‘decrypt!decrypt!decrypt!decrypt!’

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

Оцените статью
ФСС Help
Добавить комментарий