2016-04-25 30 views
2

私はJavaでファイルを暗号化しており、クライアント側で解読する必要があります。 これはサーバー側コードです:Javaからファイルbytearrayを解読するCryptoJS(AES)

var xhr = new XMLHttpRequest(); 
xhr.open('GET', 'file', true); 
xhr.responseType = 'arraybuffer'; 

xhr.onload = function (e) { 
     var encryptedData = this.response; 
     var decrypted = CryptoJS.AES.decrypt(encryptedData, "mysecretmysecret"); 
     console.log(decrypted); 
}; 
xhr.send(); 

しかし、これはファイルの暗号化を解除しない:私は、ファイルを取得し、CryptoJS AESを使用するAjaxリクエストを使用してクライアント側で

Key secretKey = new SecretKeySpec("mysecretmysecret".getBytes(), "AES"); 
Cipher cipher = Cipher.getInstance("AES"); 
cipher.init(Cipher.ENCRYPT_MODE, secretKey); 
byte[] outputBytes = cipher.doFinal(read(sampleFile)); 
return outputBytes; 

。私は、これはコンソールで解読さの値として印刷され得る:

W…y.init {words: Array[0], sigBytes: 0} 

私もhereを示唆したが、それでも同じ結果WordArrayにarraybuffer変換しようとしています。 誰かが私を正しい方向に向けることができ、私が間違っていたことを教えてくれるなら、私は喜んでいるでしょう。

編集1: 私はこの問題を解決しました。私が使ったコードは答えとして掲示されています。

+0

"mysecretmysecret"は、おそらくクライアントのソースコード内にそのシークレットが存在する場合、その秘密ではありません。 @AlexK。 –

+0

これは単なるPOCです。まだ実際のコードにはありません。 – Sandeep

+0

文字列をキーとして使用しないで、バイト配列を使用します。文字列からバイト配列への変換はあいまいです(開始時のBoM?ターミネータ\ 0など)。特に、システム間で暗号化されたデータを転送するときは**システムのデフォルトに依存しません。明示的にモード、IV/Nonceなどを設定します。あなたはこれをほとんどやっておらず、システム全体でデフォルトに頼っています。一致しないデフォルト値は問題を引き起こします。 – rossum

答えて

1

レッツ・要約、Javaであなたは

  • AES、
  • ECB(指定されたが、ほとんどの場合、デフォルトではありません!; 、それは安全ではないのです)を使用している、
  • PKCS#7パディング(ないしPKCS#5のパディングと同じです)、
  • (デフォルトのシステムエンコーディングに応じて)16バイトのキーとして16文字のパスワードが使用されます。

キーがCryptoJSに文字列として渡された場合、それは、OpenSSLのEVP_BytesToKey MD5の1ラウンドでの使用を想定パスワードから鍵を導出する必要があります。あなたの暗号文はOpenSSL互換の形式でコード化されていないので、失敗します。事は、あなたはそれを必要としないということです。

次のコードが正しく、Javaから来ている暗号文を解読するだろうが、それは非常に安全ではありません。あなたがいることを含める必要がありますので、ECBモードは、基本的なロールアップに含まれていません

var passwordWords = CryptoJS.enc.Utf8.parse("mysecretmysecret"); 
var decrypted = CryptoJS.AES.decrypt({ 
    ciphertext: CryptoJS.lib.WordArray.create(encryptedData) // or use some encoding 
}, passwordWords, { 
    mode: CryptoJS.mode.ECB 
}); 
console.log(decrypted.toString(CryptoJS.enc.Utf8)); // in case the plaintext is text 

JavaScript fileメインのCryptoJSファイルの後のページで
また、CryptoJSはデフォルトでArrayBufferを処理しません。そのためにはshimを含める必要があります(ソース:this answer)。


これの問題は、その不安です。 ECBモードは非常に安全ではありません。

  • ECB modeを使用しないでください。それは決定論的であり、したがって意味的に安全ではありません。少なくともCBCまたはCTRのようなランダム化モードを使用する必要があります。 IV /ナンスは秘密ではないので、暗号文と共に送ることができます。一般的な方法は、暗号文の前に置くことです。

  • padding oracle attackのような攻撃が不可能になるように暗号文を認証する方が良いです。これは、GCMやEAXなどの認証モード、またはencrypt-then-MACスキームで行うことができます。

  • 鍵はパスワードから派生できますが、PBKDF2などの適切なスキームを使用する必要があります。 JavaとCryptoJSはどちらもこれらをサポートしています。

+0

@Artjomに感謝します。これは単なるPOCであり、私はこれを最小限のコードで解決する必要があります。もちろん、私はECBが最も安全ではないことを知っていますが、もう一度、私は後で頑張ります。 – Sandeep

0

だから私はこれを最終的に解決しました。 Artjomが正しい方向を指してくれてありがとう。 PKCS5PaddingでCBCを使用するようにJavaコードを変更しました。

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
SecretKeySpec myKey = new SecretKeySpec("mysecretmysecret".getBytes(), "AES"); 
IvParameterSpec IVKey = new IvParameterSpec("mysecretmysecret".getBytes()); 
cipher.init(Cipher.ENCRYPT_MODE, myKey, IVKey); 
byte[] outputBytes = cipher.doFinal(read(sampleFile)); 
return outputBytes; 

そして、私のjavascriptをこのように書きます:

​​

decryptedがWordArrayです。

関連する問題