#javascript #node.js #aes-gcm
#javascript #node.js #aes-gcm
Вопрос:
Жаль, что мне не помогли, потому что я не знаю, почему моя реализация AES-GCM нарушает кодировку файлов.
У меня есть API, который использует 1 функцию для шифрования / дешифрования с помощью AES-256-GCM. (С КЛЮЧОМ = буфер из 32 случайных байтов)
Вот функция:
const aes256gcm = (key) => {
const ALGO = 'aes-256-gcm';
const encrypt = (str) => {
try {
const salt = crypto.randomBytes(64);
const iv = crypto.randomBytes(32);
let derivedkey = crypto.pbkdf2Sync(key, salt, 55000, 32, 'sha512');
const cipher = crypto.createCipheriv(ALGO, derivedkey, iv);
let encrypted = Buffer.concat([cipher.update(str), cipher.final()]);
const tag = cipher.getAuthTag();
let buffer = Buffer.concat([salt, iv, encrypted]);
encrypted = {
tag: tag,
buffer: buffer
}
return encrypted;
} catch (e) {
console.log(e);
}
};
const decrypt = (data, authTag) => {
try {
const salt = data.slice(0, 64);
const iv = data.slice(64, 96);
const text = data.slice(96, data.length);
authTag = new Buffer.from(authTag, 'base64');
let derivedkey = crypto.pbkdf2Sync(key, salt, 55000, 32, 'sha512');
let decipher = crypto.createDecipheriv(ALGO, derivedkey, iv);
decipher.setAuthTag(authTag);
let decrypted = decipher.update(text, 'binary') decipher.final();
return decrypted;
} catch (e) {
console.log(e);
}
};
return {
encrypt,
decrypt
};
};
С помощью этого кода я шифрую и записываю в файл результат:
const aesCipher = aes.aes256gcm(aes.loadKey(path.resolve(__dirname, `key`)));
const encrypted = aesCipher.encrypt(file.data);
if (encrypted !== undefined) {
fs.writeFile(`${file.name}.enc`, encrypted.buffer, function (err) {
if (err) return console.log(err);
console.log(`${file.name}.enc successfully created`);
});
}
И, наконец, с этим я расшифровываю и записываю содержимое в файл:
const aesCipher = aes.aes256gcm(aes.loadKey(path.resolve(__dirname, `key`)));
let filename = 'test1.gz';
let authTag = 'puI0FfV4Btiy7iPiZFbwew==';
let encrypted = fs.readFileSync(path.resolve(__dirname, `test1.gz.enc`));
const decrypted = aesCipher.decrypt(encrypted, authTag);
if (decrypted !== undefined) {
const file = fs.createWriteStream(filename);
file.write(new Buffer.from(decrypted, 'ascii'), function (err) {
if (err) return console.log(err);
console.log(`Successfully decrypted`);
file.close();
});
res.send({
status: true,
message: 'File is decrypted',
});
}
Разница в моих файлах ввода / вывода :
Разница
Итак, что я делаю не так? Хорош ли мой процесс шифрования? Почему это хорошо работает только с файлами .txt?
Спасибо вам!
Комментарии:
1. Тот факт, что он явно в основном правильный, означает, что шифрование / дешифрование почти наверняка в порядке. Я с подозрением
Buffer.from(decrypted, 'ascii')
отношусь к; произвольные двоичные форматы не являются ASCII (если он работает с простым текстом ASCII, это подтвердило бы мои подозрения). Я бы надеялся, что JS сможет читать и записывать необработанные двоичные данные или, в противном случае, иметь некоторую кодировку, которую вы можете использовать для «эквивалента необработанных байтов», напримерlatin-1
(в Python; технически он не использует все 256 байт, но Python позволяет ему соответствовать первым 256 порядковым номерам Unicode дажекогда это технически не определено для них).2. Спасибо за ваш быстрый ответ @ShadowRanger! Я уже тестировал это с кодировкой «binary», которая является псевдонимом для latin-1, поэтому я думаю, что это не проблема. Есть другие идеи? (Он отлично работает с длинными файлами .txt)
Ответ №1:
Я думаю, что довольно небольшое изменение в вашей функции дешифрования должно устранить проблему, если вы просто обновите ее до:
const decrypt = (data, authTag) => {
try {
const salt = data.slice(0, 64);
const iv = data.slice(64, 96);
const text = data.slice(96, data.length);
authTag = new Buffer.from(authTag, 'base64');
let derivedkey = crypto.pbkdf2Sync(key, salt, 55000, 32, 'sha512');
let decipher = crypto.createDecipheriv(ALGO, derivedkey, iv);
decipher.setAuthTag(authTag);
let decrypted = Buffer.concat([decipher.update(text), decipher.final()]);
return decrypted;
} catch (e) {
console.log(e);
}
};
Я думаю, что предыдущая реализация неправильно объединяла результат для нетекстовых файлов.
Комментарии:
1. Это то же самое, если бы я хотел защитить PDF-файл паролем, а затем, когда я его открыл, он спросил у меня ключ?
2. Я не верю, что это одно и то же. Это, скорее всего, встроенный механизм паролей PDF.