1 回答

TA贡献1779条经验 获得超6个赞
我已经解决了这个问题。问题是 java 的 AES 实现与 ZIP 标准有点不同。
我已经使用 java类在我的zip4jvmCypher库中实现了 AES 加密:
class AesEncoder {
public static AesEncoder create(AesStrength strength, char[] password) {
try {
byte[] salt = strength.generateSalt();
byte[] key = AesEngine.createKey(password, salt, strength);
Cipher cipher = AesEngine.createCipher(strength.createSecretKeyForCipher(key));
Mac mac = AesEngine.createMac(strength.createSecretKeyForMac(key));
byte[] passwordChecksum = strength.createPasswordChecksum(key);
return new AesEncoder(cipher, mac, salt, passwordChecksum);
} catch(Exception e) {
throw new Zip4jvmException(e);
}
}
}
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
enum AesStrength {
S128(128),
S192(192),
S256(256);
private final int size;
public final int saltLength() {
return size / 16;
}
private int macLength() {
return size / 8;
}
private int keyLength() {
return size / 8;
}
public SecretKeySpec createSecretKeyForCipher(byte[] key) {
return new SecretKeySpec(key, 0, keyLength(), "AES");
}
public SecretKeySpec createSecretKeyForMac(byte[] key) {
return new SecretKeySpec(key, keyLength(), macLength(), "HmacSHA1");
}
public byte[] createPasswordChecksum(byte[] key) {
final int offs = keyLength() + macLength();
return new byte[] { key[offs], key[offs + 1] };
}
public byte[] generateSalt() {
SecureRandom random = new SecureRandom();
byte[] buf = new byte[saltLength()];
random.nextBytes(buf);
return buf;
}
}
class AesEngine {
private static final int ITERATION_COUNT = 1000;
public static byte[] createKey(char[] password, byte[] salt, AesStrength strength) throws NoSuchAlgorithmException, InvalidKeySpecException {
int keyLength = strength.getSize() * 2 + 16;
KeySpec keySpec = new PBEKeySpec(password, salt, ITERATION_COUNT, keyLength);
return SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(keySpec).getEncoded();
}
public static Cipher createCipher(SecretKeySpec secretKeySpec) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException {
Cipher cipher = Cipher.getInstance("AES");
// use custom AES implementation, so no worry for DECRYPT_MODE
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
return cipher;
}
public static Mac createMac(SecretKeySpec secretKeySpec) throws NoSuchAlgorithmException, InvalidKeyException {
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(secretKeySpec);
return mac;
}
}
添加回答
举报