You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hkbak/imgdec.js

327 lines
9.7 KiB

(function() {
//by LoyDgIk
const jvString = java.lang.String;
const jvArray = java.lang.reflect.Array;
const Byte = java.lang.Byte;
const Integer = java.lang.Integer;
const StandardCharsets = java.nio.charset.StandardCharsets;
const MessageDigest = java.security.MessageDigest;
const Base64 = android.util.Base64;
const StringBuffer = java.lang.StringBuffer;
const Cipher = javax.crypto.Cipher;
const IvParameterSpec = javax.crypto.spec.IvParameterSpec;
const SecretKeySpec = javax.crypto.spec.SecretKeySpec;
const FileUtil = com.example.hikerview.utils.FileUtil;
//CryptoUtil
//互转类
function Data(bytes) {
this.bytes = bytes;
this.length = bytes.length;
}
Object.assign(Data, {
parseStr(str, charset) {
return new Data(toJvString(str).getBytes(charset));
},
parseUTF8(str) {
return Data.parseStr(str, StandardCharsets.UTF_8);
},
parseUTF16(str) {
return Data.parseStr(str, StandardCharsets.UTF_16);
},
parseHex(str) {
return new Data(hexDecodeToByteArray(str));
},
parseBase64(str, flags) {
return new Data(base64DecodeToByteArray(str, flags));
},
parseLatin1(str) {
return Data.parseStr(str, StandardCharsets.ISO_8859_1);
},
parseUTF16LE(str) {
return Data.parseStr(str, StandardCharsets.UTF_16LE);
},
parseInputStream(stream) {
return new Data(FileUtil.toBytes(stream));
}
});
Object.assign(Data.prototype, {
toHex() {
return bytesToHex(this.bytes);
},
toBytes() {
return this.bytes;
},
toString(charset) {
return bytesToString(this.bytes, charset);
},
toLatin1() {
return this.toString(StandardCharsets.ISO_8859_1);
},
toUTF16LE() {
return this.toString(StandardCharsets.UTF_16LE);
},
toUTF16() {
return this.toString(StandardCharsets.UTF_16);
},
toBase64(flags) {
return String(Base64.encodeToString(this.bytes, flags || Base64.DEFAULT));
},
toDigest() {
return new Digest(this);
},
toInputStream() {
return FileUtil.toInputStream(this.bytes);
}
});
//摘要类
function Digest(data) {
this.data = data;
}
Digest.digest = function(data, algorithm) {
try {
let md = MessageDigest.getInstance(algorithm);
md.update(data.toBytes());
let hashInBytes = md.digest();
return String(bytesToHex(hashInBytes));
} catch (e) {
throw (e);
}
}
Object.assign(Digest.prototype, {
md5() {
return Digest.digest(this.data, "MD5");
},
sha256() {
return Digest.digest(this.data, "SHA-256");
},
md2() {
return Digest.digest(this.data, "MD2");
},
sha1() {
return Digest.digest(this.data, "SHA-1");
},
sha512() {
return Digest.digest(this.data, "SHA-512");
},
sha384() {
return Digest.digest(this.data, "SHA-384");
}
});
function process(operation, cipherType, input, key, option) {
option = option || {};
validate(key, option.mode, cipherType);
if (typeof input === "string") {
input = operation === Cipher.ENCRYPT_MODE ? Data.parseUTF8(input) : Data.parseBase64(input);
}
let secretKey = new SecretKeySpec(key.toBytes(), cipherType);
let cipher = Cipher.getInstance(option.mode || cipherType);
if (option.iv != null) {
cipher.init(operation, secretKey, new IvParameterSpec(option.iv.toBytes()));
} else {
cipher.init(operation, secretKey);
}
return new Data(cipher.doFinal(input.toBytes()));
}
const AES = {
encrypt(data, key, option) {
return result = process(Cipher.ENCRYPT_MODE, "AES", data, key, option);
},
decrypt(data, key, option) {
return process(Cipher.DECRYPT_MODE, "AES", data, key, option);
}
}
const DES = {
encrypt(data, key, option) {
return process(Cipher.ENCRYPT_MODE, "DES", data, key, option);
},
decrypt(data, key, option) {
return process(Cipher.DECRYPT_MODE, "DES", data, key, option);
}
}
const DESede = {
encrypt(data, key, option) {
return process(Cipher.ENCRYPT_MODE, "DESede", data, key, option);
},
decrypt(data, key, option) {
return process(Cipher.DECRYPT_MODE, "DESede", data, key, option);
}
}
function validate(key, mode, cipherType) {
if (key == null) {
throw new Error("Key must not be null or empty.");
}
if (mode && !mode.startsWith(cipherType)) {
throw new Error("Invalid mode.");
}
let expectedKeyLength = [];
switch (cipherType) {
case "AES":
expectedKeyLength = [16, 24, 36];
break;
case "DESede":
expectedKeyLength = [24];
break;
case "DES":
expectedKeyLength = [8];
break;
default:
throw new Error("Invalid cipher type.");
}
if (!expectedKeyLength.includes(key.length)) {
throw new Error("Invalid key length. Key length must be " + expectedKeyLength.join(" or ") + " bytes for " + cipherType + ".");
}
}
/*mode
AES/CBC/PKCS5Padding
AES/CBC/NoPadding
AES/ECB/PKCS5Padding
AES/ECB/NoPadding
AES/CFB/NoPadding
AES/CFB/PKCS5Padding
AES/OFB/NoPadding
AES/OFB/PKCS5Padding
AES/CTR/NoPadding
AES/CTR/PKCS5Padding
DES/CBC/PKCS5Padding
DES/CBC/NoPadding
DES/ECB/PKCS5Padding
DES/ECB/NoPadding
DES/CFB/NoPadding
DES/CFB/PKCS5Padding
DES/OFB/NoPadding
DES/OFB/PKCS5Padding
DES/CTR/NoPadding
DES/CTR/PKCS5Padding
*/
function bytesToString(bytes, charset) {
return String(new jvString(bytes, charset || StandardCharsets.UTF_8));
}
function base64EncodeToByteArray(str, flags) {
return Base64.encode(str.getBytes(StandardCharsets.UTF_8), flags || Base64.DEFAULT);
}
function base64DecodeToByteArray(str, flags) {
if (str == null) {
return null;
}
return Base64.decode(str, flags || Base64.DEFAULT);
}
function hexDecodeToByteArray(cipherText) {
cipherText = String(cipherText);
let str = cipherText.toLowerCase();
let length = str.length;
let bArr = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, length / 2);
for (let i = 0, o = 0; i < length; i += 2, o++) {
let a = str[i + 1],
b = str[i];
if (b != "0") {
a = b + a;
}
let hexInt = Integer.parseInt(new jvString(a), 16);
let inty = hexInt > 127 ? hexInt - 255 - 1 : hexInt;
bArr[o] = inty;
}
return bArr;
}
function bytesToHex(data) {
let strBuffer = new StringBuffer();
for (let i = 0; i < data.length; i++) {
//strBuffer.append(Integer.toHexString(0xff & data[i]));
strBuffer.append(jvString.format("%02x", Byte(data[i])));
}
return String(strBuffer.toString());
}
function toJvString(str) {
if (typeof str === "string") {
return new jvString(str);
} else {
return str;
}
}
$.exports = {
Data,
Digest,
AES,
DES,
DESede
};
})()
let 图片解密 = function(key,iv,kiType,mode) {
function hexStringToBytes(cipherText) {
cipherText = String(cipherText);
let str = cipherText.toLowerCase();
let length = str.length;
let bArr = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, length / 2);
for (let i = 0, o = 0; i < length; i += 2, o++) {
let a = str[i + 1],
b = str[i];
if (b != "0") {
a = b + a;
}
let hexInt = java.lang.Integer.parseInt(new java.lang.String(a), 16);
let inty = hexInt > 127 ? hexInt - 255 - 1 : hexInt;
bArr[o] = inty;
}
return bArr;
}
let javaImport = new JavaImporter();
javaImport.importPackage(
Packages.com.example.hikerview.utils,
Packages.java.lang,
Packages.java.security,
Packages.javax.crypto,
Packages.javax.crypto.spec
);
with(javaImport) {
function getBytes(str) {
let bytes;
if (kiType === "Base64") {
bytes = _base64.decode(str, _base64.NO_WRAP);
} else if (kiType === "Hex") {
bytes = hexStringToBytes(str);
} else {
bytes = String(str).getBytes("UTF-8");
}
return bytes;
}
kiType = kiType || "String";
mode = mode || 'AES/CBC/PKCS5Padding';
key = getBytes(key);
iv = getBytes(iv);
function decryptData(cipherText) {
let secretKeySpec = new SecretKeySpec(key, "AES");
let ivParameterSpec = new IvParameterSpec(iv);
let cipher = Cipher.getInstance(mode);
cipher.init(2, secretKeySpec, ivParameterSpec);
return cipher.doFinal(cipherText);
}
let bytes = FileUtil.toBytes(input);
bytes = decryptData(bytes);
return FileUtil.toInputStream(bytes);
}
}