Получите серию AES за 30 минут (Часть 1): основные функции
Получите серию AES за 30 минут (Часть 1): основные функции

Что такое АЕС

AES — симметричный алгоритм шифрования, его полное название — РАСШИРЕННЫЙ СТАНДАРТ ШИФРОВАНИЯ.

Расширенный стандарт шифрования (AES) назначенный FIPS одобренный Криптографические алгоритмы, которые можно использовать для защиты электронных данных. АЕС 算法是一种Симметричный блочный шифр,Информация может быть зашифрована (зашифрована) и расшифрована (расшифрована). Шифрование преобразует данные в непонятную форму,называется зашифрованным текстом; расшифровка зашифрованного текста преобразует данные обратно в исходную форму;,называется открытым текстом.

Подробное описание стандарта AES можно найти в «Публикации 197 Федеральных стандартов обработки информации», оно здесь не повторяется.

Поддерживаемые режимы AES

AES поддерживает следующие режимы шифрования:

Язык кода:javascript
копировать
1. Режим ЕЦБ ( Electronic Codebook Mode)
2. Режим CBC ( Cipher Block Chaining Mode)
3. Режим CTR(The Counter Mode)
4. Режим GCM(The Galois/Counter Mode)
5. Режим CFB (режим Cipher Feedback Mode)
6. Режим OFB (режим Output Feedback Mode)

Режим шифрования AES просто делится на режим блочного шифрования и режим потокового шифрования в соответствии с различными методами шифрования.

Режим блочного шифрования является наиболее распространенным и наиболее часто используемым в технике является режим CBC.

Наиболее репрезентативным режимом шифрования потока является Режим GCM.

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

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

Почему его необходимо заполнить? Очень важная причина этого заключается в том, что библиотека шифрования (или алгоритм шифрования) сама по себе не может предсказать длину открытого текста, введенного пользователем!

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

Если длина входного открытого текста не является целым числом, кратным 16 байтам, тогда открытый текст необходимо принудительно дополнить и выровнять, чтобы он мог соответствовать правилам группировки.

Некоторые из наиболее распространенных правил заполнения следующие:

  • NoPadding: Как следует из названия,Просто не наполняется. Недостатком является то, что он может шифровать только информацию, кратную BlockSize.,Обычно не используется
  • ZerosPadding: все дополнено 0x00.,Сколько бы не хватало, заполните все 0x00,Он уже кратен BlockSize и его еще нужно заполнить.,Этот метод не используется в общем машиностроении.
  • PKCS#5: заполните недостающие байты.,Значение каждого байта — это количество пропущенных байтов.;Строго говоря, PKCS#5 нельзя использовать в шифровании AES, поскольку размер блока AES составляет 16 байт, а PKCS#5 можно использовать только для 8 байт.
  • PKCS#7:Заполните несколько недостающих байтов, а значение каждого байта — это количество недостающих байтов; когда длины не выровнены, заполните данные до длины группы, когда длины только что выровнены, в конце; исходные данные Добавлен блок заполнения OpenSSL по умолчанию использует PKCS#7 в шифровании AES;
  • ISO 10126: Значение последнего байта — это количество байтов, которые необходимо заполнить (количество байтов, которые необходимо заполнить, включает последний байт), а все остальные заполняются случайными числами.
  • ANSI X9.23: Очень похоже на ISO 10126, за исключением того, что остальные байты в ANSI X9.23 заполнены нулями вместо случайных чисел.

Эффект заполнения PKCS#7:

image.png
image.png
Язык кода:javascript
копировать
    def padding_check(self, origin: str, block_size: int):
        """ 
            Предполагая, что BlockSize равен 128 или 16 байт, тогда:
            Если длина исходного текста меньше 16 байт, он будет заполнен в соответствии с размером блока, равным 16 байтам (128 бит). 
        """
        padder = padding.PKCS7(block_size).padder()
        ret = padder.update(origin.encode('utf-8'))
        ret += padder.finalize()
        print("origin=", list(origin),
              "after padding=", list(ret))
        
        """ Убедитесь, что количество байтов после заполнения соответствует ожидаемому. """
        self.assertEqual(len(ret) % get_bytes_len(block_size), 0)
        
        """ Значение заполнения также является длиной заполнения в байтах. """
        padding_value = get_padding_value(
            get_bytes_len(block_size), len(origin))
        
        """ Длина заполнения составляет padding_value байт, значение каждого байта должно быть padding_value """
        for i in range(1, padding_value + 1):
            self.assertEqual(int(ret[0 - i]), int(padding_value))

