C # Rfc2898DeriveBytes для узла - PullRequest
2 голосов
/ 09 мая 2019

Я переписываю алгоритм шифрования (реализованный в C #) с использованием Node.Шифрование использует 32-байтовый ключ и 16-байтовый IV и использует Rfc2898DeriveBytes для генерации ключа и IV.Я использовал crypto.pbkdf2Sync для генерации ключа из 48 байтов вместо 32. Первые 32 бита были бы ключом, а оставшиеся биты служили бы IV, как показано ниже:

const crypto = require( "crypto");

const secret = 'e23d5bb0-2349-289a-d932-abc5a238a873';
const salt = '1bca26a8-49b8-6ad0-b65c-206a96107702';
const algorithm = 'aes-256-xts';
const keyAndIv = crypto.pbkdf2Sync(Buffer.from(secret, "binary"),
  Buffer.from(salt, "binary"),
  1024,
  48,
  'sha1');
const key = keyAndIv.slice(0, 32);
const iv = keyAndIv.slice(32, 48);

const cipher = crypto.createCipheriv(algorithm, key, iv);

let encrypted = cipher.update('test', 'utf8', 'hex');
encrypted += cipher.final('hex');
console.log(encrypted);

Это бросаетниже ошибка:

Error: Invalid key length
    at Cipheriv.createCipherBase (internal/crypto/cipher.js:78:18)
    at Cipheriv.createCipherWithIV (internal/crypto/cipher.js:122:20)
    at new Cipheriv (internal/crypto/cipher.js:231:22)
    at Object.createCipheriv (crypto.js:105:10)

Любые мысли были бы действительно полезны.

Ответы [ 2 ]

1 голос
/ 10 мая 2019

Причиной наблюдаемого поведения является используемый режим AES-256-XTS.

AES-XTS генерирует два ключа из переданного ключа и доступен как AES-256-XTS и AES-128-XTS.AES-256-XTS ожидает 64-байтовый ключ и генерирует из этих двух 32-байтовых ключей, AES-128-XTS ожидает 32-байтовый ключ и генерирует два 16-байтовых ключа.

Вместо заполнения *Используется 1005 * кража зашифрованного текста .Следовательно, открытый текст и зашифрованный текст имеют одинаковую длину.Кроме того, открытый текст должен иметь размер не менее одного блока (= 16 байт).Более подробную информацию об AES-XTS можно найти здесь и здесь .

Использование 32-байтового ключа в коде C # говорит об использованииAES-128-XTS, а не AES-256-XTS, для которого потребуется 64-байтовый ключ.Если алгоритм в коде изменяется с AES-256-XTS на AES-128-XTS, ошибка больше не будет возникать.

Например, для опубликованных входных данных простой текст

The quick brown fox jumped over the lazy dog

зашифрован с помощью AES-128-XTS в следующем зашифрованном тексте

b70d9f10ea6c1db513e141290059a73ab7c454e7d0a24fe482c9a6023a783303fe8bcc41bec1734d85af84ba

Там нет ничегонеправильно с генерацией ключа и IV.

NodeJS-метод pbkdf2Sync с digest = 'SHA1' является аналогом C # -метода Rfc2898DeriveBytes.Оба реализуют PBKDF2 с HMACSHA1 и поэтому возвращают одинаковый результат для одних и тех же входных данных.Например, для опубликованных входных данных:

secret:          e23d5bb0-2349-289a-d932-abc5a238a873
salt:            1bca26a8-49b8-6ad0-b65c-206a96107702
iteration count: 1024
key size:        48

генерируется следующая последовательность байтов:

BE00676F6A3D57EE66FF618FDE5BB15C0E1FC9ECDE5CE949BC784D14ACB7963B49FA9319394A69024A1F359BCC23C703
0 голосов
/ 19 мая 2019

Ниже код работает для большинства шифров:

const crypto = require( "crypto");
const base64url = require('base64url');

const secret = 'secret';
const salt = 'add some salt';

const plainText = 'test';
const algorithm = 'aes-256-ctr';

const derivedBytes = crypto.pbkdf2Sync(Buffer.from(secret), Buffer.from(salt), 1024, 48, 'sha1');

const key = derivedBytes.slice(0, 32);
const iv = derivedBytes.slice(32, 48);

const cipher = crypto.createCipheriv(algorithm, key, iv);
const output = Buffer.concat([cipher.update(plainText, 'utf8'), cipher.final()]);

console.log(output.toString('hex'));
console.log(base64url(output));

Подробный блог: https://www.devinstincts.com/2019/05/15/rewrite-c-encryption-using-node-crypto/

...