Skip to content
Advertisement

openssl_encrypt aes 256 with hash in java

From the php encryption function below:

$data = "1212312121447";
$cipher = "aes-256-ofb";
$secretKey = "aNdRgUjXn2r5u8x/A?D(G+KbPeShVmYp";
$ivLength = openssl_cipher_iv_length($cipher);
$keyOfb = substr(hash('sha256', $secretKey, true), 0, 32);
$ivOfb = substr($keyOfb, 0, $ivLength);
$encryptedOfb = openssl_encrypt($data, $cipher, $keyOfb, OPENSSL_RAW_DATA, $ivOfb);
echo "ofb-encrypted: " . base64_encode($ivOfb . $encryptedOfb);

the result of encryption is MyFTCJx8RPzOx7h8QNxEtQgeiNIRwnrJ+uc0V70=

And I have try to write this function in Java like this:

public static SecretKeySpec hashKey(String key){
        String keyPass = key;
        SecretKeySpec result = null;
        try{
                MessageDigest md = MessageDigest.getInstance("SHA-256");
                md.update(keyPass.getBytes());
                byte[] AesKeyData = Arrays.copyOfRange(md.digest(), 0, 32);
                SecretKeySpec keySpec = new SecretKeySpec(AesKeyData, "AES");
                result = keySpec;
                
        }
        catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return result;
    }

public static String encryptedOFB(String inp){
        String result = "";
        String key = "aNdRgUjXn2r5u8x/A?D(G+KbPeShVmYp";
        SecretKeySpec keyHashed = hashKey(key);
        try{
            byte[] initVectorSize = Arrays.copyOfRange(keyHashed.toString().getBytes(), 0, 16);
            Cipher cipher = Cipher.getInstance("AES/OFB/NoPadding");
            
            IvParameterSpec iv = new IvParameterSpec(initVectorSize, 0, cipher.getBlockSize());
            cipher.init(Cipher.ENCRYPT_MODE, keyHashed, iv);
            
            byte[] encrypted = cipher.doFinal(inp.getBytes());
            
            ByteArrayOutputStream conc = new ByteArrayOutputStream();
            conc.write(initVectorSize);
            conc.write(encrypted);
            byte[] concEnc = conc.toByteArray();

            result = new String(Base64.getEncoder().encode(concEnc));
            
        }
        catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return result;
    }

The result is amF2YXguY3J5cHRvLnNwZYUmrJNv8ycvLua0O9g=

Why my java function return the different result from php?

And how do I fix the java function to get the same result with php?

Thank you.

Advertisement

Answer

The IV is determined wrongly. Instead of keyHashed.toString().getBytes() you have to use keyHashed.getEncoded(). Then you get the result of the PHP code.

Apart from that, your key derivation is insecure: since the IV is the first 16 bytes of the key, the same password also means the same key/IV pair, which is insecure. For passwords, it is better to use a reliable key derivation function in conjunction with a randomly generated salt. The IV can be inferred along with the key or randomly generated independently. Salt (or IV) are not secret and can be passed with the ciphertext for decryption, usually concatenated.

When encoding (e.g. inp.getBytes()), the encoding should always be specified (e.g. StandardCharsets.UTF_8). Likewise with the decoding (new String(..., StandardCharsets.UTF_8)). Otherwise the default encoding is used, which can cause cross-platform problems.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement