我的任务是使用AES / GCM的特殊功能来验证A部分并加密单个数据块的B部分。我在使用Java-8实现解决方案时遇到了问题。
以下示例使用256位的数据块。第一个128位只能进行身份验证。以下128位应加密。组合操作的结果标记应为128位。
我相信我能够实现一种仅加密的变体,它可以加密两个128位数据块。
SecureRandom random = new SecureRandom();
byte[] initVector = new BigInteger(96, random).toByteArray();
byte[] data = new BigInteger(255, random).toByteArray();
byte[] key = new BigInteger(255, random).toByteArray();
byte[] encrypted = new byte[data.length];
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new GCMParameterSpec(16 * Byte.SIZE, initVector));
cipher.update(data, 0, data.length, encrypted, 0);
byte[] tag = cipher.doFinal();
是否有人可以提供有关如何修改代码的说明,以便只对前128位数据进行身份验证?
答案 0 :(得分:3)
您需要使用其中一个updateAAD
methods。
在您的情况下,类似这样的事情(请注意,您需要在 updateAAD
或update
来电之前进行doFinal
来电:
cipher.updateAAD(data, 0, 128); // first 128 bits are authenticated
cipher.update(data, 128, 128, encrypted, 0); // next 128 are encrypted
答案 1 :(得分:1)
马特是对的,你需要使用updateAAD
。但是还有很多其他问题。
例如,您不能只使用BigInteger
创建随机值。问题是,对于某些值,左侧会有一个额外的00
值(用于编码无符号整数),有时则不是。如果数量很小,它也可能产生太少的字节。
此外,在Java中,标签被认为是密文的一部分。在我看来这是一个错误,它真的会伤害功能。但目前就是这样。
更好的编程方法是这样的:
// --- create cipher
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
// --- generate new AES key
KeyGenerator aesKeyGen = KeyGenerator.getInstance("AES");
aesKeyGen.init(256);
SecretKey aesKey = aesKeyGen.generateKey();
// --- generate IV and GCM parameters
SecureRandom random = new SecureRandom();
byte[] initVector = new byte[96 / Byte.SIZE];
random.nextBytes(initVector);
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, initVector);
cipher.init(Cipher.ENCRYPT_MODE, aesKey,
gcmParameterSpec);
// --- process any AAD (just a bunch of zero bytes in this example)
byte[] aad = new byte[128];
cipher.updateAAD(aad);
// --- process any data (just a bunch of zero bytes in this example)
byte[] data = new byte[128];
// use cipher itself to create the right buffer size
byte[] encrypted = new byte[cipher.getOutputSize(data.length)];
int updateSize = cipher.update(data, 0, data.length, encrypted, 0);
cipher.doFinal(encrypted, updateSize);
它以不同方式生成所有参数,并通过Cipher
实例动态确定输出缓冲区的大小。