Cocos图片加密与解密

Cocos图片加密与解密现在做的cocos项目没有对资源进行加密处理,发布出来的APK一旦被人解包,则所有图片资源都会暴露出来,为了避免图片资源被人恶意使用,所有我准备给自己项目中使用到的图片进行简单加密,这样可以防住一部分解包伸手党。我们这里采用最常见的**异或加密**,*异或加密性质:一个数异或同一个数两次,得到的是本身*。根据这个性质,我们可以采用把图片的字节流进行异或加密,只需要设置一个Key,在本地客户端使用…

大家好,又见面了,我是你们的朋友全栈君。

如果cocos项目没有对资源进行加密处理,发布出来的APK一旦被人解包,则所有图片资源都会暴露出来,为了避免图片资源被人恶意使用,所以我准备给自己项目中使用到的图片进行简单加密,这样可以防住一部分解包伸手党。

我们这里采用最常见的异或加密,异或加密性质:一个数异或同一个数两次,得到的是本身。根据这个性质,我们可以采用把图片的字节流进行异或加密,只需要设置一个Key,在本地客户端使用Key进行一次异或,然后在cocos导入文件的函数中再使用Key进行一次异或,即可还原。

同时为了兼容没有加密的图片,我们需要再加密过后的文件头上添加一下标识,比如文件头部添加N个自定字节流来表示该图片别加密过,同时除了添加的头标识外的其他字节流全部或者部分进行异或加密。

Python进行图片文件加密

根据上面的思路,首先我们需要把项目中使用到的图片进行字节流加密,这里我为了方便就采用python来做,比较简单快捷。你也用C++,java等等你擅长的语言进行文件操作。

#!/usr/bin/env python
#coding=utf-8
# 2019-12-28 by LeiTao
#
import sys
import os
FileEncrpyEnum = { 
".png"}  #这里填入你需要加密图片的后缀名,这里我只加密png
EncrpyKey = 58   #异或加密秘钥
HeadSize = 8	 #添加8个byte在文件头
EncrySize = 100  #为了更快的解密,只加密文件的100个字节流
def MakeEncrpy(pahtName,FileName):
oldfile = open(os.path.join(pahtName, FileName),'rb')
oldConten = oldfile.read()
oldfile.close()
li_out=[]
#添加加密标识
for index in range(HeadSize):
li_out.append(chr(0x01))
for i in range(len(oldConten)):
if i < EncrySize:
li_out.append(chr(ord(oldConten[i])^EncrpyKey)) #异或Key进行加密
else:
li_out.append(chr(ord(oldConten[i])))
newfile = open(os.path.join(pahtName, FileName), 'wb')
newfile.truncate()
newfile.write(''.join(li_out))
newfile.close()
return
def main():
dirPath = sys.argv[1]
print dirPath
print "==============GameEncrpy Begin"
for root, dirs, files in os.walk(dirPath):
# root 表示当前正在访问的文件夹路径
# dirs 表示该文件夹下的子目录名list
# files 表示该文件夹下的文件list
# 遍历文件
for f in files:
ExtensionName = os.path.splitext(f)[1]
if ExtensionName in FileEncrpyEnum :
MakeEncrpy(root,f)
print "==============GameEncrpy End"
# -------------- main --------------
if __name__ == '__main__':
try:
main()
except Exception as e:
sys.exit(1)

上面的代码就能够批量对文件夹中后缀为png的图片进行处理,我这里边选择在文件头上插入8个0x01,然后对文件前100个字节进行加密。
加密前后的对比
这是加密前后的对比,加密后的图片因为里面的内容已经被改变,所以正常已经打不开了,这也就达到我们加密的目的。
在这里插入图片描述

COCOS CCFileUtils解密

图片加密过后,COCOS也是无法识别的如果直接引用则会出现错误。所以我们现在开始做COCOS部分的解密。
阅读过源代码的同学应该都知道,COCOS内最终获取图片字节流的函数是写在CCFileUtils的getDataFromFile中,不熟悉源代码的同学也可以自己断点进去调试跟踪,这里我们直接开始修改加载的代码。

static Data getData(const std::string& filename, bool forString)
{ 

if (filename.empty())
{ 

return Data::Null;
}
CCLOG("FileUtils getData Now"); 
Data ret;
unsigned char* buffer = nullptr;
size_t size = 0;
size_t readsize;
const char* mode = nullptr;
if (forString)
mode = "rt";
else
mode = "rb";
auto fileutils = FileUtils::getInstance();
do
{ 

// Read the file from hardware
std::string fullPath = fileutils->fullPathForFilename(filename);
FILE *fp = fopen(fileutils->getSuitableFOpen(fullPath).c_str(), mode);
CC_BREAK_IF(!fp);
fseek(fp,0,SEEK_END);
size = ftell(fp);
fseek(fp,0,SEEK_SET);
if (forString)
{ 

buffer = (unsigned char*)malloc(sizeof(unsigned char) * (size + 1));
buffer[size] = '\0';
}
else
{ 

buffer = (unsigned char*)malloc(sizeof(unsigned char) * size);
}
readsize = fread(buffer, sizeof(unsigned char), size, fp);
fclose(fp);
if (forString && readsize < size)
{ 

buffer[readsize] = '\0';
}
} while (0);
if (nullptr == buffer || 0 == readsize)
{ 

CCLOG("Get data from file %s failed", filename.c_str());
}
else
{ 

//这里实际上就是最终文件读取后的buffer
//所以我们需要再这里进行校验文件是否需要解密
///
//检查是否需要解密
std::string::size_type index = fullPath.find_last_of(".") + 1;
std::string fileType = fullPath.substr(index, fullPath.length() - index);
if(fileType.compare("png")==0)  //png类型进行解密
{ 

CCLOG("Decode Now");
unsigned char encry_head[8] = { 
 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};//添加的头
size_t HeadSize = 8;
if (memcmp(buffer, encry_head, HeadSize) == 0) //比较是否我们添加的头,来判断是否需要解密
{ 

int Key = 58;
int EncrySize = 100;
unsigned char *new_buffer = nullptr;
if (forString)
{ 

new_buffer = (unsigned char*)malloc(size - HeadSize + 1);
new_buffer[size - HeadSize] = '\0';
}
else
{ 

new_buffer = (unsigned char*)malloc(size - HeadSize);
}
for (int i = HeadSize; i < size; i++) { 

if (i < EncrySize + HeadSize) { 
  //加密部分进行解密
new_buffer[i - HeadSize] = buffer[i] ^ Key; //异或Key进行解密
}
else { 

new_buffer[i - HeadSize] = buffer[i];
}
}
free(buffer);
buffer = new_buffer;
size = size - HeadSize;  //去掉加密头长度
}
}
ret.fastSet(buffer, readsize);
}
return ret;
}

修改完getData函数之后,我们就可以愉快的使用我们加密后的图片啦。最后要注意的点是cocos 的跨平台性质,所以你如果你要在win32调试的话记得把CCFileUtils-win32.cpp中的也一并修改了。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/151982.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 零基础学Java(7)大数

    零基础学Java(7)大数大数如果基本的整数和浮点数精度不能够满足需求,那么可以使用java.math包中两个很有用的类:BigInteger和BigDecimal。这两个类可以处理包含任意长度数字序列的数值。BigInte

  • idea2019激活码【最新永久激活】

    (idea2019激活码)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~https://javaforall.cn/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~09LV…

  • c++ bool类型函数[通俗易懂]

    c++ bool类型函数[通俗易懂]bool型函数指的是返回值为bool类型的函数,其调用方式和int型函数没有太大的区别。bool型变量的值只有真(true)和假(false)。bool可用于定义函数类型为布尔型,函数里可以有returntrue;returnfalse之类的语句。示例:#includeusing namespace std;bool cmp(int a,int b){    

  • springboot框架详解_springboot加载spring框架

    springboot框架详解_springboot加载spring框架一图胜千言:springboot容器启动流程:其中最重要的:运行机制为:springboot事件驱动:详情见:springboot事件驱动与观察者模式(http://www.cnblogs.com/dennyzhangdd/p/8343229.html)springboot启动流程图:分层图:…

  • c语言ioctl函数_min函数用法

    c语言ioctl函数_min函数用法ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的调用个数如下: intioctl(intfd,indcmd,…);    其中fd是用户程序打开设备时使用open函数返回的文件标示符,cmd是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,这个参数的…

    2022年10月18日
  • go语言goquery下载图片实例「建议收藏」

    crawl.gopackagemainimport(“fmt””strings””strconv””net/http””net/url””io/ioutil””os””log””runtime””flag””github.com/PuerkitoBio/goquery”)constH

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号