亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

ZIP 文件的 AES 加密不正確的第二個 16 字節塊

ZIP 文件的 AES 加密不正確的第二個 16 字節塊

慕斯709654 2023-06-04 17:52:30
我正在使用 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 }
查看完整描述

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;

? ? }


}


查看完整回答
反對 回復 2023-06-04
  • 1 回答
  • 0 關注
  • 166 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號