Question

I have a RESTful API written in Java and I want to protect the external configuration file of that API.

I'm trying to protect it with the following symmetric ciphering method:

private final static String passPhrase = "My Super Ultra Passphrase";
private final static byte[] salt = "My Super Ultra Salt".getBytes();
private final static int iterations = 8192;
private static String strIv = "";

private static String encryptText(String text) {
    String result = "";
    try {
        // create the key for encryption
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        SecretKey secret = factory.generateSecret(
                new PBEKeySpec(passPhrase.toCharArray(), salt, iterations, 128));
        SecretKeySpec key = new SecretKeySpec(secret.getEncoded(), "AES");

        // encrypts the text
        Cipher aes = Cipher.getInstance("AES/CBC/PKCS5Padding");
        aes.init(Cipher.ENCRYPT_MODE, key);
        byte[] cipherText = aes.doFinal(text.getBytes());
        byte[] iv = aes.getIV();

        result = new String(Base64.encode(cipherText));
        strIv = new String(Base64.encode(iv));

    } catch (NoSuchAlgorithmException 
            | InvalidKeySpecException 
            | NoSuchPaddingException 
            | InvalidKeyException 
            | IllegalBlockSizeException 
            | BadPaddingException e) {
        e.printStackTrace();
    }
    return result;
}

private static String decryptText(String text) {
    String result = "";
    try {
        // create the key for decryption
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        SecretKey secret = factory.generateSecret(
                new PBEKeySpec(passPhrase.toCharArray(), salt, iterations, 128));
        SecretKeySpec key = new SecretKeySpec(secret.getEncoded(), "AES");

        byte[] iv = Base64.decode(strIv);
        byte[] cipherText = Base64.decode(text);

        // decrypt the text
        Cipher aes = Cipher.getInstance("AES/CBC/PKCS5Padding");
        aes.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
        result = new String(aes.doFinal(cipherText));

    } catch (NoSuchAlgorithmException 
            | InvalidKeySpecException 
            | NoSuchPaddingException 
            | InvalidKeyException 
            | IllegalBlockSizeException 
            | BadPaddingException 
            | InvalidAlgorithmParameterException
            | Base64DecodingException e) {
        e.printStackTrace();
    }
    return result;
}

My question is: Is this code fairly strong?

Was it helpful?

Solution

Exactly against which attack scenario are you trying to defend yourself? I'm going to answer making some assumptions, please correct if I'm wrong.

If you want to protect the configuration file, then you are trying to defend against an attacker who has already gained read access to your server files. In this scenario, this attacker may as well download the program itself and extract the key with a debugger, as it is hardcoded. It is an extra layer of defense, that could make some attackers give up, but will only delay others.

Hope it helps.

OTHER TIPS

Well, that's pretty hard to answer. Currently neither your IV nor your salt is randomized, so that's certainly an error, one that is easy to fix. You do add an authentication tag so your configuration may not be read (stays confidential), but it might be changed. If you go from one system to another you may get different results on String.getBytes(), so that could be a non-security related issue.

On the other hand, using PBKDF2 and AES in CBC mode is probably a good idea. 8Ki iterations may not be enough if you keep to those kind of pass phrases though.

Note that I was assuming that the password was not actually a static string, please look at the answer of jspurim if that is the case.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top