Машинное обучение в большей или меньшей степени сейчас используется в различных отраслях. Не стало исключением и направление криптографического анализа. В этой статье мы рассмотрим генеративно‑состязательную сеть CipherGAN, используемую для определения базового шифровального отображения по банкам непарного зашифрованного текста и открытого текста.
CycleGAN
В основе CipherGAN лежит другая генеративно‑состязательная сеть — CycleGAN. Данный тип генеративно‑состязательной сети, используется для переноса стиля изображения. Так CycleGAN можно обучить конвертировать изображения из одного домена (например, Fortnite) в другой, например, PUBG. Обучение выполняется без учителя, то есть не существует способа однозначного сопоставления изображений из обоих этих доменов.
Это открывает возможность выполнять множество интересных задач, таких как улучшение качества фотографий, раскрашивание изображений, перенос стиля и т. д. Все, что вам нужно, — это исходный и целевой набор данных (который представляет собой просто каталог изображений). Общий принцип работы данной сети представлен на следующей схеме.
Но вернемся к основной теме нашей статьи — CipherGAN. Как уже упоминалось выше, данная сеть используется для определения базового шифровального отображения по банкам непарного зашифрованного текста и открытого текста.
Шифры подстановки обладают свойством запутывания, которое обеспечивает неразличимость ключа шифрования и соответствующего зашифрованного текста. В частности, путаница является основным строительным блоком современной симметричной криптографии, обладающей свойством диффузии. Таким образом, понимание структуры и уязвимости шифров подстановки может стать основой для криптоанализа современной криптографии. В таблице 2 представлены различные исследования криптоанализа на основе искусственного интеллекта
Однако, CipherGAN способен взламывать языковые данные, зашифрованные с использованием различных вариаций шифров и шифра Виженера, с высокой степенью точности и для словарей, значительно превышающих ранее достигнутые.
Напомним, что такое шифр Виженера. Для зашифровывания может использоваться таблица алфавитов, называемая tabula recta или квадрат (таблица) Виженера. Применительно к латинскому алфавиту таблица Виженера составляется из строк по 26 символов, причём каждая следующая строка сдвигается на несколько позиций.
На каждом этапе шифрования используются различные алфавиты, выбираемые в зависимости от символа ключевого слова. Например, предположим, что исходный текст имеет такой вид:
ATTACKATDAWN
Человек, посылающий сообщение, записывает ключевое слово («LEMON») циклически до тех пор, пока его длина не будет соответствовать длине исходного текста:
LEMONLEMONLE
Первый символ исходного текста («A») зашифрован последовательностью L, которая является первым символом ключа. Первый символ зашифрованного текста («L») находится на пересечении строки L и столбца A в таблице Виженера. Точно так же для второго символа исходного текста используется второй символ ключа; то есть второй символ зашифрованного текста («X») получается на пересечении строки E и столбца T. Остальная часть исходного текста шифруется подобным способом.
Исходный текст: ATTACKATDAWN
Ключ: LEMONLEMONLE
Зашифрованный текст: LXFOPVEFRNHR
Конечно, по современным меркам это мягко говоря, не самый мощный алгоритм шифрования, однако в учебных целях он вполне может использоваться.
Установка CipherGAN
CipherGAN написан на Python, что заметно упрощает работу с данной сетью. Для установки выполним:
pip install -r CipherGAN/requirements.txt
Для того, чтобы обучить нашу нейросеть мы используем генераторы данных. Особого внимания заслуживает cipher_generator (https://github.com/for‑ai/CipherGAN/blob/master/data/data_generators/cipher_generator.py), который может использоваться для генерации данных для шифров смещения и Виженера.
Настройки, необходимые для генерации передаются скрипту в виде флагов. Например, чтобы сгенерировать шифр Виженера на уровне слов (ключ:КОД) с длиной выборки 200, вызовите:
python CipherGAN/data/data_generators/cipher_generator.py \
--cipher=vigenere \
--vigenere_key=345 \
--percentage_training=0.9 \
--corpus=brown \
--vocab_size=200 \
--test_name=vigenere345-brown200-eval \
--train_name=vigenere345-brown200-train \
--output_dir=tmp/data \
--vocab_filename=vigenere345_brown200_vocab.txt
Запускаем обучение
Для того, чтобы выполнить обучение нейросети можно воспользоваться скриптом train.py
, представленным ниже.
import shutil
import os
import tensorflow as tf
from .hparams.registry import get_hparams
from .models.registry import _MODELS
from .data.registry import _INPUT_FNS, get_dataset
from .metrics.registry import get_metrics
from .train_utils.lr_schemes import get_lr
from .train_utils.vocab_utils import read_vocab
tf.flags.DEFINE_string("model", "cycle_gan", "Which model to use.")
tf.flags.DEFINE_string("data", "cipher", "Which data to use.")
tf.flags.DEFINE_string("hparam_sets", "cipher_default", "Which hparams to use.")
tf.flags.DEFINE_string("hparams", "", "Run-specific hparam settings to use.")
tf.flags.DEFINE_string("metrics", "xy_mse",
"Dash separated list of metrics to use.")
tf.flags.DEFINE_string("output_dir", "tmp/tf_run",
"The output directory.")
tf.flags.DEFINE_string("data_dir", "tmp/data", "The data directory.")
tf.flags.DEFINE_integer("train_steps", 1e4,
"Number of training steps to perform.")
tf.flags.DEFINE_integer("eval_steps", 1e2,
"Number of evaluation steps to perform.")
tf.flags.DEFINE_boolean("overwrite_output", False,
"Remove output_dir before running.")
tf.flags.DEFINE_string("train_name", "data-train*",
"The train dataset file name.")
tf.flags.DEFINE_string("test_name", "data-eval*", "The test dataset file name.")
FLAGS = tf.app.flags.FLAGS
tf.logging.set_verbosity(tf.logging.INFO)
def _run_locally(train_steps, eval_steps):
"""Run training, evaluation and inference locally.
Args:
train_steps: An integer, number of steps to train.
eval_steps: An integer, number of steps to evaluate.
"""
hparams = get_hparams(FLAGS.hparam_sets)
hparams = hparams.parse(FLAGS.hparams)
hparams.total_steps = FLAGS.train_steps
if "vocab_file" in hparams.values():
hparams.vocab = read_vocab(hparams.vocab_file)
hparams.vocab_size = len(hparams.vocab)
hparams.vocab_size += int(hparams.vocab_size % 2 == 1)
hparams.input_shape = [hparams.sample_length, hparams.vocab_size]
output_dir = FLAGS.output_dir
if os.path.exists(output_dir) and FLAGS.overwrite_output:
shutil.rmtree(FLAGS.output_dir)
if not os.path.exists(output_dir):
os.makedirs(output_dir)
def model_fn(features, labels, mode):
lr = get_lr(hparams)
return _MODELS[FLAGS.model](hparams, lr)(features, labels, mode)
train_path, eval_path = get_dataset(FLAGS.data_dir, FLAGS.train_name,
FLAGS.test_name)
train_input_fn = _INPUT_FNS[FLAGS.data](train_path, hparams, training=True)
eval_input_fn = _INPUT_FNS[FLAGS.data](eval_path, hparams, training=False)
run_config = tf.contrib.learn.RunConfig()
estimator = tf.contrib.learn.Estimator(
model_fn=model_fn, model_dir=output_dir, config=run_config)
eval_metrics = get_metrics(FLAGS.metrics, hparams)
experiment = tf.contrib.learn.Experiment(
estimator=estimator,
train_input_fn=train_input_fn,
eval_input_fn=eval_input_fn,
eval_metrics=eval_metrics,
train_steps=train_steps,
eval_steps=eval_steps)
experiment.train_and_evaluate()
def main(_):
_run_locally(FLAGS.train_steps, FLAGS.eval_steps)
if __name__ == "__main__":
tf.app.run()
В качестве примера представлены параметры, необходимые для обучения нейросети, на основе данных, сгенерированных на предыдущем шаге.
python -m CipherGAN.train \
--output_dir=runs/vig345 \
--test_name="vigenere345-brown200-eval*" \
--train_name="vigenere345-brown200-train*" \
--hparam_sets=vigenere_brown_vocab_200
Заключение
Конечно, сейчас искусственный интеллект еще не умеет взламывать AES или ГОСТ. Представленная в статье нейросеть CipherGAN пока умеет расшифровывать учебные шифры, наподобие шифра Виженера. Однако, в будущем нейросети вполне могут стать эффективным помощником для криптоаналитиков.
Статья подготовлена в преддверии старта курса «Криптографическая защита информации». Узнать подробнее о курсе.