ArmCloudAF/app/src/main/java/com/bjlx/armcloudaf/AESPatchHelper.java

81 lines
3.0 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.bjlx.armcloudaf;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class AESPatchHelper {
private static final byte[] SALT = new byte[8]; // 全零 salt
private static final int PADDING_LEN = 8;
private static final int IV_LEN = 16;
public static byte[] extractIV(byte[] data) {
int ivPos = data.length - PADDING_LEN - IV_LEN;
return Arrays.copyOfRange(data, ivPos, ivPos + IV_LEN);
}
public static byte[] extractPadding(byte[] data) {
int padPos = data.length - PADDING_LEN - IV_LEN - PADDING_LEN;
if (padPos < 0) padPos = data.length - PADDING_LEN - IV_LEN;
return Arrays.copyOfRange(data, data.length - PADDING_LEN - IV_LEN, data.length - IV_LEN);
}
public static byte[] extractCiphertext(byte[] data) {
int ctLen = data.length - PADDING_LEN - IV_LEN;
return Arrays.copyOfRange(data, 0, ctLen);
}
private static SecretKeySpec deriveKey(String password) throws Exception {
return new SecretKeySpec(
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")
.generateSecret(new PBEKeySpec(password.toCharArray(), SALT, 10000, 128))
.getEncoded(),
"AES"
);
}
public static byte[] decryptRaw(byte[] ciphertext, byte[] iv, String password) throws Exception {
SecretKeySpec key = deriveKey(password);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
return cipher.doFinal(ciphertext);
}
public static byte[] encryptRaw(byte[] plaintext, byte[] iv, String password) throws Exception {
SecretKeySpec key = deriveKey(password);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
return cipher.doFinal(plaintext);
}
/**
* 入口函数:
* 提取 data 中 IV + padding + 密文 → 解密 → 加密 → 再拼装成结构化数据
*/
public static byte[] patchAndReEncrypt(byte[] data, String password) throws Exception {
if (data == null || data.length <= (PADDING_LEN + IV_LEN)) return null;
byte[] iv = extractIV(data);
byte[] padding = extractPadding(data);
byte[] ciphertext = extractCiphertext(data);
// 解密
byte[] plaintext = decryptRaw(ciphertext, iv, password);
// 可在此修改 plaintext如篡改某些字段
// 再加密
byte[] newCiphertext = encryptRaw(plaintext, iv, password);
// 拼装为结构:[newCiphertext] + [padding] + [iv]
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(newCiphertext);
out.write(padding);
out.write(iv);
return out.toByteArray();
}
}