Что такое аналог WebCrypto.subtle.decrypt для node.js crypto.createDecipheriv (алгоритм AES-CTR)?
Я пытаюсь переписать старый алгоритм шифрования NodeJs из
crypto.createDecipheriv(algorithm, key, iv[, options])
в веб-крипто
subtle.decrypt(algorithm, key, data)
Этот код достаточно хорошо работает с алгоритмом AES-128-CTR.
const algorithm = 'aes-128-ctr';
const iv = '0123456789ABCDEF0123456789ABCDEF';
const privateKey = '16Random_Letters';
const hexBufferFromIv = Buffer.from(iv, 'hex');
const utfBufferFromPrivateKey = Buffer.from(privateKey, 'utf8');
function oldEncryptData(data: string): string {
const cipher = createCipheriv(
algorithm,
utfBufferFromPrivateKey,
hexBufferFromIv,
);
let crypted = cipher.update(data, 'utf8', 'base64');
crypted += cipher.final('base64');
return crypted;
}
function oldDecryptData(data: string): string {
const decipher = createDecipheriv(
algorithm,
utfBufferFromPrivateKey,
hexBufferFromIv,
);
let dec = decipher.update(data, 'base64', 'utf8');
dec += decipher.final('utf8');
return dec;
}
async function testDecrypt() {
const sourceText = `any text to encrypt!`;
const encryptedText = oldEncryptData(sourceText);
const decryptedText = oldDecryptData(encryptedText);
return sourceText === decryptedText;
}
testDecrypt().then(console.log);
Прямо сейчас я тестирую этот код и примеры WebCrypto в nodejs, но в конечном итоге я не буду переносить функциональность webCrypto.subtle.decrypt в NGINX njs, и, насколько мне известно, njs не поддерживает другие варианты расшифровки, кроме WebCrypto.
Интерфейс для расшифровки WebCrypto для AES-CTR в целом выглядит так
const data = await crypto.subtle.decrypt(
{
name: "AES-CTR",
counter, // BufferSource
length: 128, // 1-128
},
key, // AES key
encData, // BufferSource
);
И я не понимаю.
- счетчик - это то же самое, что
Initialization vector
вcreateDecipheriv
метод? - Как я должен сгенерировать ключ для
subtle.decrypt
метод из той же кодовой фразы? - Нужно ли мне делать какие-либо дополнительные преобразования из или в
base64
илиutf8
кодирование для воспроизведения входной и выходной кодировки вcipher.update(data, 'utf8', 'base64');
И вdecipher.update(data, 'base64', 'utf8');
методы?
1 ответ
Спасибо Топако за подсказки. Напишу более полный ответ. Может быть, это будет полезно для кого-то.
- Да,
Initialization vector
иcounter
можно рассматривать как одно и то же. - Для генерации ключа из той же парольной фразы следует использовать метод importKey . И вы должны отправить тот же ArrayBuffer из парольной фразы, что и в
createCipheriv
метод. - Да, если ваш старый метод использовал какое-то конкретное кодирование и декодирование, вы должны повторить ту же логику кодирования/декодирования после методов Webcrypto.SubtleCrypto.encrypt() и decrypt().
Полный работоспособный пример может выглядеть примерно так
import { webcrypto } from 'crypto';
const iv = '0123456789ABCDEF0123456789ABCDEF';
const privateKey = '16Random_Letters';
const hexBufferFromIv = Buffer.from(iv, 'hex');
const utfBufferFromPrivateKey = Buffer.from(privateKey, 'utf8');
async function generateKeyFromPassPhrase(): Promise<CryptoKey> {
return webcrypto.subtle.importKey(
'raw',
utfBufferFromPrivateKey,
{
name: 'AES-CTR',
},
true,
['decrypt', 'encrypt'],
);
}
async function newEncryptData(data: string): Promise<string> {
const key = await generateKeyFromPassPhrase();
const encryptResult = await webcrypto.subtle.encrypt(
{
name: 'AES-CTR',
length: 128,
counter: hexBufferFromIv,
},
key,
Buffer.from(data),
);
return Buffer.from(encryptResult).toString('base64');
}
async function newDecryptData(data: string): Promise<string> {
const key = await generateKeyFromPassPhrase();
const decryptResult = await webcrypto.subtle.decrypt(
{
name: 'AES-CTR',
length: 128,
counter: hexBufferFromIv,
},
key,
Buffer.from(data, 'base64'),
);
return Buffer.from(decryptResult).toString();
}
async function testDecrypt() {
const sourceText = `any text to encrypt!`;
const encrypted2 = await newEncryptData(sourceText);
const decrypted2 = await newDecryptData(encrypted2);
return sourceText === decrypted2;
}
testDecrypt().then(console.log);