随机访问AES CTR模式有一个很好的例子,它有效: Random access InputStream using AES CTR mode in android
private static final int AES_BLOCK_SIZE = 16;
private static IvParameterSpec calculateIVForOffset(final IvParameterSpec iv,
final long blockOffset) {
final BigInteger ivBI = new BigInteger(1, iv.getIV());
final BigInteger ivForOffsetBI = ivBI.add(BigInteger.valueOf(blockOffset
/ AES_BLOCK_SIZE));
final byte[] ivForOffsetBA = ivForOffsetBI.toByteArray();
final IvParameterSpec ivForOffset;
if (ivForOffsetBA.length >= AES_BLOCK_SIZE) {
ivForOffset = new IvParameterSpec(ivForOffsetBA, ivForOffsetBA.length - AES_BLOCK_SIZE,
AES_BLOCK_SIZE);
} else {
final byte[] ivForOffsetBASized = new byte[AES_BLOCK_SIZE];
System.arraycopy(ivForOffsetBA, 0, ivForOffsetBASized, AES_BLOCK_SIZE
- ivForOffsetBA.length, ivForOffsetBA.length);
ivForOffset = new IvParameterSpec(ivForOffsetBASized);
}
return ivForOffset;
}
但是,它不适用于AES GCM模式。解密时我得到垃圾。我不是加密专家,并且已经试图破解它几天了。也许任何人都可以提供任何见解?我的猜测我需要以某种方式更改偏移量的IV计算,或者它与auth Tag(我没有使用)有关。
答案 0 :(得分:3)
GCM模式使用计数器模式进行保密。因此可以在没有认证的情况下解密密文;看看我的回答here。要从给定的偏移量加密或解密,您可以更改计数器以更改给定偏移量的字节,并对生成的密文进行异或。但是,如果您跳过一个字节,则无法验证任何密文。
因此,对于GCM,最好将明文分成块并分别加密。
答案 1 :(得分:0)
AES GCM使用一种称为GCTR的模式。它类似于CTR,但定义在非常specific way中。
当IV不为12个字节时,首先对其进行哈希处理以得到12个字节的IV(GHASH函数被指定为与Galois字段的一次乘法,与MAC相同)。
然后将12字节的IV与4字节的计数器(从1开始)连接起来,以获得16字节的CTR块。
因此,像您在示例中那样将IV视为BigInteger
并将其递增肯定是行不通的。