Browse Source

https://gist.github.com/bnoordhuis/2de2766d3d3a47ebe41aaaec7e8b14df

https://github.com/nodejs/node/issues/18441
Girish Ramakrishnan 9 months ago
parent
commit
5b627eeac7
2 changed files with 87 additions and 5 deletions
  1. 81 0
      bytestokey.js
  2. 6 5
      test.js

+ 81 - 0
bytestokey.js

@@ -0,0 +1,81 @@
+// Copyright (c) 2017, Ben Noordhuis <info@bnoordhuis.nl>
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// Compute the key and IV that crypto.createCipher() derives from the
+// passphrase.  Use this when migrating to crypto.createCipheriv().
+'use strict';
+
+const { createCipheriv, createHash } = require('crypto');
+
+function sizes(cipher) {
+  for (let nkey = 1, niv = 0;;) {
+    try {
+      createCipheriv(cipher, '.'.repeat(nkey), '.'.repeat(niv));
+      return [nkey, niv];
+    } catch (e) {
+      if (/invalid iv length/i.test(e.message)) niv += 1;
+      else if (/invalid key length/i.test(e.message)) nkey += 1;
+      else throw e;
+    }
+  }
+}
+
+function compute(cipher, passphrase) {
+  let [nkey, niv] = sizes(cipher);
+  for (let key = '', iv = '', p = '';;) {
+    const h = createHash('md5');
+    h.update(p, 'hex');
+    h.update(passphrase);
+    p = h.digest('hex');
+    let n, i = 0;
+    n = Math.min(p.length-i, 2*nkey);
+    nkey -= n/2, key += p.slice(i, i+n), i += n;
+    n = Math.min(p.length-i, 2*niv);
+    niv -= n/2, iv += p.slice(i, i+n), i += n;
+    if (nkey+niv === 0) return [key, iv];
+  }
+}
+
+const [arg0, arg1, cipher, passphrase] = process.argv;
+if (cipher && passphrase !== undefined) {
+  const [key, iv] = compute(cipher, passphrase);
+  console.log('key:', key);
+  console.log('iv: ', iv);
+  if (/ccm|ctr|gcm/i.test(cipher)) {
+    console.log(`WARNING: Data encrypted with crypto.createCipher('${cipher}')`);
+    console.log(`WARNING: is fundamentally compromised.  You should fix this ASAP!`);
+  }
+} else {
+  const [cipher, passphrase] = ['aes-128-cbc', 'secret'];
+  const [key, iv] = compute(cipher, passphrase);
+  console.log('Usage:');
+  console.log(`  ${arg0} ${arg1} CIPHER PASSPHRASE`);
+  console.log();
+  console.log('Example:');
+  console.log(`  ${arg0} ${arg1} ${cipher} ${passphrase}`);
+  console.log();
+  console.log('Prints:');
+  console.log(`  key: ${key}`);
+  console.log(`  iv:  ${iv}`);
+  console.log();
+  console.log('Now update your code and replace this:');
+  console.log();
+  console.log(`  const cipher = crypto.createCipher('${cipher}', '${passphrase}');`);
+  console.log();
+  console.log('With this:');
+  console.log();
+  console.log(`  const key = Buffer.from('${key}', 'hex');`);
+  console.log(`  const iv  = Buffer.from('${iv}', 'hex');`);
+  console.log(`  const cipher = crypto.createCipheriv('${cipher}', key, iv);`);
+}

+ 6 - 5
test.js

@@ -30,14 +30,15 @@ function decrypt(blob, key) {
 }
 
 function main() {
-    let blob = fs.readFileSync('test.js');
+    let blob = new Buffer('foo'); // fs.readFileSync('test.js');
     let crypt = encrypt(blob, 'secret');
 
-    fs.writeFileSync('/tmp/test.js.enc', crypt);
+console.log(crypt.toString('base64'));
+//    fs.writeFileSync('/tmp/test.js.enc', crypt);
 
-    crypt = fs.readFileSync('/tmp/test.js.enc');
-    let out = decrypt(crypt, 'secret');
-    fs.writeFileSync('/tmp/test.js', out);
+//    crypt = fs.readFileSync('/tmp/test.js.enc');
+//    let out = decrypt(crypt, 'secret');
+//    fs.writeFileSync('/tmp/test.js', out);
 }
 
 main();