Завершите серию AES за 30 минут (часть 2): исследование безопасности IV и семантики шифрования.
Завершите серию AES за 30 минут (часть 2): исследование безопасности IV и семантики шифрования.

Начните с простой картинки

Это простая картинка,Там есть какой-то текстовый контент:Конфиденциальная информация СОВЕРШЕННО СЕКРЕТНО

Предположим, что это изображение содержит конфиденциальную информацию, и теперь мне нужно скрыть эту информацию. Что мне делать?

Да, я зашифрую его AES!

Далее мы могли бы попытаться зашифровать его и увидеть эффект.

Еще раз: AES-ECB не является рекомендуемым режимом шифрования.

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

Так насколько это небезопасно? То, что мы видим, — это верить!

Ключ, который мы согласились использоватьkey = b"test_png_encrypt",в то же время Мы согласны с тем, что файлы, которые необходимо зашифровать на рисунке выше,file = "top_secret.png"

в то же время,Для более интуитивной проверки эффекта шифрования и уменьшения излишней детализации деталей шифрования изображений.,У нас здесь соглашение:Для изображений PNG с обычным текстом зашифруйте их по строкам, используйте несколько строк данных в изображении для имитации больших объемов данных и используйте зашифрованный зашифрованный текст каждой строки для формирования изображения зашифрованного текста для имитации различных режимов шифрования. Характеристики массива данных. сгенерированный зашифрованный текст.

На этом этапе мы шифруем файл в режиме AES-ECB:

Язык кода:javascript
копировать
    test_ecb = png_aes_encryption("ecb")
    test_ecb.key_value = key
    test_ecb.load(file)
    test_ecb.encrypt()
    test_ecb.save_cipher_png("cipher_ecb.png")

На этом этапе мы получаем изображение зашифрованного текста со следующим эффектом:

Как описать это чувство?

Он выглядит зашифрованным, но мало что добавляется.

Есть даже чувство одиночества!

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

Это также причина, по которой необходимо ввести IV.

IV усложняет процесс шифрования, позволяя лучше скрыть характеристики открытого текста.

Безопасно ли использовать режим AES-CBC IV?

Нет сомнений в том, что после введения IV в режиме CBC можно, по крайней мере, сделать вывод, что он не будет сохранять исходную текстовую информацию в полной мере.

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

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

Язык кода:javascript
копировать
    test_cbc_fixed_iv = png_aes_encryption("cbc")
    test_cbc_fixed_iv.key_value = key
    test_cbc_fixed_iv.load(file)
    test_cbc_fixed_iv.iv_value = fixed_iv
    test_cbc_fixed_iv.encrypt(fixed_iv = True)
    test_cbc_fixed_iv.save_cipher_png("cipher_cbc_fixed_iv.png")

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

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

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

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

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

Предположим, что длина двух фрагментов открытого текста составляет 128 байт и 160 байт соответственно, а их первые 33 байта одинаковы. Тогда первые 32 байта их зашифрованного текста одинаковы.

И если мы оставим ключ неизменным, каждая строка данных будет использовать другой IV (каждый раз генерируется случайный IV):

Язык кода:javascript
копировать
    test_cbc = png_aes_encryption("cbc")
    test_cbc.key_value = key
    test_cbc.load(file)
    test_cbc.encrypt()
    test_cbc.save_cipher_png("cipher_cbc.png")

Тогда вы сможете получить следующий эффект:

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

Следует подчеркнуть: AES-GCM более чувствителен к повторным IV.

Сначала нам нужно просмотреть:GCM может обеспечить шифрование и проверку целостности сообщений. Это потоковое, а не блочное шифрование.

Метод потокового шифрования на самом деле более чувствителен к повторяющимся IV.

Язык кода:javascript
копировать
    test_gcm_fixed_iv = png_aes_encryption("gcm")
    test_gcm_fixed_iv.key_value = key
    test_gcm_fixed_iv.load(file)
    test_gcm_fixed_iv.iv_value = fixed_iv
    test_gcm_fixed_iv.encrypt(fixed_iv = True)
    test_gcm_fixed_iv.save_cipher_png("cipher_gcm_fixed_iv.png")

При шифровании строк с повторяющимися IV мы получаем картину следующего эффекта:

Удивлен или нет?

Удивительно ли это?

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

Фактически, для OFB/CTR/GCM такой шаблон, как блочный шифр передачи, повторное использование NONCE понизит его до ECB модель.

ECB требуется как минимум один блок (16 байт для AES) одного и того же открытого текста, чтобы получить тот же зашифрованный текст, тогда как OFB/CTR/GCM требует только 1 бит. Если значения в одной и той же позиции в двух частях открытого текста одинаковы, то их значения в соответствующих позициях в зашифрованном тексте одинаковы в одно и то же время, если значения в одной и той же позиции в открытом тексте одинаковы; противоположны, значения на соответствующих позициях в зашифрованном тексте также противоположны. Ведь 1 бит имеет всего два значения: 0 и 1.

