Вектор инициализации в шифровании

Вектор инициализации

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

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

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

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

IV не должен храниться в секрете, он может передаваться открыто вместе с шифротекстом. Если вы не понимаете почему, рассмотрите следующий довод. Пусть наше сообщение состоит из нескольких блоков: B1, B2, . Bi. B1 шифруется вместе с IV. B2 шифруется с использованием шифротекста B1 в роли IV. B3 шифруется с использованием шифротекста B2 в роли IV, и так далее. Итак, если количество блоков — n, то n-1 «векторов инициализации» открыты, даже если первоначальный IV хранится в секрете. Поэтому причин хранить в секрете IV нет, IV — это просто блок-заглушка, можно считать его нулевым блоком сцепления B0.

Видео:Шифруем данные в Java с помощью алгоритма AESСкачать

Шифруем данные в Java с помощью алгоритма AES

Шифрование и расшифровка Java AES

Узнайте, как реализовать шифрование и расшифровку AES с помощью архитектуры криптографии Java.

  • Автор записи

Автор: baeldung
Дата записи

Видео:Симметричное шифрованиеСкачать

Симметричное шифрование

Шифрование и расшифровка Java AES

Видео:Реализация симметричного блочного алгоритма шифрования AES в различных режимах (ECB, CBC, CFB, OFB)Скачать

Реализация симметричного блочного алгоритма шифрования AES в различных режимах (ECB, CBC, CFB, OFB)

1. Обзор

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

В этом учебнике мы увидим, как реализовать шифрование и расшифровку AES с помощью архитектуры криптографии Java (JCA) в JDK.

Видео:Блочные шифры и как их не надо использоватьСкачать

Блочные шифры и как их не надо использовать

2. Алгоритм AES

Алгоритм AES является итеративным, симметричным шифром блока ключа, который поддерживает криптографические ключи (секретные ключи) 128, 192 и 256 битов для шифрования и расшифровки данных в блоках по 128 . На рисунке ниже показан алгоритм AES высокого уровня:

Если данные, которые будут зашифрованы, не соответствуют размеру блока в 128 битов, они должны быть проложены. Padding это процесс заполнения последнего блока до 128 битов.

Видео:2021.05.05.Режимы шифрованияСкачать

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

3. Вариации AES

Алгоритм AES имеет шесть режимов работы:

  1. ЕЦБ (Электронная кодовая книга)
  2. CBC (Цепочка блоков шифра)
  3. CFB (Шифр FeedBack)
  4. OFB (Выход FeedBack)
  5. CTR (счетчик)
  6. GCM (Галуа/Режим счетчика)

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

3.1. ЕЦБ

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

3.2. CBC

Для преодоления слабости ЕЦБ режим CBC использует Вектор инициализации (IV) для увеличения шифрования. Во-первых, CBC использует ксор блока plaintext с IV. Затем он шифрует результат к блоку шифров. В следующем блоке он использует результат шифрования для xor с блоком plaintext до последнего блока.

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

3.3. CFB

Этот режим может быть использован в качестве шифра потока. Сначала он шифрует IV, затем он будет xor с блоком plaintext, чтобы получить шифроваль. Затем CFB шифрует результат шифрования, чтобы xor простой текст. Ему нужен капельницу.

В этом режиме расшифровка может быть параллельной, но шифрование не может быть параллелизировано.

3.4. OFB

Этот режим может быть использован в качестве шифра потока. Во-первых, он шифрует IV. Затем он использует результаты шифрования, чтобы xor простой текст, чтобы получить шифроваль.

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

3.5. CTR

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

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

3.6. ГКМ

Этот режим является продолжением режима CTR. ГКМ получил значительное внимание и рекомендован NIST. Модель GCM выводит шифроватекст и тег аутентификации. Основным преимуществом этого режима, по сравнению с другими режимами работы алгоритма, является его эффективность.

В этом учебнике мы будем использовать AES/CBC/PKCS5Padding алгоритм, потому что он широко используется во многих проектах.

3.7. Размер данных после шифрования

Как упоминалось ранее, AES имеет размер блока 128 битов или 16 байтов. AES не меняет размер, а размер шифра равен размеру четкоготекста. Кроме того, в режимах ECB и CBC мы должны использовать алгоритм обивки, который ПККС 5. Таким образом, размер данных после шифрования:

Для хранения IV с шифртекстом нам нужно добавить еще 16 байтов.

Видео:Основы Шифрования за 5 минут - Asymmetric Cryptography - #ityoutubersruСкачать

Основы Шифрования за 5 минут - Asymmetric Cryptography - #ityoutubersru

4. Параметры AES

В алгоритме AES нам нужны три параметра: входные данные, секретный ключ и IV. IV не используется в режиме ЕЦБ.

4.1. Входные данные

Входные данные в AES могут быть строка, файл, объект и пароль на основе.

4.2. Секретный ключ

Существует два способа создания секретного ключа в AES: генерация случайного числа или получение данного пароля.

В первом подходе секретный ключ должен быть создан из криптографически безопасного (Псевдо-)Генератора случайных чисел, как БезопасныйРандом класс.

Для создания секретного ключа мы можем использовать Ключевой генерал класс. Давайте определим метод генерации ключа AES с размером n (128, 192 и 256) битов:

Во втором подходе секретный ключ AES может быть получен из данного пароля с помощью функции производного ключа на основе пароля, такой как PBKDF2 . Нам также нужно значение соли для превращения пароля в секретный ключ. Соль также является случайным значением.

Мы можем использовать SecretKeyFactory класс с PBKDF2WithHmacSHA256 алгоритм генерации ключа из данного пароля.

Давайте определим метод генерации ключа AES из данного пароля с 65 536 итерациями и длиной ключа 256 битов:

4.3. Вектор инициализации (IV)

IV является псевдо-случайным значением и имеет тот же размер, что и зашифрованный блок. Мы можем использовать БезопасныйРандом класса для создания случайного IV.

Давайте определим метод генерации IV:

Видео:Асимметричное шифрование | КриптографияСкачать

Асимметричное шифрование | Криптография

5. Шифрование и расшифровка

5.1. Струна

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

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

Для расшифровки строки ввода мы можем инициализировать наш шифр с помощью DECRYPT_MODE для расшифровки содержимого:

Давайте напишем метод тестирования для шифрования и расшифровки строки ввода:

5.2. Файл

Теперь давайте зашифруем файл с помощью алгоритма AES. Шаги те же, но нам нужно некоторое IO классы для работы с файлами. Давайте зашифруем текстовый файл:

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

Для расшифровки файла мы используем аналогичные шаги и инициализируем наш шифр, используя DECRYPT_MODE как мы видели раньше.

Опять же, давайте определим метод тестирования для шифрования и расшифровки текстового файла. В этом методе мы читаем Baeldung.txt файл из каталога тестовых ресурсов, шифровать его в файл под названием baeldung.encrypted , а затем расшифровать файл в новый файл:

5.3. Пароль на основе

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

Для создания секретного ключа мы используем getKeyFromPassword () метод. Шаги шифрования и расшифровки такие же, как и в разделе ввода строки. Затем мы можем использовать мгновенный шифр и предоставленный секретный ключ для выполнения шифрования.

Давайте напишем метод тестирования:

5.4. Объект

Для шифрования java-объекта необходимо использовать ЗапечатанныйОбъект класс. Объект должен быть Серийный . Начнем с определения Студенческие класс:

Далее давайте зашифруем Студенческие объект:

Зашифрованный объект можно расшифровать с помощью правильного шифра:

Давайте напишем тестовый случай:

Видео:Защита информации. Блочные шифрыСкачать

Защита информации. Блочные шифры

6. Заключение

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

Как всегда, полный исходный код статьи доступен более на GitHub .

Видео:AES алгоритм блочного шифрованияСкачать

AES алгоритм блочного шифрования

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

