2016-02-28 60 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實現,但我不知道該去哪裏去確認這個懷疑。

這些方案中的哪一個可以提供最高的安全級別並且存在明顯的安全問題?

編輯:我希望能夠無需最終用戶安裝無限的加密文件分發給我的代碼,因爲這幾乎肯定會超越不那麼精通技術的用戶的能力。我真正想要的是我可以在不使用無限強度管轄區文件的情況下獲得最強大的加密。

+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 s和更高的安全等級應該可用。

此外,對於最高級別的加密可能,我根本不會使用JaSypt,因爲it doesn't seem to provide any integrity checking or authentication of ciphertext。只是保密,不似乎重要。但在實踐中,您需要檢查一下您的威脅模型。

如果您決定使用JaSypt(我個人不喜歡),您應該選擇PBEWITHHMACSHA512ANDAES_256作爲最高級別的可能性。確保你瞭解PBKDF2和工作因素(迭代次數,例如:setKeyObtentionIterations

你不需要Bouncy Castle。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提供的附加功能),但請注意,有許多方法可以加密某些東西,如果有人發佈關於JaSypt的問題,新的加密方法在我看來並不是真正的答案,但我會在第二次去除更多的權利的時候刪除我的downvote。 –

相關問題