2016-02-28 20 views
5

私は残りの部分で暗号化されたバイナリ情報を格納する必要があるプログラムに取り組んでいます。残念ながら、さまざまなアプリケーションに最適な暗号化方式を説明するリソースを見つけることはできません。Java暗号化:どのアルゴリズムを使用すべきですか?

暗号化が複雑で、専門家ではないので、私はJasyptというライブラリにJavaの組み込み暗号化機能をラップすることにしました。利用可能なアルゴリズムを理解するために、私はいくつかの単体テストを書きました。

最初のテストはJasyptのAlgorithmRegistry.getAllPBEAlgorithms()関数を呼び出し、すべての利用可能な暗号化アルゴリズムを示しています

PBEWITHHMACSHA1ANDAES_128 
PBEWITHHMACSHA1ANDAES_256 
PBEWITHHMACSHA224ANDAES_128 
PBEWITHHMACSHA224ANDAES_256 
PBEWITHHMACSHA256ANDAES_128 
PBEWITHHMACSHA256ANDAES_256 
PBEWITHHMACSHA384ANDAES_128 
PBEWITHHMACSHA384ANDAES_256 
PBEWITHHMACSHA512ANDAES_128 
PBEWITHHMACSHA512ANDAES_256 
PBEWITHMD5ANDDES 
PBEWITHMD5ANDTRIPLEDES 
PBEWITHSHA1ANDDESEDE 
PBEWITHSHA1ANDRC2_128 
PBEWITHSHA1ANDRC2_40 
PBEWITHSHA1ANDRC4_128 
PBEWITHSHA1ANDRC4_40 

実行時にあなたには、いくつかの理由でサポートされたりされていないアルゴリズムを使用しようとすると、JasyptはEncryptionOperationNotPossibleExceptionをスローしますJavaの暗号化ルールに違反します。

PBEWITHMD5ANDDES 
PBEWITHSHA1ANDDESEDE 
PBEWITHSHA1ANDRC2_128 
PBEWITHSHA1ANDRC2_40 
PBEWITHSHA1ANDRC4_128 
PBEWITHSHA1ANDRC4_40 
:私は暗号化し、その後、いくつかの任意のデータを復号化するために「利用可能」なアルゴリズムのそれぞれを使用し、それだけで例外をスローしないものをプリントアウトしようとすると、興味深いことに、私は、このスリムダウンリストを得ます

利用可能なアルゴリズムのリストは、BouncyCastle JCEをプルしてSecurity.addProvider(new BouncyCastleProvider())を実行して登録することで拡張できます。私はこれを実行した後、以前のテストを繰り返した場合、私はから選択するアルゴリズムのはるかに大きなリストを取得:

PBEWITHMD2ANDDES 
PBEWITHMD5AND128BITAES-CBC-OPENSSL 
PBEWITHMD5AND192BITAES-CBC-OPENSSL 
PBEWITHMD5AND256BITAES-CBC-OPENSSL 
PBEWITHMD5ANDDES 
PBEWITHMD5ANDRC2 
PBEWITHSHA1ANDDES 
PBEWITHSHA1ANDDESEDE 
PBEWITHSHA1ANDRC2 
PBEWITHSHA1ANDRC2_128 
PBEWITHSHA1ANDRC2_40 
PBEWITHSHA1ANDRC4_128 
PBEWITHSHA1ANDRC4_40 
PBEWITHSHA256AND128BITAES-CBC-BC 
PBEWITHSHA256AND192BITAES-CBC-BC 
PBEWITHSHA256AND256BITAES-CBC-BC 
PBEWITHSHAAND128BITAES-CBC-BC 
PBEWITHSHAAND128BITRC2-CBC 
PBEWITHSHAAND128BITRC4 
PBEWITHSHAAND192BITAES-CBC-BC 
PBEWITHSHAAND2-KEYTRIPLEDES-CBC 
PBEWITHSHAAND256BITAES-CBC-BC 
PBEWITHSHAAND3-KEYTRIPLEDES-CBC 
PBEWITHSHAAND40BITRC2-CBC 
PBEWITHSHAAND40BITRC4 
PBEWITHSHAANDIDEA-CBC 
PBEWITHSHAANDTWOFISH-CBC 

を残念ながら、今私は、これらの多くのアルゴリズムを自分のアプリケーションに最も適切な見当がつかない。私はAESが正しい方法であることを暗示しています。そして、それはPBEWITHSHA256AND256BITAES-CBC-BCが最も長いキーの長さを持つAES実装ですが、その疑惑を確認するためにどこに行くべきか分かりません。

これらのスキームの中で、最も高いセキュリティレベルを提供し、明らかなセキュリティ問題があるものはどれですか?

EDIT:それはほぼ確実にそうハイテクない精通したユーザーの能力を超えるだろうと私は、無制限の暗号化ファイルをインストールするために、エンドユーザを必要とせずに自分のコードを配布することができるようにしたいです。私が本当に望むのは、無制限の強さの管轄権ファイルを使わずに得ることができる最も強力な暗号化です。

+0

ないでください。すべての正しい決定を行うラッパー・ライブラリーを使用してください。 http://blog.slaks.net/2015-11-18/common-crypto-pitfalls/ – SLaks

+1