А что, если мы воспользуемся случайным IV?

Язык кода:javascript
копировать
    test_gcm = png_aes_encryption("gcm")
    test_gcm.key_value = key
    test_gcm.load(file)
    test_gcm.encrypt()
    test_gcm.save_cipher_png("cipher_gcm.png")

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

IV, Ключи и конфиденциальность

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

Ключ, то есть ключ, в алгоритме шифрования должен храниться в секрете и его нельзя разглашать.

У IV есть одно основное требование как для режима CBC, так и для режима GCM: уникальность.

Когда IV требует только уникальности, мы также можем назвать его NONCE.

Здесь нужно подчеркнуть: уникальность и случайность — разные вещи.

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

Библиотека Apple: https://developer.apple.com/documentation/cryptokit/aes/gcm.

Известная библиотека C++: https://doc.libsodium.org/secret-key_cryptography/aead/aes-256-gcm.

Использование библиотеки Go: https://gist.github.com/kkirsche/e28da6754c39d5e7ea10.

Для режима CBC помимо уникальности требуется еще и рандомность IV. Что такое рандом?

Просто скажи это,яПо текущему IV невозможно угадать следующий IV. Если на основе текущего IV я могу угадать следующий IV, прибавив единицу к значению последнего байта предыдущего IV, то он теряет свою случайность.

Вообще говоря,в инженерных приложениях,я们Сохранение IV уникальным и случайным — лучший вариант.

приложение

Некоторые фрагменты кода, посвященные шифрованию и перезаписи изображений PNG, предназначены только для справки:

Язык кода:javascript
копировать
def cut_list_with_step(lst: List[Any], step: int = 1):
    return [lst[i:i + step] for i in range(0, len(lst), step)]


class png_aes_encryption(object):
    def __init__(self, mode: str = "cbc"):
        self.__aes_operator = aes_encryption.aes_encryption(mode)
        self.__width: int = 0
        self.__height: int = 0
        self.__rows: List[bytes] = list()
        self.__info: Dict[str:Any] = dict()
        self.__cipher_rows: List[bytes] = list()
    
    @property
    def key_value(self) -> bytes:
        return self.__aes_operator.key_value
    
    @key_value.setter
    def key_value(self, key: bytes):
        self.__aes_operator.key_value = key
    
    @property
    def iv_value(self):
        return self.__aes_operator.iv_value
    
    @iv_value.setter
    def iv_value(self, iv: bytes):
        self.__aes_operator.iv_value = iv
    
    def load(self, filename: str):
        self.__width, self.__height, self.__rows, self.__info = png.Reader(filename = filename).read()
        print("file={filename}, file_info={info}".format(filename = filename, info = self.__info))
    
    def __generate_row_cipher(self, row_data: bytes) -> Tuple[bytes, int]:
        return self.__aes_operator.encrypt(row_data)
    
    def encrypt(self, block_size_in_bytes: int = 0, fixed_iv: bool = False):
        """
            block_size_in_bytes По умолчанию 0, Указывает шифрование по строкам матрицы
            В противном случае каждая строка будет разделена в соответствии с размером блока_в_байтах, а затем каждый разделенный блок будет зашифрован.
        """
        start = time.perf_counter()
        self.__cipher_rows = list()
        for i in self.__rows:
            
            if not fixed_iv:
                self.iv_value = bytes([random.randint(0, 255) for x in range(random.randint(8, 16))])
            
            if block_size_in_bytes <= 0:
                row_cipher, row_cipher_len = self.__aes_operator.encrypt(bytes(i))
                self.__cipher_rows.append(row_cipher)
            else:
                if block_size_in_bytes % 4 != 0:
                    raise ValueError("block_size_in_bytes has to be a multiple of 4 ")
                cut_row_cipher = bytes()
                cut_row_list = cut_list_with_step(bytes(i), block_size_in_bytes)
                for ci in cut_row_list:
                    tmp_cipher, tmp_cipher_len = self.__aes_operator.encrypt(bytes(ci))
                    cut_row_cipher += tmp_cipher
                self.__cipher_rows.append(cut_row_cipher)
        
        elapsed = round((time.perf_counter() - start), 3) * 1000
        print("mode={}, file_size={}, encryption time cost={}ms".format(self.__aes_operator.current_mode,
                                                                        self.__info["size"],
                                                                        elapsed))
    
    def save_cipher_png(self, filename: str):
        f = open(filename, 'wb')
        w = png.Writer(width = int(len(self.__cipher_rows[0]) / 4), height = len(self.__cipher_rows),
                       greyscale = self.__info['greyscale'],
                       alpha = self.__info['alpha'], bitdepth = self.__info['bitdepth'])
        print("try save png:filename={}, width={}, height={}".format(filename,
                                                                     int(len(self.__cipher_rows[0]) / 4),
                                                                     len(self.__cipher_rows)))
        w.write(f, self.__cipher_rows)
        f.close()


boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose