加密 - IV长度与提供的不同

时间:2012-12-12 14:48:09

标签: java encryption jce

我一直在努力加密加密一段时间,我即将完成这个过程,但是,我现在遇到了一些问题。这是我的代码:

IV代

public static byte[] createIV(int size) { 
 byte[] iv = new byte[size];
 SecureRandom random = new SecureRandom();
 random.nextBytes(iv);   

 return iv; 
}

AES-256密码创建(密钥)

public static Map<String, byte[]> cipherAES() throws NoSuchAlgorithmException {
     Map<String, byte[]> aes = new HashMap<String, byte[]>();
     aes.put("IV", ConversionUtil.toHex(createIV(16), 16).getBytes());
     KeyGenerator keyGen = KeyGenerator.getInstance("AES");
     keyGen.init(256);
     Key encryptionKey = keyGen.generateKey();
     aes.put("key", encryptionKey.getEncoded());

     return aes;
}

toHex方法

public static String toHex(byte[] data, int length) {
     StringBuffer buf = new StringBuffer();

     for (int i = 0; i != length; i++) {
        int v = data[i] & 0xff;

        buf.append(DIGITS.charAt(v >> 4));
        buf.append(DIGITS.charAt(v & 0xf));
     }

        return buf.toString();
}

密码初始化

  SecretKey key = new SecretKeySpec(map.get("key"), 0, map.get("key").length, "AES");
  Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
  cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(map.get("IV"), 0, 16));

如果我使用这种格式向密码提供16字节的IV:

8E12399C07726F5A8E12399C07726F5A

当我在Cipher上调用getIV方法时,我得到了这个:

8E12399C07726F5A

这正是我为IV提供的字节的一半。这当前导致了几个问题,因为服务器可以解密消息的第二部分而不是第一部分。

我只使用JCE库:

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

有人可以对此有所了解吗?如果您需要更多详细信息,请与我们联系。

1 个答案:

答案 0 :(得分:1)

正如CodesInChaosbimsapi的评论中所提到的,您的错误在于您将IV值转换为十六进制。对cipherAES()方法的简单修正是:

public static Map<String, byte[]> cipherAES() throws NoSuchAlgorithmException {
     Map<String, byte[]> aes = new HashMap<String, byte[]>();
     aes.put("IV", createIV(16)); // <-- no need for conversion
     KeyGenerator keyGen = KeyGenerator.getInstance("AES");
     keyGen.init(256);
     Key encryptionKey = keyGen.generateKey();
     aes.put("key", encryptionKey.getEncoded());
     return aes;
}

另请注意,您的方法设计有点奇怪。将字符串映射返回到字节数组是非常脆弱的并且容易出错。请考虑返回存储这些项的对象。在该对象中,我将密钥存储为Key,而不是字节数组。