Files
2026-10-08 11:37:25 +07:00

65 lines
2.0 KiB
Dart

import 'dart:typed_data';
//图片解密:前 100 字节与 key 循环异或
class ImageCrypto {
//jpg/png/gif 文件头,都对不上视为加密图
static final List<Uint8List> _featuresList = [
Uint8List.fromList([0xff, 0xd8, 0xff]), //jpg,jpeg
Uint8List.fromList([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), //png
Uint8List.fromList([0x47, 0x49, 0x46]), //gif
];
static const int _minLen = 6; //最小字节数
static const int _encryptedLen = 100; //加密图片的数据长度
static final Uint8List _decryptKey = Uint8List.fromList('2019ysapp7527'.codeUnits); //加密key
static Uint8List? decrypt(Uint8List? imgBytes) {
if (imgBytes?.isNotEmpty != true) {
return imgBytes;
}
//不足 6 字节视为坏图,抛给调用方走失败(沿用老逻辑比对 6 字节魔数时越界抛错的行为)
if (imgBytes!.length < _minLen) {
throw RangeError.range(imgBytes.length, 0, imgBytes.length - 1, 'length');
}
if (_isEncrypted(imgBytes)) {
imgBytes = _xor(imgBytes, _decryptKey, _encryptedLen);
}
return imgBytes;
}
static bool _isEncrypted(Uint8List imgBytes) {
bool isMismatch = false;
int featuresLen = _featuresList.length;
for (int i = 0; i < featuresLen; i++) {
isMismatch = false;
for (int j = 0; j < _featuresList[i].length; j++) {
if (_featuresList[i][j] != imgBytes[j]) {
isMismatch = true;
break;
}
}
if (isMismatch) {
continue;
} else {
break;
}
}
return isMismatch;
}
//前 length 字节与 key 循环异或(原地修改)
static Uint8List _xor(Uint8List src, Uint8List key, int length) {
int srcLen = src.length;
int keyLen = key.length;
if (length > srcLen || length <= 0) {
length = srcLen;
}
for (var i = 0; i < length; i += keyLen) {
for (var j = 0; j < keyLen && i + j < length; j++) {
src[i + j] ^= key[j];
}
}
return src;
}
}