Может ли значение узла crypto.createCipheriv('aes-256-gcm', .getAuthKey() быть общедоступным?

У меня возникли проблемы с поиском некоторой информации. Кто-нибудь знает, возвращено ли значение из cipher.getAuthTag( ) (--> возвращает MAC) может быть общедоступным?

TL;DR

Может ли код аутентификации сообщения быть общедоступным или его нужно держать в секрете, как пароль?

Некоторая предыстория, я пытаюсь зашифровать файл. Я нашел этот вопрос и ответ на stackoverflow, которые помогли мне начать работу. https://stackoverflow.com/a/27345933/11070228

Проведя некоторое исследование документации nodejs, я обнаружил, что в ответе используется устаревшая функция. createCipher. Новая функция должна быть createCipheriv. .

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

Ошибка: неподдерживаемое состояние или невозможность аутентификации данных

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

Я не знал, что это за authTag, и никто из тех, кого я знал. Итак, я начал гуглить это, и это позволило мне найти этот запись блога. Здесь утверждается

authTag — это код аутентификации сообщения (MAC), вычисляемый во время шифрования.

А вот статья в Википедии о том, что такое код аутентификации сообщения.

Итак. Вот мой вопрос. Может ли код аутентификации сообщения быть общедоступным или его нужно держать в секрете, как пароль?


Мой код не так актуален, но может помочь кому-то создать шифрование и дешифрование с помощью createCipheriv и createDecipheriv.

Шифрование

const crypto = require('crypto');
const fs = require('fs');

// const iv = crypto.randomBytes(32).toString('hex');
// EDIT - based on @President James K. Polk. The initialization vector should be 12 bytes long
// const iv = crypto.randomBytes(6).toString('hex');
// EDIT - based on @dsprenkels. I misunderstood @President James K. Polk
const iv = crypto.randomBytes(12).toString('hex');
const privateKey = 'private key that is 32 byte long';
const cipher = crypto.createCipheriv('aes-256-gcm', privateKey, iv);

const filename = 'somefile.txt';
const encFilename = 'somefile.txt.enc';
const unencryptedInput = fs.createReadStream(filename);
const encryptedOutput = fs.createWriteStream(encFilename);
unencryptedInput.pipe(cipher).pipe(encryptedOutput);

encryptedOutput.on('finish', () => {
    const authTagAsHex = cipher.getAuthTag().toString('hex'); // <-- can this be public
    console.log(authTagAsHex);
});

Расшифровка

const crypto = require('crypto');
const fs = require('fs');

// const publicIV = 'same iv generated during encryption crypto.randomBytes(32).toString("hex")';
// EDIT - based on @President James K. Polk. The initialization vector should be 12 bytes long
// const publicIV = 'same iv generated during encryption crypto.randomBytes(6).toString("hex")';
// EDIT - based on @dsprenkels. I misunderstood @President James K. Polk
const publicIV = 'same iv generated during encryption crypto.randomBytes(12).toString("hex")';
const authTag = 'same authKey generated from cipher.getAuthTag().toString("hex")';
const privateKey = 'private key that is 32 byte long';
const decipher = crypto.createDecipheriv('aes-256-gcm', privateKey, publicIV);
decipher.setAuthTag(Buffer.from(authTag, 'hex'));

const filename = 'somefile.txt';
const encFilename = 'somefile.txt.enc';
const readStream = fs.createReadStream(encFilename);
const writeStream = fs.createWriteStream(filename);
readStream.pipe(decipher).pipe(writeStream);

person tuffant21    schedule 17.06.2020    source источник
comment
Тег аутентификации не является секретом и обычно размещается где-то в зашифрованном сообщении, часто в конце. IV (который обычно называется одноразовым номером для режима GCM) должен иметь размер 12 байт и также не является секретом, а также обычно помещается в тот же поток, что и зашифрованное сообщение, часто в начале.   -  person President James K. Polk    schedule 18.06.2020
comment
Круто, ваш ответ очень полезен и очень ценен! Я обновил свой код, чтобы использовать только вектор инициализации размером 12 байт.   -  person tuffant21    schedule 18.06.2020


Ответы (1)


Да. MAC-адрес считается общедоступным.

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

MAC обычно помещается рядом с зашифрованным текстом при сохранении зашифрованного текста (так же, как IV).


Кстати, в вашем случае вы are случайным образом генерировали IV. Это нормально, но имейте в виду, что количество сообщений, которые можно безопасно зашифровать одним и тем же ключом, довольно небольшое. Если IV используется для нескольких сообщений (даже один раз!), полная безопасность этой схемы нарушается. На самом деле, вы, вероятно, хотите этого:

const iv = crypto.randomBytes(12);
person dsprenkels    schedule 18.06.2020
comment
Потрясающий! Спасибо, что поймали это. Я обновил свой код выше, чтобы отразить это изменение. Спасибо за помощь! - person tuffant21; 18.06.2020