質問を変更して、どのスキームが「最高のセキュリティレベル」を提供しているかを直接説明しました。オフサイトの説明/指示を求めることはトピックから外れており、「最高」は主観的なものであることを求めています。どちらも問題を終わらせる理由になります。 –

+0

ライブラリは必要ありません。あまりにもJava APIを使用することは難しくありません。私の例 - https://gist.github.com/zhong-j-yu/9d23c850e580d60ddd46 – ZhongYu

答えて

3

まず、Oracleから無制限の暗号化ファイルをインストールする必要があります。その後、少ない数のEncryptionOperationNotPossibleExceptionがあり、より高いセキュリティレベルが利用可能になるはずです。

さらに、最高レベルの暗号化が可能な場合は、it doesn't seem to provide any integrity checking or authentication of ciphertextのため、私はJaSyptをまったく使用しません。守秘義務のためにと思われます。しかし実際には、あなたの脅威モデルに対してそれをチェックする必要があります。

私が個人的に嫌いなJaSyptを使用することに決めたら、PBEWITHHMACSHA512ANDAES_256の可能性が最も高いと思われます。 PBKDF2と作業要素(反復回数、例:setKeyObtentionIterations

)を理解することを忘れないでください。AESは安全であるとみなされ、Bouncy CastleはすべてJaSyptを使用する例ではわかりにくい暗号を追加しています。上記のリスト、AES以外のものはすべてAESより安全性が低くなります。

+0

私の場合、エンドユーザーが無制限の暗号化ファイルをインストールする必要なく、自分のコードを配布できるようにしたいという問題があります。これは技術に精通していないユーザーの能力をはるかに超えているためです。 私が本当に望むのは、無制限の強さの管轄権ファイルを使用せずに得ることができる最も強力な暗号化です。おそらく私は多くのことを言うために質問を編集する必要があります。 – MusikPolice

+0

はい、そうすべきです。デフォルトでAES 128アルゴリズムが利用できないランタイムは何ですか? –

+0

私はOracleの標準Java 8 JDKを実行しています。これにはAES 128アルゴリズムがありますが、実際に使用しようとすると例外が発生します。 – MusikPolice

-2

元の質問は、データを暗号化する方法でした。どのようなアルゴリズムを使用すると、どのJavaライブラリですか?

package cryptography; 

import java.security.AlgorithmParameters; 
import java.security.InvalidAlgorithmParameterException; 
import java.security.InvalidKeyException; 
import java.security.Key; 
import java.security.NoSuchAlgorithmException; 
import java.security.spec.InvalidKeySpecException; 
import java.security.spec.InvalidParameterSpecException; 
import java.security.spec.KeySpec; 

import javax.crypto.Cipher; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.SecretKey; 
import javax.crypto.SecretKeyFactory; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.PBEKeySpec; 
import javax.crypto.spec.SecretKeySpec; 

import java.util.Base64; 
import java.util.Base64.Decoder; 
import java.util.Base64.Encoder; 

public class BasicAESEncrypt { 
private final byte[] SALT = { 
     (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32, 
     (byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03 
    }; 

private Cipher ecipher; 
private Cipher dcipher; 
Encoder encoder = Base64.getEncoder(); 
Decoder decoder = Base64.getDecoder(); 


BasicAESEncrypt(String password) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, InvalidAlgorithmParameterException{ 
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 

    KeySpec spec = new PBEKeySpec(password.toCharArray(), SALT, 65536, 256); 
    SecretKey tmp = factory.generateSecret(spec);   

    SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); 

    ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    ecipher.init(Cipher.ENCRYPT_MODE, secret); 

    AlgorithmParameters params = ecipher.getParameters(); 
    byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV(); 

    dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv)); 
} 

public String encrypt(String encrypt) throws Exception { 
    byte[] bytes = encrypt.getBytes("UTF8"); 
    byte[] encrypted = encrypt(bytes); 
    return encoder.encodeToString(encrypted); 
} 

public byte[] encrypt(byte[] plain) throws Exception { 
    return ecipher.doFinal(plain); 
} 

public String decrypt(String encrypt) throws Exception { 
    byte[] decodedData = decoder.decode(encrypt); 
    byte[] decrypted = decrypt(decodedData); 
    return new String(decrypted, "UTF8"); 
} 

public byte[] decrypt(byte[] encrypt) throws Exception { 
    return dcipher.doFinal(encrypt); 
} 

public static void main(String[] args) throws Exception { 
    String message = "Wire message for encryption"; 
    String password = "TopSecretKey"; 

    try { 
     BasicAESEncrypt app = new BasicAESEncrypt(password); 

     String encrypted = app.encrypt(message); 
     System.out.println("Encrypted string is: " + encrypted); 

     String decrypted = app.decrypt(encrypted); 
     System.out.println("Decrypted string is: " + decrypted); 
    } catch (InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException 
      | InvalidParameterSpecException | InvalidAlgorithmParameterException e1) { 
     e1.printStackTrace(); 
    } 
    try { 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

}

+2

静的でない塩を使用すると、JaSyptが提供できるセキュリティとほぼ同じレベルのセキュリティが達成されます。その意味では、以前に投稿したものよりもはるかに優れています(ただし、JaSyptが提供する追加機能を実装していないという点を除いては同じですが、何かを暗号化する方法はたくさんあることに注意してください。私の意見では、新しい暗号化方法は実際には答えではありません。 –

関連する問題