Общ. рыноч. кап.:$00
API
RU
Тёмный

ПоискSSI/Mag7/Meme/ETF/Монета/Индекс/Графики/Исследования
00:00 / 00:00
Вид
    Рынки
    Индексы
    Лента
    TokenBar®
    Анализ
    Макрос
    Список наблюдения
Поделится

DAEAD: детерминированное аутентифицированное шифрование с сопутствующими данными

Prof Bill Buchanan OBE
1KСлова
29/06/2025

DAEAD: Детерминированное аутентифицированное шифрование со связанными данными

Преодоление повторного использования/неправильного использования Nonce: режим SIV

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

Когда дело доходит до симметричных ключевых методов, детерминированная природа может быть полезна при поиске данных, но с точки зрения безопасности она будет слабее, поскольку злоумышленник может сопоставить входные данные с выходными. В этом случае мы объединим детерминированную природу с Authenticated Encryption with Associated Data (Deterministic AEAD) и будем использовать режим AES-SIV.

SIV — Synthetic Initialization Vector (синтетический вектор инициализации)

Мы выдаем слишком много наших секретов и часто не можем защитить один из наших самых важных секретов … наши ключи шифрования. Чтобы преодолеть это, мы можем использовать метод, называемый key wrapping, который защищает ключ. Это особенно важно, когда мы передаем ключ по ненадежным каналам или храним его в местах без строгого контроля доступа. Для key wrapping Rogaway et al предложили метод SIV (Synthetic Initialisation Vector) [here], который аутентифицирует и шифрует, а также аутентифицирует любые дополнительные данные, связанные с ключом:

В настоящее время этот метод стандартизирован в RFC 5297 [here]. С помощью улучшенных методов шифрования мы можем как аутентифицировать шифр, так и доказать его целостность. Это известно как Authenticated Encryption with Associated Data (AEAD). Для этого мы предоставляем дополнительные данные для аутентификации процесса шифрования и можем определить, где был изменен зашифрованный текст, чтобы его нельзя было расшифровать. В большинстве обычных методов AEAD мы создаем значение nonce и добавляем дополнительные данные (AD), которые аутентифицируются, но не шифруются. С подходом без nonce мы можем использовать метод key wrapping, который часто использовался для защиты ключей шифрования. Дополнительные данные могут включать [here]:

addresses, ports, sequence numbers, protocol version numbers, and other fields that indicate how the plaintext or ciphertext should be handled, forwarded, or processed

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

В следующем коде мы будем использовать дополнительную информацию «101112131415161718191a1b1c1d1e1f2021222324252627», но на практике она может быть любой длины. В SIV у нас также может быть несколько источников этих дополнительных данных (известных как вектор строк). Эта информация может быть распределена по нескольким источникам, и злоумышленнику, вероятно, будет трудно ее захватить и воспроизвести. Это одна из особенностей SIV, которая позволяет использовать несколько строк для аутентификации, а не объединять их в одну строку для получения дополнительной информации:

byte[] plaintext = pl.getBytes();

String additional="101112131415161718191a1b1c1d1e1f2021222324252627";
byte[] ciphertext = daead.encryptDeterministically(plaintext, Hex.decode(additional));

Традиционные методы AEAD могут быть слабыми с точки зрения повторного использования nonce, а также неправильного использования nonce. Во многих системах мы используем недетерминированный метод генерации nonce, поэтому нет возможности узнать, не использовались ли ранее сгенерированные значения. Другая слабость заключается в том, что nonce можно «воспроизвести», откатив виртуальную машину и обнаружив использованное значение nonce. Таким образом, большинство методов AEAD безопасны с уникальным nonce, но нет никакой гарантии безопасности, если nonce не является уникальным. Поскольку значение nonce ограничено по размеру, всегда будет шанс повторно использовать его с тем же ключом, и, следовательно, нам, возможно, придется регулярно менять наши ключи. SIV обеспечивает большую защиту от повторного использования/неправильного использования nonce, и злоумышленник может только определить, что данное значение открытого текста и данный набор связанных данных были защищены с использованием определенного ключа и значения nonce.

Кодирование

В следующем коде мы создаем ключ SIV, а затем создаем значения зашифрованного текста, которые должны быть одинаковыми [here]:

package main

import (
"fmt"
"os"

"github.com/tink-crypto/tink-go/v2/daead"
"github.com/tink-crypto/tink-go/v2/keyset"


)

func main() {

msg:="Hello"
associated:="Hello"

argCount := len(os.Args[1:])
if (argCount>0) {msg = os.Args[1]}
if (argCount>1) {associated =os.Args[2]}

handle, _ := keyset.NewHandle(daead.AESSIVKeyTemplate())

primitive, _ := daead.New(handle)

plaintext := []byte(msg)
associatedData := []byte(associated)


ciphertext1, _:= primitive.EncryptDeterministically(plaintext, associatedData)
ciphertext2, _:= primitive.EncryptDeterministically(plaintext, associatedData)

res, _ := primitive.DecryptDeterministically(ciphertext1, associatedData)

fmt.Printf("Plaintext is %s\n",msg)
fmt.Printf("Associated data is %s\n\n",associated)

fmt.Printf("Key is %s\n\n",handle)

fmt.Printf("Cipher1 is %x\n\n",ciphertext1)
fmt.Printf("Cipher2 is %x\n\n",ciphertext2)
fmt.Printf("Decrypted is %s",res)


}

Пример запуска показывает, что у нас один и тот же шифр, когда мы шифруем детерминированно [here]:

Plaintext is Testing 123
Associated data is qwerty123

Key is primary_key_id:1537855825 key_info:{type_url:"type.googleapis.com/google.crypto.tink.AesSivKey" status:ENABLED key_id:1537855825 output_prefix_type:TINK}

Cipher1 is 015ba9d1518f3a5d213ce9630294f87af76ce86011c8631842aa96571d0dee03

Cipher2 is 015ba9d1518f3a5d213ce9630294f87af76ce86011c8631842aa96571d0dee03

Decrypted is Testing 123

Все, что вам нужно знать за 10 секунд
УсловияПолитика конфиденциальностиБелая книгаОфициальная проверкаCookieБлог
sha512-gmb+mMXJiXiv+eWvJ2SAkPYdcx2jn05V/UFSemmQN07Xzi5pn0QhnS09TkRj2IZm/UnUmYV4tRTVwvHiHwY2BQ==
sha512-kYWj302xPe4RCV/dCeCy7bQu1jhBWhkeFeDJid4V8+5qSzhayXq80dsq8c+0s7YFQKiUUIWvHNzduvFJAPANWA==