Java encryption: what algorithms should I use?

I am working on a program that should store binary information encrypted at rest. Unfortunately, I cannot find a resource that explains which encryption schemes are best suited for different applications.

Since encryption is complex, and I'm not an expert, I decided to use a library called Jasypt , which wraps the Java construct in encryption functions. To find out which algorithms are available to me, I wrote several unit tests.

The first test calls the Jasypt AlgorithmRegistry.getAllPBEAlgorithms() function and lists all available encryption algorithms:

 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 

At run time, Jasypt will throw an EncryptionOperationNotPossibleException if you try to use an algorithm that for some reason is not supported or does not violate Java encryption rules. Interestingly, if I try to use each of the available algorithms for encryption, and then decrypt some arbitrary data and print only those that do not throw this exception, I get this short list:

 PBEWITHMD5ANDDES PBEWITHSHA1ANDDESEDE PBEWITHSHA1ANDRC2_128 PBEWITHSHA1ANDRC2_40 PBEWITHSHA1ANDRC4_128 PBEWITHSHA1ANDRC4_40 

The list of available algorithms can be expanded by pulling the BouncyCastle JCE and registering it by executing Security.addProvider(new BouncyCastleProvider()) . If I repeat the previous test after this, I get a much larger list of algorithms to choose from:

 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 

Unfortunately, now I do not know which of these algorithms is most suitable for my application. I have a suspicion that AES is the right way, and it looks like PBEWITHSHA256AND256BITAES-CBC-BC is the AES implementation with the longest key length, but I don’t know where to go to confirm this suspicion.

Which of these schemes will provide the highest levels of security and which have obvious security concerns?

EDIT:. I want to be able to distribute my code without requiring the end user to install unlimited cryptography files, as this will almost certainly be beyond the capabilities of less experienced users. What I really want is the strongest encryption I can get without using files of unlimited strength.

+5
source share
2 answers

First of all, you must install unlimited cryptography files from Oracle. After that, you should have less EncryptionOperationNotPossibleException , and higher security levels should become available.

Also, for the highest level encryption, I would not use JaSypt at all, because it does not seem to provide any integrity check or authentication of the ciphertext . For just privacy, which does not seem to matter. But in practice, you will need to test this against your threat model.

If you decide to use JaSypt (which I personally don’t like), you should probably go to PBEWITHHMACSHA512ANDAES_256 as the highest level opportunity. Make sure you understand PBKDF2 and the working factors (number of iterations, e.g. setKeyObtentionIterations .

You do not need Bouncy Castle. AES is considered safe; everything Bouncy Castle does - for your example, which uses JaSypt - adds obscure ciphers. In the above list, everything except AES is less secure than AES.

+3
source

The original question you had was how to encrypt the data. Which algorithm to use and which java library?

 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
source

Source: https://habr.com/ru/post/1244057/


All Articles