使用python对cocos2dx的手游图片资源进行加密

栏目: IOS · 发布时间: 7年前

内容简介:由于项目的需要,要对游戏的图片资源进行加密,目前比较常用的做法应该是使用TexturePacker的加密功能。但因为我们的整个打包流程都是python脚本控制,自动化完成的,如果要使用TexturePacker的加密功能,就要把TexturePacker的命令行工具集成到整个自动化打包工具中。考虑到工作量会比较大,所以决定采用在图片压缩后自动遍历assets目录下的所有的图片并使用python自动进行字节流加密的解决方案。缺点是加密方式比较简单,易于破解。加密模块的大致思路就是以2进制可读的方式打开图片资

导言

由于项目的需要,要对游戏的图片资源进行加密,目前比较常用的做法应该是使用TexturePacker的加密功能。但因为我们的整个打包流程都是 python 脚本控制,自动化完成的,如果要使用TexturePacker的加密功能,就要把TexturePacker的命令行工具集成到整个自动化打包 工具 中。考虑到工作量会比较大,所以决定采用在图片压缩后自动遍历assets目录下的所有的图片并使用python自动进行字节流加密的解决方案。缺点是加密方式比较简单,易于破解。

步骤

1.编写python加密模块

加密模块的大致思路就是以2进制可读的方式打开图片资源文件,然后遍历字节流,对每个字节进行一定的转化,我采用的是异或一个随机的值,然后在整个文件的头部加上三个字节的标识,用来标识这个图片是否进行了加密处理。然后第四个字节保存加密的密钥。最后将二进制数据流写入一个新的图片文件,同时删除老的图片文件。图片的加密过程到此就结束了。

########################################
# __encrypt__.py
# 功能:对png、jpg进行加密处理
# 作者:刘翰男
# 创建:2016-09-01
########################################
import os
import sys
import random
print("__encrypt__.py")

#随机生成密匙random.randint(1, 255)
encrypt_key = random.randint(1, 255)
#加密过的标示,两个字节
have_encrypt_first_flag = 0x12
have_encrypt_second_flag = 0x34
have_encrypt_third_flag = 0x56

#images_path是需要加密的图片的绝对路径
def encrypt(images_path):
    f = open(images_path, 'rb')
    filedata = f.read()
    filesize = f.tell()
    f.close()

    file_byte_array = bytearray(filedata)

    #判断是否加密过
    if(have_encrypt_first_flag == file_byte_array[0]
        and have_encrypt_second_flag == file_byte_array[1]
        and have_encrypt_third_flag == file_byte_array[2]):
            print('this png has encrypt before!')
    else:
        encrypt_file_byte_array = bytearray(0)
        encrypt_file_byte_array.append(have_encrypt_first_flag)
        encrypt_file_byte_array.append(have_encrypt_second_flag)
        encrypt_file_byte_array.append(have_encrypt_third_flag)
        encrypt_file_byte_array.append(encrypt_key)

        for byte in file_byte_array:
            encrypt_bype = byte ^ encrypt_key
            encrypt_file_byte_array.append(encrypt_bype)

        workdir = os.path.split(images_path)[0]

        os.remove(images_path)
        f2 = open(images_path,'wb')
        f2.write(encrypt_file_byte_array)
        f2.close()

#判断是否是png和jpg图片
def judge_is_png_or_jpg(file_name):
    suffix = os.path.splitext(file_name)[1]
    if  suffix== '.png' or suffix == '.jpg' or suffix == '.PNG' or suffix == '.JPG':
        return True
    else:
        return False

2.修改cocos2dx引擎

我们知道,所有的资源文件,都要先从磁盘读到内存。我们要修改的就是读取的这个过程。打开cocos2dx引擎源码文件CCImage.cpp,找到initWithImageFile(const std::string& path)这个方法。修改前的源代码如下:

bool Image::initWithImageFile(const std::string& path)
{
    bool ret = false;
    _filePath = FileUtils::getInstance()->fullPathForFilename(path);

    Data data = FileUtils::getInstance()->getDataFromFile(_filePath);

    if (!data.isNull())
    {
        auto bin = data.getBytes();
        auto size = data.getSize();

        ret = initWithImageData(data.getBytes() + encrypt_head_lengh, data.getSize());
    }
    return ret;
}

这个方法是读取图片文件,然后获取byte数据流,并用这些数据初始化形成图片,现在我们要做的就是在获取到这些二进制数据之后,进行解密。

1. 获取前三个字节,如果是加密标识的话,表明这个图片已经进行了,加密处理,在此则要进行解密处理。

2. 取第四个字节,也就是对当前这个图片进行加密时的密钥,拿这个密钥进行解密。

3. 用解密后的字节流初始化形成图片。

修改后的源代码如下:

bool Image::initWithImageFile(const std::string& path)
{
    bool ret = false;
    _filePath = FileUtils::getInstance()->fullPathForFilename(path);
    Data data = FileUtils::getInstance()->getDataFromFile(_filePath);

    if (!data.isNull())
    {
        auto bin = data.getBytes();
        auto size = data.getSize();

        unsigned char have_encrypt_first_flag = *bin;
        unsigned char have_encrypt_second_flag = *(bin + 1);
        unsigned char have_encrypt_third_flag = *(bin + 2);
        unsigned char encrypt_key = 0;
        unsigned int encrypt_head_flag_lengh = 3;
        unsigned int encrypt_head_lengh = 4;

        if (have_encrypt_first_flag == 0x12
            && have_encrypt_second_flag == 0x34
            && have_encrypt_third_flag == 0x56)
        {
            encrypt_key = *(bin + encrypt_head_flag_lengh);
            auto *cur = bin + encrypt_head_lengh;
            auto count = size - encrypt_head_lengh;
            while (count)
            {
                *cur ^= encrypt_key;
                ++cur;
                --count;
            }

            ret = initWithImageData(data.getBytes() + encrypt_head_lengh, data.getSize());
        }
        else
        {
            ret = initWithImageData(data.getBytes(), data.getSize());
        }
    }

    return ret;
}

PS:小知识

int a = 0x1121;
int b = 0x21;
int c = a^b;
再用c^b会发现等于a。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

淘宝、天猫网上开店速查速用一本通

淘宝、天猫网上开店速查速用一本通

刘珂 / 北京时代华文书局 / 2015-6 / 39.8

为了帮助众多的新手卖家掌握淘宝天猫网上开店、货源准备、店铺装修、商品拍摄、交易方法、营销推广以及售后服务等知识,本书作者根据自己多年网上开店心得,并结合了多名淘宝五皇冠店主和天猫旗舰店卖家的经验,精心策划编写了本书。 《淘宝、天猫网上开店速查速用一本通:开店、装修、运营、推广完全攻略》将目前最前沿、最流行的营销理念运用到淘宝天猫网上平台,所有技术都在实际应用获得显著效果,并且还在持续创造着惊......一起来看看 《淘宝、天猫网上开店速查速用一本通》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

随机密码生成器
随机密码生成器

多种字符组合密码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具