Nodejs createCipheriv like openssl - PullRequest
0 голосов
/ 04 мая 2018

Шифрование MariaDB в состоянии покоя основывается на шифровании openssl sha1 файла keys.txt (https://mariadb.com/kb/en/library/encryption-key-management/#encrypting-the-key-file).. Мне нужно запустить экземпляр MariaDB с помощью Node.js. Итак, мне нужно зашифровать этот файл аналогичным образом, используя Node.js. Пока, используя https://github.com/beeven/gulp-openssl-encrypt в качестве руководства, я смог скопировать версию openssl -md md5. Но это не дайджест sha1, требуемый MariaDB.

function md5(data) {
  let hash = crypto.createHash('md5');
  hash.update(data);
  return hash.digest();
}
const buffer = Buffer.from(stringToEncrypt);
const salt = crypto.randomBytes(8);
const password = Buffer.from(encryptionKey);
const hash1 = md5(Buffer.concat([password, salt]));
const hash2 = md5(Buffer.concat([hash1, password, salt]));
const key = Buffer.concat([hash1, hash2]);
const iv = md5(Buffer.concat([hash2, password, salt]));
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
const chunks = [Buffer.from('Salted__'),salt];
chunks.push(cipher.update(buffer));
chunks.push(cipher.final());
let encryptedStuff = Buffer.concat(chunks);

(Правка: Уточнение) Что-то вроде этого:

function sha1(data) {
  let hash = crypto.createHash('sha1');
  hash.update(data);
  return hash.digest();
}
const buffer = Buffer.from(stringToEncrypt);
const salt = crypto.randomBytes(8);
const password = Buffer.from(encryptionKey);
const hash1 = sha1(Buffer.concat([password, salt]));
const hash2 = sha1(Buffer.concat([hash1, password, salt]));
const key = Buffer.concat([hash1, hash2]);
const iv = sha1(Buffer.concat([hash2, password, salt]));
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
const chunks = [Buffer.from('Salted__'),salt];
chunks.push(cipher.update(buffer));
chunks.push(cipher.final());
let encryptedStuff = Buffer.concat(chunks);

Но когда я пытаюсь это сделать, ключ и iv становятся слишком длинными, и возникает ошибка "Недопустимая длина ключа". Поэтому, когда я попытался нарезать его в соответствии с рекомендациями https://github.com/nodejs/node/issues/6696,, он зашифровал его, но openssl не смог его расшифровать.

1 Ответ

0 голосов
/ 05 мая 2018

Подробнее о схеме шифрования на основе пароля OpenSSL, используемой для enc, а именно EVP_BytesToKey, см. https://crypto.stackexchange.com/questions/3298/is-there-a-standard-for-openssl-interoperable-aes-encryption

AES-256 в режиме CBC требует 48 октетов для ключа + IV, а выход SHA1 равен 20 октетам, поэтому необходимо:

// do three hashes, much as you already have
hash1 = sha1(Buffer.concat([password, salt]));
hash2 = sha1(Buffer.concat([hash1, password, salt]));
hash3 = sha1(Buffer.concat([hash2, password, salt]));

// then concatenate them and split _that_ to key and IV 
total = Buffer.concat([hash1,hash2,hash3]);
key = total.slice(0,32);
iv = total.slice(32,48);

Для обработки md5 их отдельно обрабатывали, потому что бывает, что вывод MD5 из 16 октетов - это ровно половина размера ключа и точно размер IV.

...