2016-03-25 5 views
1

パスフレーズで文字列を暗号化するコードがあります。それはCryptoJS AESの暗号化機能(CryptoJS.AES.encrypt)を使用し、このようになります...Forge.jsのCryptoJS AESデータ(パスフレーズ付き)の復号

CryptoJS.AES.encrypt(data, password).toString(); 

は今後、それが正式に維持/いない非推奨だと私は、CryptoJSを使用したくない、と私はその代わりたいと思いますForge.jsを使用する。私は解決策を見つけるためにGitHub上のForge.jsドキュメントを読み込もうとしましたが、手動でキー& IVを作成するのではなく、パスフレーズを使用するものを見つけることができませんでした。

https://code.google.com/archive/p/crypto-js/でCryptoJSアーカイブを見てきました。encrypt関数に2番目の引数(キー)として文字列が渡された場合、キーとIVを得るためのパスフレーズとして使用されているようです。しかし、それはどのようにこれを行うの詳細はありません。

結果をデコードすると、Salted__で始まり、その後にバイナリテキストの暗号化されたBLOBで始まる文字列が得られ、Forgeに "salt"をどのように渡すかわかりません。

Forge.jsのみを使用してこのデータのBlobを解読するにはどうすればよいですか?

答えて

4

CryptoJSは、OpenSSLのEVP_BytesToKey機能をサポートしています。この機能は、新しく生成された塩とパスワードから1ラウンドのMD5を使用してキーとIVを生成します。例はforge documentation pageにあります: OpenSSLの「ENC」のカスタムキーと非標準のファイル形式を使用します。opensslの「ENC」のコマンドラインツール (注意が一致するのNode.jsで偽造使用

導出機能と一部 ような)のOpenPGP/GnuPGのような代替手段よりも安全検討1の固定された繰り返し回数、この例では、トリプルDESのために示されている

var forge = require('node-forge'); 
var fs = require('fs'); 

// openssl enc -des3 -in input.txt -out input.enc 
function encrypt(password) { 
    var input = fs.readFileSync('input.txt', {encoding: 'binary'}); 

    // 3DES key and IV sizes 
    var keySize = 24; 
    var ivSize = 8; 

    // get derived bytes 
    // Notes: 
    // 1. If using an alternative hash (eg: "-md sha1") pass 
    // "forge.md.sha1.create()" as the final parameter. 
    // 2. If using "-nosalt", set salt to null. 
    var salt = forge.random.getBytesSync(8); 
    // var md = forge.md.sha1.create(); // "-md sha1" 
    var derivedBytes = forge.pbe.opensslDeriveBytes(
    password, salt, keySize + ivSize/*, md*/); 
    var buffer = forge.util.createBuffer(derivedBytes); 
    var key = buffer.getBytes(keySize); 
    var iv = buffer.getBytes(ivSize); 

    var cipher = forge.cipher.createCipher('3DES-CBC', key); 
    cipher.start({iv: iv}); 
    cipher.update(forge.util.createBuffer(input, 'binary')); 
    cipher.finish(); 

    var output = forge.util.createBuffer(); 

    // if using a salt, prepend this to the output: 
    if(salt !== null) { 
    output.putBytes('Salted__'); // (add to match openssl tool output) 
    output.putBytes(salt); 
    } 
    output.putBuffer(cipher.output); 

    fs.writeFileSync('input.enc', output.getBytes(), {encoding: 'binary'}); 
} 

// openssl enc -d -des3 -in input.enc -out input.dec.txt 
function decrypt(password) { 
    var input = fs.readFileSync('input.enc', {encoding: 'binary'}); 

    // parse salt from input 
    input = forge.util.createBuffer(input, 'binary'); 
    // skip "Salted__" (if known to be present) 
    input.getBytes('Salted__'.length); 
    // read 8-byte salt 
    var salt = input.getBytes(8); 

    // Note: if using "-nosalt", skip above parsing and use 
    // var salt = null; 

    // 3DES key and IV sizes 
    var keySize = 24; 
    var ivSize = 8; 

    var derivedBytes = forge.pbe.opensslDeriveBytes(
    password, salt, keySize + ivSize); 
    var buffer = forge.util.createBuffer(derivedBytes); 
    var key = buffer.getBytes(keySize); 
    var iv = buffer.getBytes(ivSize); 

    var decipher = forge.cipher.createDecipher('3DES-CBC', key); 
    decipher.start({iv: iv}); 
    decipher.update(input); 
    var result = decipher.finish(); // check 'result' for true/false 

    fs.writeFileSync(
    'input.dec.txt', decipher.output.getBytes(), {encoding: 'binary'}); 
} 

、それは同じように動作しますために AES。 ivSizeを16に変更するだけです。

+0

私はこれを高く評価します。これは私の質問に対する答えです。私は引用した3DESの例をAESで再利用できることを見落としました。 –

+0

私はあなたの提案を試みた後に私が返信しなかったことを認識します。おそらく私は何かが欠けているかもしれませんが、単に '3DES 'を' AES'に、 'iv'を' ivSize'に '16 'に変更しても同じ結果は得られません。私は偽造が成功したと言っているが、出力は完全に異なっているので、問題が何であるかを捜し出そうとした。だから私はそれがエンコーディング関連の問題かどうか疑問に思う。あまり確かではありません。 –

+0

Forgeは次の文字列を出力します... '1p00¿UÚ@G4WtCÕ5¸«ÑZ¿}Á6©_ͬiñýüʸiÔúÆúÇúÇÃ)&nQOW»AMب3{〜5 = O!¼=W²Ò?次... '----- RSA PRIVATE KEYをBEGIN ----- MIIEowIBAAKCAQEAqSFulewpMjRBLhiiorbvWleD5I [...]' を出力cryptojsとして、私はこれをマークするのが大好きだ[...] ' 正しいコメントとして、しかし今の上のスニペットで、私は誰もこれを見て、同じ問題を抱えて欲しくないでしょう。 –