Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8896

CryptoJSで暗号化したファイルをどうしてもシェルスクリプト上で復号したかった

$
0
0
やりたかったこと Node.jsのCryptoJSで暗号化したファイルを保存する そのファイルをシェルスクリプト上で読み込み、復号する 暗号化処理(Node.js) const crypto = require('crypto'); const fs = require('fs'); /* * passphrase <String> * salt <String> * keylen <Number> * iv <String> * pass <String> ファイルパス * inputPath <String> ファイルパス * outputPath <String> ファイルパス */ // 暗号 const key = crypto.scryptSync(passphrase, salt, keylen); const cipher = crypto.createCipheriv('aes-256-cbc', key, iv); fs.writeFileSync(pass, passphrase); // 読み込み => 暗号化 => 書き出し const input = fs.createReadStream(inputPath); const output = fs.createWriteStream(outputPath); input.pipe(cipher).pipe(appendiv).pipe(output); 復号処理(Shell) $ openssl -aes-256-cbc -d \ $ -pass pass:<pass> \ $ -salt <salt> \ $ -in <inputPath> \ $ -out <outputPath> 結果: bad decrypt できなかったこと(めんどくさくなったこと) opensslコマンドで復号 opensslが取り扱うsaltあり暗号文は、ヘッダとして Salted__ という8byteを持つ前提になっている。 暗号文とpassのみを渡して復号 IVを使って暗号化するとき、理論上passと暗号文からkeyとIVを復元できるが、手軽にこれを実現するライブラリを見つけられなかった。 やったこと 暗号化処理でIVを暗号文に連結して渡すように変更 シェルスクリプト側でもNode.jsのCryptoJSを利用して復号するように変更 ※IVは平文のまま安全でない経路で受け渡しできるとされている 暗号化処理(Node.js) const crypto = require('crypto'); const fs = require('fs'); // 暗号 const key = crypto.scryptSync(passphrase, salt, keylen); const cipher = crypto.createCipheriv('aes-256-cbc', key, iv); fs.writeFileSync(pass, passphrase); const input = fs.createReadStream(inputPath); /* ↓追加処理↓ */ // https://stackoverflow.com/questions/41594042/node-transform-stream-append-string-to-end const appendiv = new stream.Transform({ transform(chunk, encoding, callback) { callback(null, chunk); }, flush(callback) { this.push(iv); callback(); } }); /* ↑追加処理↑ */ const output = fs.createWriteStream(outputPath); // 読み込み => 暗号化 => IVを末尾に付加 => 書き出し input.pipe(cipher).pipe(appendiv).pipe(output); node-script.js /* 復号処理(Node.jsスクリプト) */ /* * IV_LEN <Number> IVの長さ */ exports.decipher = async(options) => { const pass = fs.readFileSync(options.pass).toString(/* passphraseの文字コードに注意 */); const key = crypto.scryptSync(pass, options.salt, options.keylen); const input = fs.readFileSync(options.inputPath); const iv = input.slice(-1 * IV_LEN); // 後ろからIV_LEN文字がIV const cipher = crypto.createDecipheriv(options.cipher, key, iv); let decrypted = cipher.update(input.slice(0, -1 * IV_LEN)); // 後ろからIV_LEN文字目より前が暗号文 decrypted = Buffer.concat([decrypted, cipher.final()]); const output = fs.writeFileSync(options.outputPath, decrypted); } decipher.js /* cacjsによりcliコマンド化 */ const cac = require('cac'); const cli = cac(); const nodeScript = require('./node-script'); cli .command('decipher', '復号する') .option('--pass <pass>', 'passが記載されたファイル') .option('--salt <salt>', 'ソルト文字列') .option('--keylen <keylen>', 'keyの長さ') .option('--inputPath <inputPath>', '暗号化されたファイル') .option('--outputPath <outputPath>', '復号されたファイル') .action(async (options) => { await nodeUtils.decipher(options); }); cli.help(); cli.parse(); シェルスクリプト node decipher.js decipher \ --pass <pass> \ --salt <salt> \ --keylen <keylen> \ --in <inputPath> \ --out <outputPath> わかったこと 暗号化と復号は同じツールを使ってやるのが楽。

Viewing all articles
Browse latest Browse all 8896

Trending Articles