我正在使用 Java 的实现来实现Zip AESCipher加密。这是我的加密代码:
public final class AesEncoder implements Encoder {
private final Cipher cipher;
private final Mac mac;
private final byte[] salt;
private final byte[] derivedPasswordVerifier;
// AesStrength is an Enum with AES strength constants like salt or mac length
public static AesEncoder create(AesStrength strength, char[] password) throws Exception {
KeySpec spec = new PBEKeySpec(password, salt, 1000, strength.getSize());
SecretKey secretKey = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(spec);
byte[] iv = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secretKey.getEncoded(), "AES"), new IvParameterSpec(iv));
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(new SecretKeySpec(macKey, "HmacSHA1"));
return new AesEncoder(cipher, mac, salt, derivedPasswordVerifier);
}
private static byte[] generateSalt(AesStrength strength) {
SecureRandom random = new SecureRandom();
byte[] buf = new byte[strength.getSaltLength()];
random.nextBytes(buf);
return buf;
}
}
我想加密以下文本:
abcdefghijklmnopqrstuvwxyz
没有细节,我encrypt()
用两个长度为 16 字节的块调用了方法两次:abcdefghijklmnop
和qrstuvwxyz
。我有使用 AES 算法加密的正确 ZIP 文件。
我在任何存档器中打开此 ZIP 文件,例如WinZip
或WinRar
并打开加密文件。结果我有以下文字:
abcdefghijklmnopÄÝB`CÙ∼Wi¯
如您所见,第一个块已正确加密,但第二个块未正确加密。
我调查了这个问题。我找到了一个名为zip4j 的工作解决方案,并发现了两个不同之处:
第一:这个库有自定义 AES 实现AESEngine;我使用jdk实现;
第二:这个库从第一个字节开始增加初始化向量。
第一个块iv = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
第二块iv = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
但是jdk 中使用的com.sun.crypto.provider.CounterMode从末尾递增向量:
第一个块iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
第二块iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
PS如果我设置初始向量iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
哆啦的时光机
相关分类