В оставшейся части этой статьи мы будем использовать PKCS#7 по умолчанию для избыточного заполнения.

Небезопасное блочное шифрование: ЕЦБ

Режим ECB небезопасен и не рекомендуется к использованию в инженерной практике.

Язык кода:javascript
копировать
    def test_ecb_cipher(self):
        origin_1 = "aaaaaaaaaaaaaaaa"
        origin_2 = "bbbbbbbbbbbbbbbb"
        origin_3 = (origin_1 + origin_2)
        key = "1234567890123456".encode('utf-8')
        aes_obj = aes_encryption.aes_encryption("ecb", key)
        print("Current AES Mode:", aes_obj.current_mode)
        cipher_1, cipher_1_len = aes_obj.encrypt(origin_1.encode('utf-8'))
        cipher_2, cipher_2_len = aes_obj.encrypt(origin_2.encode('utf-8'))
        cipher_3, cipher_3_len = aes_obj.encrypt(origin_3.encode('utf-8'))
        print("cipher_1:{}".format(list(cipher_1)))
        print("cipher_2:{}".format(list(cipher_2)))
        print("cipher_3:{}".format(list(cipher_3)))
        """ В режиме ECB между зашифрованным и открытым текстом существует взаимно однозначное соответствие, что небезопасно. """
        self.assertEqual(cipher_1_len % 16, 0)
        self.assertEqual(cipher_2_len % 16, 0)
        self.assertEqual(cipher_3_len % 16, 0)
        self.assertEqual(
            cipher_1[:cipher_1_len - 16] + cipher_2[:cipher_2_len - 16], cipher_3[:cipher_3_len - 16])
        self.assertEqual(len(aes_obj.key_value) % 16, 0)
        self.assertLessEqual(len(aes_obj.key_value), 32)

когда мы используемECBоткрытый текст:aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbа такжеaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb做шифрование时,Если мы немного понаблюдаем, то обнаружим,Зашифрованный текст фактически появляется неоднократно.

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

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

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

Классический режим блочного шифрования: CBC

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

Язык кода:javascript
копировать
    def test_aes_cbc_encryption(self):
        origin = os.urandom(random.randint(17, 256))
        key = os.urandom(32)
        iv = os.urandom(16)
        aes_obj = aes_encryption.aes_encryption("cbc", key, iv)
        print("Current AES Mode:", aes_obj.current_mode)
        cipher, cipher_len = aes_obj.encrypt(origin)
        plain, plain_len = aes_obj.decrypt(cipher)
        self.assertEqual(plain, origin)
        self.assertEqual(len(origin), plain_len)
        self.assertGreaterEqual(cipher_len, len(origin))
        print("cipher_len:", cipher_len)
        print("origin_len:", len(origin))
        print("len(origin) % 16 = ", len(origin) % 16)
        """
            Если исходная длина данных равна BlockSize * n,
            затем используйте NoPadding Когда длина зашифрованных данных равна BlockSize * n, в остальных случаях длина зашифрованных данных равна BlockSize * (n+1)。
            Если исходная длина данных равна BlockSize*n+m [в m меньше, чем BlockSize],
            Кроме NoPadding Любыми способами, кроме заполнения, длина зашифрованных данных равна BlockSize*(n+1);
        """
        if len(origin) % 16 == 0:
            self.assertEqual(cipher_len, len(origin))
        else:
            self.assertEqual(cipher_len, (len(origin) // 16 + 1) * 16)

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

В режиме шифрования CBC первый входной блок формируется путем операции XOR первого блока открытого текста с IV.

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

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

Функция прямого шифрования применяется к каждому входному блоку для создания блока зашифрованного текста.

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

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

Классическая логическая абстрактная диаграмма AES-CBC:

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

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

Цепная реакция режима CBC относится к процессу шифрования, поскольку при изменении IV все блоки зашифрованного текста в процессе шифрования изменятся;

При расшифровке IV повлияет только на первый блок открытого текста.

Язык кода:javascript
копировать
    def test_aes_cbc_decrypt_by_wrong_iv(self):
        """
            Цепная реакция в режиме CBC обычно относится к процессу шифрования, поскольку при изменении IV все блоки зашифрованного текста в процессе шифрования изменяются.
            При расшифровке IV повлияет только на первый блок открытого текста.
        """
        # 64-байтовый простой текст
        origin_plain = os.urandom(64)
        print("origin_plain[0:16]:{}".format(list(origin_plain[0:16])))
        print("origin_plain[16:32]:{}".format(list(origin_plain[16:32])))
        print("origin_plain[32:48]:{}".format(list(origin_plain[32:48])))
        print("origin_plain[48:64]:{}".format(list(origin_plain[48:64])))
        # Ключ длиной 32 байта
        key = os.urandom(32)
        # print("key:{}".format(list(key)))
        # Длина 16 байт iv
        iv = os.urandom(16)
        print("correct iv:{}".format(list(iv)))
        aes_obj = aes_encryption.aes_encryption("cbc", key, iv)
        cipher, cipher_len = aes_obj.encrypt(origin_plain)
        # Используйте правильный ключ и iv для расшифровки
        plain, plain_len = aes_obj.decrypt(cipher)
        self.assertEqual(plain, origin_plain)
        self.assertEqual(len(origin_plain), plain_len)
        self.assertGreaterEqual(cipher_len, len(origin_plain))
        # Установите неправильное значение iv
        aes_obj.iv_value = os.urandom(16)
        self.assertNotEqual(iv, aes_obj.iv_value)
        print("wrong iv:{}".format(list(aes_obj.iv_value)))
        wrong_plain, wrong_plain_len = aes_obj.decrypt(cipher)
        print("wrong_plain[0:16]:{}".format(list(wrong_plain[0:16])))
        print("wrong_plain[16:32]:{}".format(list(wrong_plain[16:32])))
        print("wrong_plain[32:48]:{}".format(list(wrong_plain[32:48])))
        print("wrong_plain[48:64]:{}".format(list(wrong_plain[48:64])))
        # Даже при использовании неправильного внутривенного введения для расшифровки,Но полученная длина по-прежнему верна.,只是Расшифровать出来的内容会有不同
        self.assertNotEqual(wrong_plain, origin_plain)
        self.assertNotEqual(wrong_plain, plain)
        self.assertEqual(len(origin_plain), wrong_plain_len)
        # При расшифровке неправильный IV влияет только на первый 16-байтовый блок блока открытого текста.
        self.assertNotEqual(wrong_plain[0:16], origin_plain[0:16])
        self.assertEqual(wrong_plain[16:], origin_plain[16:])

Режим потокового шифрования отличается от режима блочного шифрования: CTR и GCM.

Режим CTR

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

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

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

Режим CTR имеет множество преимуществ: прост в понимании,Высокая эффективность,Никакой прокладки не требуется,Поддерживает распараллеливание,произвольный доступ,А также просто функции шифрования и так далее.

Однако у CTR есть и очевидные недостатки:

Язык кода:javascript
копировать
Целостность сообщения не может быть гарантирована:
    Не имея аутентификации сообщения, злоумышленник может легко перевернуть перехваченное зашифрованное сообщение и воспроизвести его без расшифровки.
    И поскольку Режим Из-за податливости CTR изменение одного бита приведет к разрушительным результатам.
Повторное использование блока счетчика приводит к утечке открытого текста:
    Если блок счетчика (nonce) используется повторно, это может привести к утечке открытого текста;
    Особенно Шифрование CTR требует ввода уникального случайного числа, которое нельзя использовать повторно для двух разных сообщений, зашифрованных одним и тем же ключом, поэтому метод генерации случайных чисел особенно важен.
Длина зашифрованного текста известна (длину исходного текста можно скрыть с помощью заполнения):
    Потому что Режим CTR не требует заполнения, поэтому длина зашифрованного зашифрованного текста может быть известна.
    Хотя длина сообщения не считается секретом во многих методах шифрования, благодаря характеристикам симметричного шифрования можно получить соответствующую длину открытого текста:
    Это приводит к риску утечки открытого текста на высоком уровне.

Режим GCM

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

Следовательно, мы можем добавить эту часть в качестве дополнительного сообщения к расчету значения MAC.

Режим GCM — это очень классический AEAD (аутентифицированный Encryption with Associated Data)。

AEAD — это форма шифрования, сочетающая конфиденциальность, целостность и аутентификацию.

Причина AEAD очень проста. Шаг расшифровки простого алгоритма симметричного шифрования не может подтвердить правильность ключа. Другими словами, зашифрованные данные можно расшифровать с помощью любого ключа, чтобы получить набор подозрительных исходных данных. Мы не знаем, верен ли ключ и верны ли расшифрованные исходные данные. Поэтому нам необходимо добавить уровень метода проверки поверх простого алгоритма шифрования, чтобы подтвердить правильность шагов расшифровки.

Распространенными алгоритмами AEAD являются:

Язык кода:javascript
копировать
AES-128-GCM
AES-192-GCM
AES-256-GCM
ChaCha20-IETF-Poly1305
ChaCha20-IETF-Poly1305

На процессорах (настольных компьютерах, серверах) с ускорением AES рекомендуется использовать серию AES-XXX-GCM, а для мобильных устройств — серию ChaCha20-IETF-Poly1305.

Сравнение CBC и GCM

AES-GCM может шифровать и дешифровать параллельно, тогда как режим AES-CBC определяет, что он может шифровать только последовательно.

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

AES-GCM предоставляет код проверки информации GMAC для проверки целостности зашифрованного текста. AES-CBC его не имеет и не может эффективно проверять целостность зашифрованного текста;

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

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

Эта часть будет подробно описана в других статьях этой серии, так что следите за обновлениями!

boy illustration
Углубленный анализ переполнения памяти CUDA: OutOfMemoryError: CUDA не хватает памяти. Попыталась выделить 3,21 Ги Б (GPU 0; всего 8,00 Ги Б).
boy illustration
[Решено] ошибка установки conda. Среда решения: не удалось выполнить первоначальное зависание. Повторная попытка с помощью файла (графическое руководство).
boy illustration
Прочитайте нейросетевую модель Трансформера в одной статье
boy illustration
.ART Теплые зимние предложения уже открыты
boy illustration
Сравнительная таблица описания кодов ошибок Amap
boy illustration
Уведомление о последних правилах Points Mall в декабре 2022 года.
boy illustration
Даже новички могут быстро приступить к работе с легким сервером приложений.
boy illustration
Взгляд на RSAC 2024|Защита конфиденциальности в эпоху больших моделей
boy illustration
Вы используете ИИ каждый день и до сих пор не знаете, как ИИ дает обратную связь? Одна статья для понимания реализации в коде Python общих функций потерь генеративных моделей + анализ принципов расчета.
boy illustration
Используйте (внутренний) почтовый ящик для образовательных учреждений, чтобы использовать Microsoft Family Bucket (1T дискового пространства на одном диске и версию Office 365 для образовательных учреждений)
boy illustration
Руководство по началу работы с оперативным проектом (7) Практическое сочетание оперативного письма — оперативного письма на основе интеллектуальной системы вопросов и ответов службы поддержки клиентов
boy illustration
[docker] Версия сервера «Чтение 3» — создайте свою собственную программу чтения веб-текста
boy illustration
Обзор Cloud-init и этапы создания в рамках PVE
boy illustration
Корпоративные пользователи используют пакет регистрационных ресурсов для регистрации ICP для веб-сайта и активации оплаты WeChat H5 (с кодом платежного узла версии API V3)
boy illustration
Подробное объяснение таких показателей производительности с высоким уровнем параллелизма, как QPS, TPS, RT и пропускная способность.
boy illustration
Удачи в конкурсе Python Essay Challenge, станьте первым, кто испытает новую функцию сообщества [Запускать блоки кода онлайн] и выиграйте множество изысканных подарков!
boy illustration
[Техническая посадка травы] Кровавая рвота и отделка позволяют вам необычным образом ощипывать гусиные перья! Не распространяйте информацию! ! !
boy illustration
[Официальное ограниченное по времени мероприятие] Сейчас ноябрь, напишите и получите приз
boy illustration
Прочтите это в одной статье: Учебник для няни по созданию сервера Huanshou Parlu на базе CVM-сервера.
boy illustration
Cloud Native | Что такое CRD (настраиваемые определения ресурсов) в K8s?
boy illustration
Как использовать Cloudflare CDN для настройки узла (CF самостоятельно выбирает IP) Гонконг, Китай/Азия узел/сводка и рекомендации внутреннего высокоскоростного IP-сегмента
boy illustration
Дополнительные правила вознаграждения амбассадоров акции в марте 2023 г.
boy illustration
Можно ли открыть частный сервер Phantom Beast Palu одним щелчком мыши? Супер простой урок для начинающих! (Прилагается метод обновления сервера)
boy illustration
[Играйте с Phantom Beast Palu] Обновите игровой сервер Phantom Beast Pallu одним щелчком мыши
boy illustration
Maotouhu делится: последний доступный внутри страны адрес склада исходного образа Docker 2024 года (обновлено 1 декабря)
boy illustration
Кодирование Base64 в MultipartFile
boy illustration
5 точек расширения SpringBoot, супер практично!
boy illustration
Глубокое понимание сопоставления индексов Elasticsearch.
boy illustration
15 рекомендуемых платформ разработки с нулевым кодом корпоративного уровня. Всегда найдется та, которая вам понравится.
boy illustration
Аннотация EasyExcel позволяет экспортировать с сохранением двух десятичных знаков.