简体   繁体   中英

Encrypt and decrypt with hex string

I searched a lot but I haven't found a good solution how to solve this. I have an app which has to decrypt a long hex string with AES 256.

In order to test it, I created a test method which encrypts a long text into a hex and then convert it back and decrypt it.

If I run this method, I always get the following error: Given final block not properly padded . I receive this error in the decryption method.

The test method looks like so:

@Test
public void testEncAndDecRequestWithHexString() throws UnsupportedEncodingException {
    CryptoHelper cryptoHelper = new CryptoHelper("AES256");
    String paramStr = "ABCB28BCEE5947B8AECE3386871EC0DF&{D5CA99D2-506B-4864-8971-E87821D6B105}&7523429";

    //encrypt the param string
    byte[] paramByteEnc = cryptoHelper.encryptBytesToBytes(paramStr.getBytes("ASCII"), PARAM_KEY, PARAM_IV);

    //convert it to hex
    String encryptedHexStr = cryptoHelper.byteArrayToHexStr(paramByteEnc);

    //convert it back to a byte array
    byte[] encryptedHexBytes = cryptoHelper.hexStrToByteArray(encryptedHexStr);

    // decrypt it
    byte[] paramByteDecrypted = cryptoHelper.decryptBytesToBytes(encryptedHexBytes, encryptedHexBytes.length, PARAM_KEY, PARAM_IV);

    String decryptedStr = new String(paramByteDecrypted);

    assertEquals("ABCB28BCEE5947B8AECE3386871EC0DF&{D5CA99D2-506B-4864-8971-E87821D6B105}&7523429", decryptedStr);
}

The CryptHelper class has following methods:

@Override
public byte[] encryptBytesToBytes(byte[] plainData, byte[] key, byte[] iv) {
    try {
        initCipher(Cipher.ENCRYPT_MODE, key, iv);
        return aesCipher.doFinal(plainData);

    } catch (IllegalBlockSizeException | BadPaddingException e) {
        log.severe(e.getMessage());
    }

    return null;
}    

@Override
public byte[] decryptBytesToBytes(byte[] encryptedBytes, int length,
        byte[] key, byte[] iv) {
    try {
        initCipher(Cipher.DECRYPT_MODE, key, iv);
        return aesCipher.doFinal(encryptedBytes, 0, length);
    } catch (IllegalBlockSizeException | BadPaddingException e) {
        e.printStackTrace();
    }
    return null;
}

private void initCipher(int mode, byte[] keyBytes, byte[] ivBytes) {
    try {

        // create shared secret and init cipher mode
        SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
        aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        aesCipher.init(mode == Cipher.ENCRYPT_MODE ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(ivBytes));
    } catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) {
        e.printStackTrace();
    }
}

public String byteArrayToHexStr(byte[] encrypted) {
    StringBuilder hex = new StringBuilder();
    for (byte b : encrypted) {
        hex.append(String.format("%02X", b));
    }
    return new String(hex.toString());
}

public byte[] hexStrToByteArray(String hex) {
    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < hex.length() - 1; i += 2) {
        String output = hex.substring(i, (i + 2));
        int decimal = Integer.parseInt(output, 16);
        sb.append((char) decimal);
    }

    String temp = sb.toString();
    return temp.getBytes();
}

I used the same key and initialization vector for the decryption process so the problem is not the wrong key or initialization vector. I am also sure that every function here is doing their job correctly. If you don't use the functions hexStrToByteArray() and byteArrayToHexStr() and just use the encrypted byte for decrypting, it works no problem. I think there is a encoding/decoding problem but I have no idea how to handle it in java. If I use getBytes("UTF-8") and new String(byte[], "UTF-8") I get an IllegalBlockSizeException.

I hope you can help me finding out if I am on the right way and what I did wrong.

This is a clear indication that you shouldn't write library functions if they have already been defined. Use a hex codec from Bouncy Castle, Guava or Apache codec instead (until Oracle finally sees the light and provides one in a java.util package).

If you do implement it yourself, please don't mistake characters for bytes:

public byte[] hexStrToByteArray(String hex) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream(hex.length() / 2);

    for (int i = 0; i < hex.length(); i += 2) {
        String output = hex.substring(i, i + 2);
        int decimal = Integer.parseInt(output, 16);
        baos.write(decimal);
    }
    return baos.toByteArray();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM