MD5介绍
MD5的全称是Message-Digest Algorithm 5,它一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。
MD5值等同于文件的ID,它的值是唯一的。 如果文件已被修改(例如嵌入式病毒,特洛伊木马等),其MD5值将发生变化。 因此,一些常规下载URL提供文件MD并且通常提供MD5值。 如果用户在下载后发现他们的MD5值与网站公告不一致,可能是文件被修改过或者下载出错。
需求
苹果机审是马甲包混淆被打回来的一大障碍,机审一般是比较文件的MD5是否一致,所以我们单单修改文件的名称是不够的,需要我们批量修改工程中图片等文件资源的MD5值。
方案
MD5哈希算法是基于文件内容的,而不考虑文件的元数据,如创建日期、文件名等。只要图片的像素数据没有被修改,无论你修改了哪些元数据,都不会改变其MD5哈希值。
所以,我们需要对文件的内容进行修改。
压缩
我们通过压缩图片生成新的图片。
缺点:当对同一张图片进行压缩时,如果压缩参数相同,生成的图片MD5是一样的,会重复。当再次压缩已经压缩过的图片,可以解决这个问题,但是多次压缩后会造成图片模糊。
添加噪点
我们可以在图片任意四个角,取一点添加一个1px的像素点,像素颜色随机生成。
缺点:图片上的噪点看起来可能会比较明显,显得很突兀,生成相同的噪点也会造成MD5重复。
修改文件二进制值
通过读取文件的二进制值,在末尾添加时间戳
作为标记
优点:支持任意文件。多次处理后,图片显示与原图一致,同时MD5不会重复。
import hashlib
import os
import re
import time
def get_md5(image_path):
# 计算处理后的图片的MD5哈希值
with open(image_path, 'rb') as file:
md5 = hashlib.md5(file.read()).hexdigest()
print(f"MD5哈希值: {md5}")
def change_md5_folder(root_folder):
"""
修改文件中所有文件MD5
"""
# 递归遍历文件夹及其子文件夹中的所有文件
for foldername, subfolders, filenames in os.walk(root_folder):
for filename in filenames:
# 获取图片文件的完整路径
image_path = os.path.join(foldername, filename)
# 调用处理图片的函数
change_md5_file(image_path)
def change_md5_file(file_path):
"""
修改文件MD5,在末尾添加时间戳来改变MD5
"""
# 读取图片二进制数据
with open(file_path, "rb") as file:
file_data = file.read()
# 使用正则表达式匹配以 "TAG" 开头和以数字结尾的模式
match = re.search(b"TAG\\d+$", file_data)
timestamp = str(int(time.time())).encode() # 获取当前时间戳并转换为字节
if match:
# 如果匹配到 "TAG" 开头和数字结尾的模式,将数字替换为时间戳
new_image_data = re.sub(b"KK\\d+$", b"TAG" + timestamp, file_data)
else:
# 如果没有匹配到模式,添加 "KK" 时间戳
new_image_data = file_data + b"TAG" + timestamp
# 保存新的文件
output_path = file_path
with open(output_path, "wb") as output_image_file:
output_image_file.write(new_image_data)
print(f"已处理并保存为 {output_path}")
if __name__ == '__main__':
change_md5_folder('/Users/alen/Aproject/flutter_project/assets')