0

我想用 AES 加密和解密整数,但无法进行。

为了测试基本的加密过程,我编写了一个简单的方法,它接受输入数据,使用相同的参数对其进行加密和解密,然后返回结果。

这是我失败的 JUnit 测试用例,它检查输入和输出数据是否相等。

    @Test
public void test4() throws UnsupportedEncodingException {

    Random random = new Random();

    SecretKey secretKey = Tools.generateKey("secretKey".getBytes("UTF-8"));

    byte[] initializationVector = Tools.intToByteArray(random.nextInt()); 
    // ensuring that the initialization vector has the correct length
    byte[] ivHash = Tools.hashMD5(initializationVector);

    int value = random.nextInt();
    byte[] input = Tools.intToByteArray(value);

    byte[] received = Tools.enDeCrypt(input, secretKey, ivHash);        
    assertEquals(data.hashCode(), received.hashCode());
}

方法生成密钥:

public static SecretKeySpec generateKey(byte[] secretKey) {

    try {
        // 256 bit key length
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(secretKey);
        byte[] key = md.digest();
        return new SecretKeySpec(key, "AES");
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    }
}

int -> byte[] 转换方法:

public static byte[] intToByteArray(int a) {
    // block size is 128 bit, thus I append zeros 

    byte[] intByte = ByteBuffer.allocate(4).putInt(a).array();
    byte[] longerIntByte = new byte[16];
    for (int i = 0; i < 4; i++) {
        longerIntByte[i] = intByte[i];
    }
    for (int i = 4; i < longerIntByte.length; i++) {
        longerIntByte[i] = 0;
    }
    return longerIntByte;
}

下面是加解密的代码:

public static byte[] enDeCrypt(byte[] data, SecretKey secretKey,
        byte[] initialisationVector) {

    try {
        IvParameterSpec ivSpec = new IvParameterSpec(initialisationVector);
        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");

        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
        byte[] encrypted = cipher.doFinal(data);

        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
        byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;

    } catch (NoSuchAlgorithmException | NoSuchPaddingException
            | InvalidKeyException | InvalidAlgorithmParameterException
            | IllegalBlockSizeException | BadPaddingException e) {
        throw new RuntimeException(e);
    }

}
4

1 回答 1

4

assertEquals(data.hashCode(), received.hashCode())data除非和received引用同一个对象,否则不太可能通过(因为字节数组从 Object 继承标识哈希码方法)。我不知道data从哪里来,但这里可能不是这种情况。你应该使用Arrays.equals(data, received).

除此之外,这里还有各种加密问题:

  • 随机对于加密目的来说不够“随机”;你应该使用 SecureRandom。
  • 使用普通 SHA-256 的密钥派生是可疑的。您应该考虑使用专门为此设计的密钥派生算法,例如 PBKDF2。
  • 具有 256 位密钥的 AES 并不总是优于 128 位密钥。检查这个页面。在这种情况下,它完全是伪造的,因为密码短语甚至很少达到 128 位的熵。
  • 随机 IV - 很好,但是当您可以直接使用 SecureRandom.nextBytes() 时,为什么要跳过箍。散列 IV 不会增加任何有用的东西。
  • 当您可以让库处理它时,没有理由进行手动零填充。只需指定 PKCS5Padding 而不是 NoPadding。
于 2013-06-23T15:41:04.887 回答