Теперь, когда вы ознакомились с базовыми принципами организации криптографии .NET, самое время собрать все вместе. В следующих разделах будут созданы два класса, которые используют симметричный и асимметричный алгоритмы. В разделе «Шифрование информации в базе данных» один из этих классов будет применяться для шифрования ответственной информации, такой как номер кредитной карты, сохраняемой в базе данных, а в следующей статье «Шифрование строки запроса» будет показано, как шифровать строку URL-адреса HTTP-запроса GET или POST.

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

Выберите и создайте алгоритм.

Сгенерируйте и сохраните секретный ключ.

Зашифруйте или расшифруйте информацию через CryptoStream.

Закройте соответствующим образом исходный и целевой потоки.

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

Видео:Симметричное шифрование Асимметричное шифрование ХэшСкачать

Симметричное шифрование Асимметричное шифрование Хэш

Управление ключами

Прежде чем обратиться к деталям работы с классами шифрования, следует подумать об одном дополнительном моменте: где хранить ключ? Ключ, используемый для шифрования и расшифровки — это секрет, поэтому он должен храниться в безопасном месте. Часто разработчики думают, что лучше всего хранить ключ в исходном коде. Однако это одна из наиболее серьезных ошибок, которую только можно допустить в своем приложении. Предположим, что есть следующий код в составе кода библиотеки классов, которая будет компилироваться в двоичную DLL-библиотеку:

Подобного рода ключи легко раскрыть, используя инструменты дизассемблирования. Достаточно просто запустить средство ILDASM и проанализировать класс. Конечно, вы определенно сможете найти этот ключ, как показано на рисунке ниже:

Вектор инициализации в шифровании

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

Установите комплект Microsoft SDK.

Откройте окно командной строки и введите следующую команду:

Откройте сгенерированный файл test.txt в текстовом редакторе и прокрутите текст до раздела .rdata. Где-то в этом разделе несложно найти жестко закодированный ключ.

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

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

Для защиты данных с помощью этого ключа в Windows предусмотрен интерфейс . При использовании этого API-интерфейса вы не имеете прямого доступа к этому ключу, а просто указываете системе шифровать или расшифровать что-либо с помощью машинного ключа. Таким образом, это позволяет решить задачу управления ключами: приложение может шифровать используемый в нем ключ с помощью DPAPI. Для этой цели в .NET Framework поддерживается класс System.Security.Cryptography. ProtectedData, который применяется следующим образом:

Чтобы использовать класс ProtectedData для защиты важной информации, понадобится добавить ссылку на сборку System.Security.dll и импортировать пространство имен System.Security.Cryptography. Возможными контекстами являются LocalMachine и CurrentUser. В первом варианте используется машинный ключ, а во втором — ключ, сгенерированный для текущего зарегистрированного пользователя.

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

Не используйте DPAPI для шифрования информации в базе данных. Хотя DPAPI легко применять вместе с .NET Framework, с этим методом связана одна проблема: если используется настройка DataProtectionScope.LocalMachine, то зашифрованные данные будут привязаны к машине. Таким образом, если машина выходит из строя, и данные должны быть восстановлены на другой машине, на этот случай необходимо иметь резервную копию ключа в другом безопасном месте. Для использования DPAPI в сценариях с веб-фермой понадобится запускать приложение от имени учетной записи пользователя домена и применять ключ, созданный для пользовательского профиля (DataProtectionScope.CurrentUser). Чтобы не приходилось применять пользователя домена из внутренней сети компании, рекомендуется создать отдельный домен для веб-фермы.

Видео:Как устроено шифрование?Скачать

Как устроено шифрование?

Использование симметричных алгоритмов

Как уже упоминалось, симметричные алгоритмы шифрования используют один ключ и для шифрования и расшифровки данных. В следующем разделе вы узнаете подробности создания служебного класса, выполняющего шифрование и расшифровку важных данных. Затем этот класс можно будет многократно использовать в нескольких веб-приложениях. Созданный служебный класс будет иметь показанную ниже структуру, и его можно будет применять для шифрования и расшифровки строковых данных. (Обратите внимание, что на основе ProtectKey позже будет написан код, принимающий решение, шифровать ключ с использованием DPAPI или нет. Значение true означает, что ключ должен быть защищен с помощью DPAPI.)

Поскольку этот класс является служебным с только статическими членами, его можно сделать статическим, чтобы никто не мог создавать его экземпляры. Класс предоставляет возможность для указания имени алгоритма (DES, TripleDES, RijnDael или RC2) в свойстве AlgorithmName.

Также он поддерживает операции генерирования нового ключа, чтения ключа из файла непосредственно в свойство ключа экземпляра алгоритма, а также шифрование и расшифровку данных. Для использования этого класса понадобится соответствующим образом указать имя алгоритма, а затем сгенерировать ключ, если он еще не существует. Затем потребуется просто вызывать методы EncryptData и DescryptData, которые внутри себя вызовут метод ReadKey для инициализации алгоритма. Свойство ProtectKey позволяет пользователю класса указать, нужно ли защищать ключ средствами DPAPI.

Ключи шифрования можно генерировать посредством классов алгоритмов. Метод GenerateKey выглядит так:

Метод GenerateKey() класса SymmetricAlgorithm формирует новый ключ с помощью алгоритма, генерирующего строгие случайные криптографические числа через метод GenerateKey() созданного алгоритма, и инициализирует свойство Key этим новым ключом. Если вызывающий код имеет установленный в true флаг ProtectKey служебного класса, то реализация шифрует ключ с использованием DPAPI.

Метод ReadKey читает ключ из файла, созданного методом GenerateKey, как показано ниже:

Если ранее ключ был защищен, метод ReadKey() использует DPAPI для снятия защиты с ключа после чтения его из файла. Метод требует передачи ему существующего экземпляра симметричного алгоритма. Он напрямую инициализирует свойство Key алгоритма, так что этот ключ затем применяется автоматически во всех последующих операциях. В конечном итоге обе функции — EncryptData() и DecryptData() — используют функцию ReadKey().

Оба метода требуют параметра keyFile с путем к файлу, в котором хранится ключ. Оба они последовательно вызывают метод ReadKey для инициализации своего экземпляра алгоритма этим ключом. В то время как метод EncryptData принимает строку и возвращает байтовый массив с зашифрованным ее представлением, DecryptData принимает зашифрованный байтовый массив и возвращает строку в виде открытого текста:

Начнем с метода EncryptData():

Сначала метод преобразует строку в байтовый массив, поскольку все функции шифрования алгоритма требуют байтовых массивов в качестве входных параметров. Проще всего для этого применять класс Encoding из пространства имен System.Text. Далее метод создает алгоритм согласно свойству класса AlgorithmName. Это значение может быть одним из следующих: RC2, Rijndael, DES или TripleDES.

Фабричный метод SymmetricAlgorithm.Create() создает соответствующий экземпляр, в то время как дополнительные криптографические классы могут быть зарегистрированы в разделе файла machine.config.

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

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

При использовании CryptoStream для шифрования информации не забывайте вызывать FlushFinalBlock() для обеспечения того, чтобы последний блок зашифрованных данных правильно записывался по назначению.

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

Структура функции расшифровки построена иначе. Она создает алгоритм и целевой поток для расшифрованной информации. Перед тем как расшифровать данные, необходимо прочитать вектор инициализации из входного зашифрованного потока, потому что он используется алгоритмом для последней трансформации. Затем применяется CryptoStream, как это делалось ранее, но с тем отличием, что на этот раз создается расшифровывающая трансформация. И, наконец, получается расшифрованное байтовое представление строки, которая была создана Encoding.UTF8.GetBytes(). Чтобы выполнить обратную операцию, необходимо вызвать метод GetString() кодирующего класса UTF-8 для получения текстового представления строки.

Использование класса SymmetricEncryptionUtility

Теперь можно создать страницу для тестирования класса. Это будет простая страница, которая позволит генерировать ключ и вводить данные в текстовом поле. Зашифрованные данные можно легко выводить с помощью Convert.ToBase64String(). Для расшифровки понадобится просто декодировать часть, закодированную Base64, обратно в байтовый массив. С помощью метода Convert.FromBase64String() необходимо получить зашифрованные байты обратно и отправить их методу DecryptData:

В приведенной странице используется алгоритм DES, потому что так указано в AlgorithmName. Внутри события Click() кнопки GenerateKeyCommand вызывается метод GenerateKey(). В зависимости от того, уставлен ли флажок на странице, ключ шифруется через DPAPI или нет. После того, как данные зашифрованы служебным классом внутри события Click() кнопки EncryptCommand, зашифрованные байты преобразуются в строку Base64 и затем записываются в текстовое поле EcryptedDataText. Таким образом, чтобы расшифровать информацию вновь, для этого потребуется создать байтовый массив на основе представления строки Base64 и затем вызвать метод расшифровки.

Результат показан на рисунке ниже:

Вектор инициализации в шифровании

Видео:Дмитрий Яхонтов: Курс по криптографии. Симметричные шифрыСкачать

Дмитрий Яхонтов: Курс по криптографии. Симметричные шифры

Использование асимметричных алгоритмов

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

Поскольку .NET Framework поставляется только с одним асимметричным алгоритмом для реального шифрования данных (RSA, вспомните, что DSA используется только для цифровых подписей), нет необходимости включать способ выбора алгоритма:

Метод GenerateKey() создает экземпляр алгоритма RSA для генерации ключа. Он сохраняет в файле только секретный ключ, защитив его посредством DPAPI и возвратив открытый ключ в виде XML-строки с использованием метода ToXmlString() алгоритма. Это довольно реалистичная концепция — секретный ключ обычно сохраняется приложением в секрете, в то время как открытый ключ разделяется с другими, чтобы иметь возможность шифровать информацию, которая впоследствии расшифровывается приложением с помощью его секретного ключа:

Код, вызывающий эту функцию, должен где-то сохранить полученный открытый ключ — он понадобится для шифрования информации. Извлечь ключ в XML-представлении можно с помощью метода ToXmlString(). Параметр указывает, должна включаться информация секретного ключа (true) или же нет (false). Таким образом, функция GenerateKey сначала вызывает функцию с параметром true для сохранения полной информации о ключах в файле, а затем вызывает ее с аргументом false для включения только открытого ключа. Впоследствии метод ReadKey() просто читает ключ из файла и инициализирует переданный экземпляр алгоритма через FromXml(), который противоположен методу ToXmlString():

На этот раз метод ReadKey() используется только функцией расшифровки. Функция EncryptData() принимает в виде параметра XML-представление открытого ключа, возвращенного методом GenerateKey(), поскольку секретный ключ для выполнения шифрования не требуется. Шифрование и расшифровка с помощью RSA осуществляются так, как показано ниже:

Теперь можно построить тестовую страницу, как показано ниже:

📺 Видео

Криптография в Node js - Хеширование и шифрованиеСкачать

Криптография в Node js - Хеширование и шифрование

Разработка модуля, реализующего ГОСТ 34.12-2018 “Кузнечик”, для платформы node jsСкачать

Разработка модуля, реализующего ГОСТ 34.12-2018 “Кузнечик”, для платформы node js

Режим шифрованияСкачать

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

2 КриптографияСкачать

2  Криптография

Асимметричное шифрование простым языкомСкачать

Асимметричное шифрование простым языком

Принципы шифрования и криптографии. Расшифруйте послание!Скачать

Принципы шифрования и криптографии. Расшифруйте послание!

КАК РАБОТАЕТ ШИФРОВАНИЕ? С НУЛЯ ЗА ЧАССкачать

КАК РАБОТАЕТ ШИФРОВАНИЕ? С НУЛЯ ЗА ЧАС

Криптография для хакеров. Основы алгоритмов шифрованияСкачать

Криптография для хакеров. Основы алгоритмов шифрования
Поделиться или сохранить к себе: