zoukankan      html  css  js  c++  java
  • 图片资源的加密和cocos2d-x中的解密

    主要处理png图片,其他格式图片也是一样的原理。阅读前可以简略了解一下png格式图片的Data trunck。

         首先使用python脚本去掉png的PNG SIG(8 bytes) 以及末尾的PNGIEND(12 bytes)。然后图片剩余数据的每一个字节和秘钥字符串的每一个字符做不进位加(按位异或,解密的原理就是 a ^ b ^ b = a)。通过改写cpp工程里的 Image::initWithImageData(const unsigned char * data, ssize_t dataLen),来进行还原图片数据,也就是解密,过程就是对每一位加密后的数据按秘钥做异或运算还原数据,然后加上PNGSIG和PNGIEND。

    加密脚本:(这个脚本会生成加密后的图片替换原始图片)

      1 # -*- coding:UTF-8 -*-
      2 #该脚本用于加密png图片 使用python3以上版本解释执行
      3 __author__ = "ChenGuanzhou"
      4 
      5 import os
      6 import time
      7 CUR_DIR = os.getcwd();
      8 print("cur_dir:",CUR_DIR)
      9 #CUR_DIR = 'C:\Users\chenguanzhou\Desktop'
     10 _KEY = 'jiaozi2013' #指定加密秘钥,英文
     11 _ENCRYSIG = 'jiaozhi'
     12 _PNGSIG = bytes([0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a])
     13 _PNGIEND = bytes([0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82])
     14 #获取filesig是否是png
     15 def isPNGSig(bytes_8):
     16     return bytes_8 == _PNGSIG
     17 
     18 def isPNG(absPath):#判断是否是PNG图片
     19     """
     20     :param absPath: 文件的绝对路径
     21     :return: {Bool}
     22     """
     23     isFile = os.path.isfile(absPath)
     24     hasPNGSig = False
     25     fileExt = os.path.splitext(absPath)[1]
     26     isPngExt = (fileExt == ".png" or fileExt == ".PNG")
     27     if isFile and isPngExt:
     28         with open(absPath,"rb") as file:
     29             hasPNGSig = isPNGSig(file.read(8)[:8])
     30     return isFile and isPngExt and hasPNGSig
     31 
     32 def preProcessPng(pngData):#预处理图片数据
     33     """
     34     剪掉png的signature(8bytes),IEND(12Bytes)
     35     :param pngData:
     36     :return:
     37     """
     38     assert type(pngData) == bytes
     39     lostHeadData = pngData[8:]
     40     iendData = lostHeadData[-12:]
     41     if iendData == _PNGIEND:#防止Png已经进行过外部软件的压缩,丢掉了IEND
     42         return lostHeadData[:-12]
     43     else:
     44         return lostHeadData
     45 
     46 def encryption(fileData,key):#加密操作 ascii占一个字节
     47     """
     48     加密png数据
     49     :param fileData:{bytes}预处理后的png数据
     50     :param key:{str}秘钥
     51     :return:{bytes}加密后的数据
     52     """
     53     assert type(key) is str
     54     k = bytes(key,"utf8")
     55     klen= len(k)
     56     kindex = 0
     57     fileData = bytearray(fileData)
     58     for i,v in enumerate(fileData):
     59         if kindex >= klen:
     60             kindex = 0
     61         fileData[i] = v ^ k[kindex]#加密
     62         kindex = kindex + 1
     63     return bytes(_ENCRYSIG,"utf8") + fileData
     64 
     65 #处理图片
     66 def processPNG(filePath):
     67     global filenum
     68     fileData = None
     69     with open(filePath,'rb') as file:
     70         fileData = encryption(preProcessPng(file.read()),_KEY)
     71     os.remove(filePath)
     72     with open(filePath,'wb') as file: #覆盖新文件
     73         file.write(fileData)
     74     filenum = filenum + 1
     75 
     76 
     77 
     78 def traverseDir(absDir):#遍历当前目录以及递归的子目录,找到所有的png图片
     79     """
     80     :param absDir: 要遍历的路径
     81     :return: None
     82     """
     83     assert (os.path.isdir(absDir) and os.path.isabs(absDir))
     84     dirName = absDir
     85     for fileName in os.listdir(absDir):
     86         absFileName = os.path.join(dirName,fileName)
     87         if os.path.isdir(absFileName):#递归查找文件夹
     88             traverseDir(absFileName)
     89         elif isPNG(absFileName):
     90             processPNG(absFileName)
     91         else:
     92             pass
     93 
     94 
     95 #------------------- 主函数-------------------------#
     96 start_clock = time.clock()
     97 filenum = 0
     98 #traverseDir(os.path.join(CUR_DIR,"png2"))
     99 traverseDir(CUR_DIR)
    100 end_clock = time.clock()
    101 time = (end_clock - start_clock)*1000
    102 print("encrypt %d Png Pictures"%filenum)
    103 print("use time %fms"%time)

    解密的cpp文件

    1.新增图片类型

     enum class Format
        {
            //! JPEG
            JPG,
            //! PNG
            PNG,
            //! ENCRYPTEDPNG
            ENCRYPTEDPNG, //加密后的Png图片
            //! TIFF
            TIFF,
            //! WebP
            WEBP,
            //! PVR
            PVR,
            //! ETC
            ETC,
            //! S3TC
            S3TC,
            //! ATITC
            ATITC,
            //! TGA
            TGA,
            //! Raw Data
            RAW_DATA,
            //! Unknown format
            UNKNOWN
        };

    2,修改检测图片类型的Image::detectFormat

    1 bool Image::isEncryptedPng(const unsigned char * data, ssize_t dataLen){
    2     if (dataLen <= 7 || memcmp("jiaozhi", data, 7) != 0){
    3         return false;
    4     }
    5     return true;
    6 }
     1 mage::Format Image::detectFormat(const unsigned char * data, ssize_t dataLen)
     2 {
     3     if (isPng(data, dataLen))
     4     {
     5         return Format::PNG;
     6     }
     7     else if(isEncryptedPng(data,dataLen)){
     8         return Format::ENCRYPTEDPNG;
     9     }
    10     else if (isJpg(data, dataLen))
    11     {
    12         return Format::JPG;
    13     }
    14     else if (isTiff(data, dataLen))
    15     {
    16         return Format::TIFF;
    17     }
    18     else if (isWebp(data, dataLen))
    19     {
    20         return Format::WEBP;
    21     }
    22     else if (isPvr(data, dataLen))
    23     {
    24         return Format::PVR;
    25     }
    26     else if (isEtc(data, dataLen))
    27     {
    28         return Format::ETC;
    29     }
    30     else if (isS3TC(data, dataLen))
    31     {
    32         return Format::S3TC;
    33     }
    34     else if (isATITC(data, dataLen))
    35     {
    36         return Format::ATITC;
    37     }
    38     else
    39     {
    40         return Format::UNKNOWN;
    41     }
    42 }

    3.修改Image::initWithImageData,进行解密png

     1 bool Image::initWithImageData(const unsigned char * data, ssize_t dataLen)
     2 {
     3     bool ret = false;
     4     do
     5     {
     6         CC_BREAK_IF(! data || dataLen <= 0);
     7         
     8         unsigned char* unpackedData = nullptr;
     9         ssize_t unpackedLen = 0;
    10         
    11         //detect and unzip the compress file
    12         if (ZipUtils::isCCZBuffer(data, dataLen))
    13         {
    14             unpackedLen = ZipUtils::inflateCCZBuffer(data, dataLen, &unpackedData);
    15         }
    16         else if (ZipUtils::isGZipBuffer(data, dataLen))
    17         {
    18             unpackedLen = ZipUtils::inflateMemory(const_cast<unsigned char*>(data), dataLen, &unpackedData);
    19         }
    20         else
    21         {
    22             unpackedData = const_cast<unsigned char*>(data);
    23             unpackedLen = dataLen;
    24         }
    25 
    26         _fileType = detectFormat(unpackedData, unpackedLen);
    27 
    28         switch (_fileType)
    29         {
    30         case Format::ENCRYPTEDPNG:
    31         {
    32             unsigned char* copyData = new unsigned char[unpackedLen+13];//8+12-7
    33             memcpy(copyData + 8, unpackedData+7, unpackedLen-7);
    34             deEncryptPng(&copyData, "jiaozi2013", unpackedLen + 13);
    35             ret = initWithPngData(copyData, unpackedLen + 13);
    36             delete[] copyData;
    37 
    38         }
    39             break;
    40         case Format::PNG:
    41             ret = initWithPngData(unpackedData, unpackedLen);
    42             break;
    43         case Format::JPG:
    44             ret = initWithJpgData(unpackedData, unpackedLen);
    45             break;
    46         case Format::TIFF:
    47             ret = initWithTiffData(unpackedData, unpackedLen);
    48             break;
    49         case Format::WEBP:
    50             ret = initWithWebpData(unpackedData, unpackedLen);
    51             break;
    52         case Format::PVR:
    53             ret = initWithPVRData(unpackedData, unpackedLen);
    54             break;
    55         case Format::ETC:
    56             ret = initWithETCData(unpackedData, unpackedLen);
    57             break;
    58         case Format::S3TC:
    59             ret = initWithS3TCData(unpackedData, unpackedLen);
    60             break;
    61         case Format::ATITC:
    62             ret = initWithATITCData(unpackedData, unpackedLen);
    63             break;
    64         default:
    65             {
    66                 // load and detect image format
    67                 tImageTGA* tgaData = tgaLoadBuffer(unpackedData, unpackedLen);
    68                 
    69                 if (tgaData != nullptr && tgaData->status == TGA_OK)
    70                 {
    71                     ret = initWithTGAData(tgaData);
    72                 }
    73                 else
    74                 {
    75                     CCLOG("cocos2d: unsupported image format!");
    76                 }
    77                 
    78                 free(tgaData);
    79                 break;
    80             }
    81         }
    82         
    83         if(unpackedData != data)
    84         {
    85             free(unpackedData);
    86         }
    87     } while (0);
    88     
    89     return ret;
    90 }

    4.新增Image::deEncryptPng做解密:

    void Image::deEncryptPng(unsigned char** copyData, const char* key, ssize_t dataLen){
        static const unsigned char PNG_SIGNATURE[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a };
        static const unsigned char PNG_IEND[] = { 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82 };
        unsigned char* _data = *copyData;
        memcpy(_data, PNG_SIGNATURE, 8);
        memcpy(_data + (dataLen - 12), PNG_IEND, 12);
        unsigned char* de_start = _data + 8;
        unsigned char* de_end = _data + dataLen - 13;
        ssize_t keyLen = strlen(key);
        ssize_t keyIndex = 0;
        for (; de_start <= de_end;de_start++,keyIndex++){
            if (keyIndex >= keyLen)
                keyIndex = 0;
            *de_start ^= key[keyIndex];
        }
    }

    最后加一句:python大法好。

  • 相关阅读:
    ValueError: max() arg is an empty sequence
    链接到镜像
    SparkStreaming+Kafka
    软件质量六大属性—
    架构之美3
    架构之美2
    架构之美-读书笔记之一
    机器学习四正则化(Regularization)
    机器学习三--各种差
    机器学习系列(二)——回归模型
  • 原文地址:https://www.cnblogs.com/pixs-union/p/6226337.html
Copyright © 2011-2022 走看看