简体   繁体   English

使用十六进制字符串加密和解密

[英]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. 我有一个应用程序,必须用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: CryptHelper类有以下方法:

@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. 如果你不使用函数hexStrToByteArray()和byteArrayToHexStr(),只使用加密的字节进行解密,它没有问题。 I think there is a encoding/decoding problem but I have no idea how to handle it in java. 我认为存在编码/解码问题,但我不知道如何在java中处理它。 If I use getBytes("UTF-8") and new String(byte[], "UTF-8") I get an IllegalBlockSizeException. 如果我使用getBytes(“UTF-8”)和新的String(byte [],“UTF-8”),我会得到一个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). 使用来自Bouncy Castle,Guava或Apache编解码器的十六进制编解码器(直到Oracle最终看到光并在java.util包中提供一个)。

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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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