簡體   English   中英

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

[英]Encrypt and decrypt with hex string

我搜索了很多,但我沒有找到一個很好的解決方案如何解決這個問題。 我有一個應用程序,必須用AES 256解密長十六進制字符串。

為了測試它,我創建了一個測試方法,將長文本加密為十六進制,然后將其轉換回來並解密。

如果我運行此方法,我總是會收到以下錯誤: 給定最終塊未正確填充 我在解密方法中收到此錯誤。

測試方法如下:

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

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

我使用相同的密鑰和初始化向量進行解密過程,因此問題不是錯誤的密鑰或初始化向量。 我也確信這里的每個功能都能正常工作。 如果你不使用函數hexStrToByteArray()和byteArrayToHexStr(),只使用加密的字節進行解密,它沒有問題。 我認為存在編碼/解碼問題,但我不知道如何在java中處理它。 如果我使用getBytes(“UTF-8”)和新的String(byte [],“UTF-8”),我會得到一個IllegalBlockSizeException。

我希望你能幫助我找出我是否正確的方式以及我做錯了什么。

這清楚地表明,如果已經定義了庫函數,則不應該編寫庫函數。 使用來自Bouncy Castle,Guava或Apache編解碼器的十六進制編解碼器(直到Oracle最終看到光並在java.util包中提供一個)。

如果您自己實現它,請不要將字符誤認為字節:

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