Дополнительные аутентифицированные данные (AAD) — это часть входных данных в схемах аутентифицированного шифрования, которая не подвергается шифрованию, но включается в вычисление тега целостности (authentication tag).
Ключевое свойство AAD:
В схемах AEAD (Authenticated Encryption with Associated Data) AAD играет роль связующего контекста между шифротекстом и внешними параметрами системы: заголовками сообщений, метаданными, идентификаторами сессий.
AEAD объединяет две операции:
AAD участвует только во второй части.
Формально модель выглядит так:
plaintext + key + nonce + AADciphertext + authTagAAD входит в вычисление authTag, но не влияет на
ciphertext.
Это означает:
Stanford Javascript Crypto Library реализует аутентифицированное шифрование через режимы, в первую очередь CCM (Counter with CBC-MAC).
В SJCL AAD задаётся через параметр:
adata (associated data)Он используется как часть входа в MAC (Message Authentication Code), но не шифруется.
Основной API шифрования:
sjcl.encrypt(password, data, options)
Параметр options может содержать:
mode — режим шифрования (например, “ccm”)iv — вектор инициализации (nonce)iter — количество итераций KDFsalt — сольadata — дополнительные аутентифицированные данныеПример базовой структуры:
const encrypted = sjcl.encrypt("secretPassword", "Sensitive message", {
mode: "ccm",
adata: "header-information"
});
AAD в SJCL — это строка или сериализуемые данные, которые:
Типичные примеры AAD:
Рассмотрим сценарий обмена сообщениями:
const message = "transfer 1000 coins";
const encrypted = sjcl.encrypt("key123", message, {
mode: "ccm",
adata: JSON.stringify({
userId: 42,
type: "transaction",
version: 1
})
});
Здесь:
"transfer 1000 coins" — шифруетсяПри расшифровании AAD должен быть идентичным побитово:
const decrypted = sjcl.decrypt("key123", encrypted, {
mode: "ccm",
adata: JSON.stringify({
userId: 42,
type: "transaction",
version: 1
})
});
Если изменить хотя бы один символ:
adata: '{"userId":43,"type":"transaction","version":1}'
результат:
CCM mode (Counter with CBC-MAC) реализует AAD через CBC-MAC.
Процесс вычисления:
AAD разбивается на блоки
включается в CBC-MAC до обработки plaintext
затем добавляется ciphertext (в режиме счётчика)
итоговый MAC зависит от:
Важно:
Внутри SJCL AAD сериализуется в строку и включается в структуру параметров:
{
"iv": "...",
"v": 1,
"iter": 10000,
"ks": 128,
"ts": 64,
"mode": "ccm",
"adata": "..."
}
AAD хранится вместе с зашифрованным текстом, но логически отделён.
SJCL работает с AAD как с:
Однако важное свойство:
Это означает:
AAD используется для защиты контекста, который нельзя подделать без ключа.
adata: "msg-type:payment"
Любая подмена типа сообщения делает ciphertext недействительным.
adata: JSON.stringify({
sessionId: "A1B2C3"
})
Если ciphertext переносят между сессиями — проверка проваливается.
adata: "protocol:v3"
Позволяет исключить атаки по даунгрейду.
JSON.stringify({a:1, b:2})
JSON.stringify({b:2, a:1})
Результат:
"data"
" data "
Даже пробел критичен.
Объекты JavaScript с нефиксированным порядком ключей приводят к ошибкам.
Для корректной работы AAD в SJCL применяются строгие принципы сериализации:
Пример стабильного подхода:
function stableStringify(obj) {
const sorted = {};
Object.keys(obj).sort().forEach(k => sorted[k] = obj[k]);
return JSON.stringify(sorted);
}
AAD позволяет отделить:
Это даёт архитектурные преимущества:
Пример комбинированного сообщения:
const payload = {
user: 1001,
permissions: ["read", "write"],
timestamp: Date.now()
};
const encrypted = sjcl.encrypt("key", "payload-data", {
mode: "ccm",
adata: JSON.stringify(payload)
});
Здесь AAD фиксирует:
AAD не участвует в KDF (Key Derivation Function), но влияет на:
В SJCL ключ генерируется отдельно через PBKDF2:
Частая ошибка — попытка использовать AAD как скрытый канал данных.
AAD:
Он предназначен только для: