【说明】
这篇文章是对上一篇【Cocos2d-x PNG图片资源加密】的补充和扩展,那篇文章转自【旧时尘安】的博客,文中已经对原理和使用讲解的很清晰,这里只是根据我自己的使用情况做一些小小的功能扩展,也是自己做个整理,以便日后使用。如有侵权,请联系删除。
【链接】
原文地址:http://www.cnblogs.com/zhangpanyi/p/4560297.html
原始工程:https://github.com/zhangpanyi/EncryptPNG
【使用】
修改后的使用有所调整,原文的使用更简洁,这里主要是依照我个人的习惯作出的调整。我在代码中添加了设置密钥和扩展名的接口。
1. 在cocos目录下新建文件夹 ext ,将 CCAES.cpp、CCAES.h、CCDecryptImage.cpp、CCDecryptImage.h 拷贝到其中。
2. 在Xcode项目中引用 ext 目录。
注:这里可能会报错,为此我耽误了半天,结果居然是Xcode没有自动引用导致的,我已记录到【这里】。
3.Android项目需要修改 cocos/Android.mk 文件,将两个cpp文件添加进去即可。
4. 在 CCImage 中调用解密代码,方法与原文一样,这里略有修改,代码见附录。
注:我将对 CCDecryptImage.h 的引用放在了 CCImage.h ,是为了在项目中设置密钥时不需要再引用此头文件。
5. 在项目中设置密钥和扩展名,我是在 AppDelegate.cpp 中设置。
注:如果修改扩展名,需要加密端也做修改,保证两边扩展名一致。
-
- constext::aes_keykey={0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
- ext::DecryptImageConfig(key,".epng");
【代码】
copy
CCImage.cpp
boolImage::initWithImageFile(conststd::string&path)
- {
- ......
-
- if(!data.isNull())
- //图片文件解密
- if(ext::AnalyzeExtension(path)[1]==ext::TARGET_EXTENSION)
- {
- autoimage_data=ext::DecryptImage(path,data);
- ret=initWithImageData(&image_data[0],image_data.size());
- }
- else
- ret=initWithImageData(data.getBytes(),data.getSize());
- }
- #endif//EMSCRIPTEN
-
- returnret;
- boolImage::initWithImageFileThreadSafe(conststd::string&fullpath)
- if(ext::AnalyzeExtension(fullpath)[1]==ext::TARGET_EXTENSION)
- autoimage_data=ext::DecryptImage(fullpath,153); font-weight:bold; background-color:inherit">returnret;
- }
copy
<spanstyle="font-family:Arial,sans-serif;">CCDecryptImage.h</span>
copy
#ifndef__CC_DECRYPT_IMAGE_H__
- #define__CC_DECRYPT_IMAGE_H__
- #include<array>
- #include<vector>
- #include"CCData.h"
- #include"CCAES.h"
- namespaceext
- /*解密扩展名*/
- staticstd::stringTARGET_EXTENSION=".epng";
-
- staticaes_keySECRET_KEY={0x31,0x39};
- /**
- *设置解密秘钥
- *@paramkey秘钥(AES的16位秘钥)
- *@paramexten文件扩展名(需要解密的文件扩展名,如".png")
- */
- voidDecryptImageConfig(constaes_key&key,conststd::string&exten=TARGET_EXTENSION);
- /**
- *解密图片文件(在CCImage中调用)
- *@paramfilename文件名称
- *@paramdata文件数据
- */
- std::vector<unsignedchar>DecryptImage(conststd::string&filename,cocos2d::Data&data);
- *分解文件名的扩展名(在CCImage中调用)
- *@paramfile_path文件名
- std::array<std::string,2>AnalyzeExtension(conststd::string&file_path);
- #endif
copy
CCDecryptImage.cpp
#include"CCDecryptImage.h"
- #include<sstream>
- #include"ccMacros.h"
- #if(CC_TARGET_PLATFORM==CC_PLATFORM_WIN32)
- #include<WinSock.h>
- #pragmacomment(lib,"ws2_32.lib")
- #elif(CC_TARGET_PLATFORM==CC_PLATFORM_IOS||CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID)
- #include<netinet/in.h>
- #endif
- /*CRC码长度*/
- staticconstuint32_tCRC_SIZE=4;
- /*文件头部*/
- constunsignedcharHEAD_DATA[]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a};
- /*IENDCRC码*/
- charIEND_DATA[]={0xae,0x42,0x60,0x82};
- /*数据块头部(用于验证解密是否成功)*/
- charBLOCK_HEAD[]={0x45,0x6e,0x63,0x72,0x79,0x70,0x74,0x47};
- #pragmapack(push,1)
- structBlock
- charname[4];
- uint32_tpos;
- uint32_tsize;
- };
- structIHDRBlock
- Blockblock;
- chardata[13+CRC_SIZE];
- #pragmapack(pop)
- /*解析文件扩展名*/
- conststd::string&file_path)
- std::string::size_typepos=file_path.rfind('.');
- std::array<std::string,2>text;
- if(std::string::npos!=pos)
- text[1]=file_path.substr(pos);
- text[0]=file_path.substr(0,pos);
- else
- text[0]=file_path;
- returntext;
- template<int_Value,153); font-weight:bold; background-color:inherit">typename_Stream>
- std::array<char,_Value>ReadSome(_Stream&stream)
- for(unsignedinti=0;i<_Value;++i)buffer[i]=stream.get();
- returnbuffer;
- /*解密块*/
- voidDecryptBlock(std::stringstream&ss,153); font-weight:bold; background-color:inherit">constaes_key&key)
- conststd::streamoffcontents_size=ss.tellp()-ss.tellg();
- constuint32_tblock_size=(uint32_t)(contents_size+AES_BLOCK_SIZE-contents_size%AES_BLOCK_SIZE);
- std::vector<uint8_t>buffer;
- buffer.resize(block_size);
- for(uint32_ti=0;i<contents_size;++i)buffer[i]=ss.get();
- AES::DecryptData(&buffer[0],block_size,key);
- ss.seekg(0);ss.seekp(0);
- for(uint32_ti=0;i<block_size;++i)ss.put(buffer[i]);
- /*解密图片文件*/
- CCAssert(!data.isNull(),"dataisnull!");
- //获取数据块信息位置
- constuint32_tblock_start_pos=ntohl(*reinterpret_cast<uint32_t*>(data.getBytes()+data.getSize()-sizeof(uint32_t)));
- //获取数据块信息
- std::stringstreamblock_info;
- for(uint32_ti=block_start_pos;i<data.getSize()-sizeof(uint32_t);++i)
- block_info.put(*(data.getBytes()+i));
- //解密数据块信息
- DecryptBlock(block_info,SECRET_KEY);
- //验证数据块信息是否解密成功
- autoblock_head=ReadSome<sizeof(BLOCK_HEAD)>(block_info);
- inti=0;i<block_head.size();++i)
- if(block_head[i]!=BLOCK_HEAD[i])
- CCAssert(false,"thekeyiswrong!");
- //写入文件头信息
- char>image_data;
- image_data.reserve(data.getSize());
- for(autoch:HEAD_DATA)image_data.push_back(ch);
- //写入数据块信息
- while(true)
- memcpy(&block,&(ReadSome<sizeof(Block)>(block_info)[0]),153); font-weight:bold; background-color:inherit">sizeof(Block));
- if(block_info.eof())
- "");
- CCLOG("the%sfileformaterror!",filename.c_str());
- //写入数据块长度和名称
- charsize_buffer[sizeof(block.size)];
- memcpy(size_buffer,&block.size,sizeof(size_buffer));
- for(autoch:size_buffer)image_data.push_back(ch);
- for(autoch:block.name)image_data.push_back(ch);
- block.pos=ntohl(block.pos);
- block.size=ntohl(block.size);
- charblock_name[sizeof(block.name)+1]={0};
- memcpy(block_name,block.name,153); font-weight:bold; background-color:inherit">sizeof(block.name));
- if(strcmp(block_name,"IHDR")==0)
- IHDRBlockihdr;
- memcpy(&ihdr,&block,153); font-weight:bold; background-color:inherit">sizeof(Block));
- memcpy(((char*)&ihdr)+sizeof(Block),&ReadSome<sizeof(IHDRBlock)-sizeof(Block)>(block_info)[0],153); font-weight:bold; background-color:inherit">for(autoch:ihdr.data)image_data.push_back(ch);
- else"IEND")==0)
- for(autoch:IEND_DATA)image_data.push_back(ch);
- CCLOG("decrypt%ssuccess!",153); font-weight:bold; background-color:inherit">break;
- for(uint32_ti=0;i<block.size+CRC_SIZE;++i)
- image_data.push_back(*(data.getBytes()+block.pos+i));
- returnimage_data;
- /*配置解密秘钥和扩展名*/
- conststd::string&exten)
- SECRET_KEY=key;
- TARGET_EXTENSION=exten;
- }
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|