【說明】
這篇文章是對上一篇 【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 中設定。
注:如果修改副檔名,需要加密端也做修改,保證兩邊副檔名一致。
-
-
const ext::aes_key key = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};
-
ext::DecryptImageConfig(key, ".epng");
【程式碼】
-
bool Image::initWithImageFile(const std::string& path)
-
{
-
......
-
-
if (!data.isNull())
-
{
-
-
if (ext::AnalyzeExtension(path)[1] == ext::TARGET_EXTENSION)
-
{
-
auto image_data = ext::DecryptImage(path, data);
-
ret = initWithImageData(&image_data[0], image_data.size());
-
}
-
else
-
{
-
ret = initWithImageData(data.getBytes(), data.getSize());
-
}
-
}
-
#endif // EMSCRIPTEN
-
-
return ret;
-
}
-
-
bool Image::initWithImageFileThreadSafe(const std::string& fullpath)
-
{
-
......
-
-
if (!data.isNull())
-
{
-
-
if (ext::AnalyzeExtension(fullpath)[1] == ext::TARGET_EXTENSION)
-
{
-
auto image_data = ext::DecryptImage(fullpath, data);
-
ret = initWithImageData(&image_data[0], image_data.size());
-
}
-
else
-
{
-
ret = initWithImageData(data.getBytes(), data.getSize());
-
}
-
}
-
-
return ret;
-
}
-
<span style="font-family: Arial, Helvetica, sans-serif;">CCDecryptImage.h</span>
-
#ifndef __CC_DECRYPT_IMAGE_H__
-
#define __CC_DECRYPT_IMAGE_H__
-
-
#include <array>
-
#include <vector>
-
#include "CCData.h"
-
#include "CCAES.h"
-
-
namespace ext
-
{
-
-
static std::string TARGET_EXTENSION = ".epng";
-
-
-
static aes_key SECRET_KEY = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
-
-
-
-
-
-
-
void DecryptImageConfig(const aes_key &key, const std::string &exten = TARGET_EXTENSION);
-
-
-
-
-
-
-
std::vector<unsigned char> DecryptImage(const std::string &filename, cocos2d::Data &data);
-
-
-
-
-
-
std::array<std::string, 2> AnalyzeExtension(const std::string &file_path);
-
-
}
-
-
#endif
-
#include "CCDecryptImage.h"
-
-
#include <sstream>
-
#include "ccMacros.h"
-
-
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
-
#include <WinSock.h>
-
#pragma comment(lib, "ws2_32.lib")
-
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
-
#include <netinet/in.h>
-
#endif
-
-
namespace ext
-
{
-
-
static const uint32_t CRC_SIZE = 4;
-
-
-
static const unsigned char HEAD_DATA[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a };
-
-
-
static const unsigned char IEND_DATA[] = { 0xae, 0x42, 0x60, 0x82 };
-
-
-
static const unsigned char BLOCK_HEAD[] = { 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x50, 0x4e, 0x47 };
-
-
#pragma pack(push, 1)
-
-
struct Block
-
{
-
char name[4];
-
uint32_t pos;
-
uint32_t size;
-
};
-
-
struct IHDRBlock
-
{
-
Block block;
-
char data[13 + CRC_SIZE];
-
};
-
-
#pragma pack(pop)
-
-
-
std::array<std::string, 2> AnalyzeExtension(const std::string &file_path)
-
{
-
std::string::size_type pos = 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;
-
}
-
return text;
-
}
-
-
template <int _Value, typename _Stream>
-
std::array<char, _Value> ReadSome(_Stream &stream)
-
{
-
std::array<char, _Value> buffer;
-
for (unsigned int i = 0; i < _Value; ++i) buffer[i] = stream.get();
-
return buffer;
-
}
-
-
-
void DecryptBlock(std::stringstream &ss, const aes_key &key)
-
{
-
const std::streamoff contents_size = ss.tellp() - ss.tellg();
-
const uint32_t block_size = (uint32_t)(contents_size + AES_BLOCK_SIZE - contents_size % AES_BLOCK_SIZE);
-
std::vector<uint8_t> buffer;
-
buffer.resize(block_size);
-
for (uint32_t i = 0; i < contents_size; ++i) buffer[i] = ss.get();
-
AES::DecryptData(&buffer[0], block_size, key);
-
ss.seekg(0); ss.seekp(0);
-
for (uint32_t i = 0; i < block_size; ++i) ss.put(buffer[i]);
-
}
-
-
-
std::vector<unsigned char> DecryptImage(const std::string &filename, cocos2d::Data &data)
-
{
-
CCAssert(!data.isNull(), "data is null!");
-
-
-
const uint32_t block_start_pos = ntohl(*reinterpret_cast<uint32_t *>(data.getBytes() + data.getSize() - sizeof(uint32_t)));
-
-
-
std::stringstream block_info;
-
for (uint32_t i = block_start_pos; i < data.getSize() - sizeof(uint32_t); ++i)
-
{
-
block_info.put(*(data.getBytes() + i));
-
}
-
-
-
DecryptBlock(block_info, SECRET_KEY);
-
-
-
auto block_head = ReadSome<sizeof(BLOCK_HEAD)>(block_info);
-
for (unsigned int i = 0; i < block_head.size(); ++i)
-
{
-
if (block_head[i] != BLOCK_HEAD[i])
-
{
-
CCAssert(false, "the key is wrong!");
-
}
-
}
-
-
-
std::vector<unsigned char> image_data;
-
image_data.reserve(data.getSize());
-
for (auto ch : HEAD_DATA) image_data.push_back(ch);
-
-
-
while (true)
-
{
-
Block block;
-
memcpy(&block, &(ReadSome<sizeof(Block)>(block_info)[0]), sizeof(Block));
-
if (block_info.eof())
-
{
-
CCAssert(false, "");
-
CCLOG("the %s file format error!", filename.c_str());
-
}
-
-
-
char size_buffer[sizeof(block.size)];
-
memcpy(size_buffer, &block.size, sizeof(size_buffer));
-
for (auto ch : size_buffer) image_data.push_back(ch);
-
for (auto ch : block.name) image_data.push_back(ch);
-
-
block.pos = ntohl(block.pos);
-
block.size = ntohl(block.size);
-
-
char block_name[sizeof(block.name) + 1] = { 0 };
-
memcpy(block_name, block.name, sizeof(block.name));
-
if (strcmp(block_name, "IHDR") == 0)
-
{
-
IHDRBlock ihdr;
-
memcpy(&ihdr, &block, sizeof(Block));
-
memcpy(((char *)&ihdr) + sizeof(Block), &ReadSome<sizeof(IHDRBlock) - sizeof(Block)>(block_info)[0], sizeof(IHDRBlock) - sizeof(Block));
-
for (auto ch : ihdr.data) image_data.push_back(ch);
-
}
-
else if (strcmp(block_name, "IEND") == 0)
-
{
-
for (auto ch : IEND_DATA) image_data.push_back(ch);
-
CCLOG("decrypt %s success!", filename.c_str());
-
break;
-
}
-
else
-
{
-
for (uint32_t i = 0; i < block.size + CRC_SIZE; ++i)
-
{
-
image_data.push_back(*(data.getBytes() + block.pos + i));
-
}
-
}
-
}
-
return image_data;
-
}
-
-
-
void DecryptImageConfig(const aes_key &key, const std::string &exten)
-
{
-
SECRET_KEY = key;
-
TARGET_EXTENSION = exten;
-
}
-
}