mirror of https://github.com/axmolengine/axmol.git
Promote global functions and variables for PVR decryption to ZipUtils class.
Rename PVR decryption functions and variables to better fit in the Cocos2DX framework. Improve log error notes. Update TextureAtlasEncryptionTest to match revised function call in ZipUtils. Update ccSetPvrEncryptionKeyPart documentation to clarify that encryption is never 100% secure.
This commit is contained in:
parent
f89d39953e
commit
040e6fc5b9
|
@ -33,23 +33,13 @@
|
|||
|
||||
NS_CC_BEGIN
|
||||
|
||||
static unsigned int caw_key[4] = {0,0,0,0};
|
||||
static unsigned int caw_longKey[1024];
|
||||
static bool caw_longKeyValid = false;
|
||||
unsigned int ZipUtils::s_uEncryptedPvrKeyParts[4] = {0,0,0,0};
|
||||
unsigned int ZipUtils::s_uEncryptionKey[1024];
|
||||
bool ZipUtils::s_bEncryptionKeyIsValid = false;
|
||||
|
||||
void caw_setkey_part(int index, unsigned int value)
|
||||
{
|
||||
CCAssert(index >= 0, "Cocos2d: key part index cannot be less than 0");
|
||||
CCAssert(index <= 3, "Cocos2d: key part index cannot be greater than 3");
|
||||
|
||||
if(caw_key[index] != value)
|
||||
{
|
||||
caw_key[index] = value;
|
||||
caw_longKeyValid = false;
|
||||
}
|
||||
}
|
||||
// --------------------- ZipUtils ---------------------
|
||||
|
||||
static inline void caw_encdec (unsigned int *data, int len)
|
||||
inline void ZipUtils::ccDecodeEncodedPvr(unsigned int *data, int len)
|
||||
{
|
||||
const int enclen = 1024;
|
||||
const int securelen = 512;
|
||||
|
@ -57,39 +47,39 @@ static inline void caw_encdec (unsigned int *data, int len)
|
|||
|
||||
// check if key was set
|
||||
// make sure to call caw_setkey_part() for all 4 key parts
|
||||
CCAssert(caw_key[0] != 0, "Cocos2D: CCZ file is encrypted but key part 0 is not set. Did you call caw_setkey_part(...)?");
|
||||
CCAssert(caw_key[1] != 0, "Cocos2D: CCZ file is encrypted but key part 1 is not set. Did you call caw_setkey_part(...)?");
|
||||
CCAssert(caw_key[2] != 0, "Cocos2D: CCZ file is encrypted but key part 2 is not set. Did you call caw_setkey_part(...)?");
|
||||
CCAssert(caw_key[3] != 0, "Cocos2D: CCZ file is encrypted but key part 3 is not set. Did you call caw_setkey_part(...)?");
|
||||
CCAssert(s_uEncryptedPvrKeyParts[0] != 0, "Cocos2D: CCZ file is encrypted but key part 0 is not set. Did you call ZipUtils::ccSetPvrEncryptionKeyPart(...)?");
|
||||
CCAssert(s_uEncryptedPvrKeyParts[1] != 0, "Cocos2D: CCZ file is encrypted but key part 1 is not set. Did you call ZipUtils::ccSetPvrEncryptionKeyPart(...)?");
|
||||
CCAssert(s_uEncryptedPvrKeyParts[2] != 0, "Cocos2D: CCZ file is encrypted but key part 2 is not set. Did you call ZipUtils::ccSetPvrEncryptionKeyPart(...)?");
|
||||
CCAssert(s_uEncryptedPvrKeyParts[3] != 0, "Cocos2D: CCZ file is encrypted but key part 3 is not set. Did you call ZipUtils::ccSetPvrEncryptionKeyPart(...)?");
|
||||
|
||||
// create long key
|
||||
if(!caw_longKeyValid)
|
||||
if(!s_bEncryptionKeyIsValid)
|
||||
{
|
||||
unsigned int y, p, e;
|
||||
unsigned int rounds = 6;
|
||||
unsigned int sum = 0;
|
||||
unsigned int z = caw_longKey[enclen-1];
|
||||
unsigned int z = s_uEncryptionKey[enclen-1];
|
||||
|
||||
do
|
||||
{
|
||||
#define DELTA 0x9e3779b9
|
||||
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (caw_key[(p&3)^e] ^ z)))
|
||||
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (s_uEncryptedPvrKeyParts[(p&3)^e] ^ z)))
|
||||
|
||||
sum += DELTA;
|
||||
e = (sum >> 2) & 3;
|
||||
|
||||
for (p = 0; p < enclen - 1; p++)
|
||||
{
|
||||
y = caw_longKey[p + 1];
|
||||
z = caw_longKey[p] += MX;
|
||||
y = s_uEncryptionKey[p + 1];
|
||||
z = s_uEncryptionKey[p] += MX;
|
||||
}
|
||||
|
||||
y = caw_longKey[0];
|
||||
z = caw_longKey[enclen - 1] += MX;
|
||||
y = s_uEncryptionKey[0];
|
||||
z = s_uEncryptionKey[enclen - 1] += MX;
|
||||
|
||||
} while (--rounds);
|
||||
|
||||
caw_longKeyValid = true;
|
||||
s_bEncryptionKeyIsValid = true;
|
||||
}
|
||||
|
||||
int b = 0;
|
||||
|
@ -98,7 +88,7 @@ static inline void caw_encdec (unsigned int *data, int len)
|
|||
// encrypt first part completely
|
||||
for(; i < len && i < securelen; i++)
|
||||
{
|
||||
data[i] ^= caw_longKey[b++];
|
||||
data[i] ^= s_uEncryptionKey[b++];
|
||||
|
||||
if(b >= enclen)
|
||||
{
|
||||
|
@ -109,7 +99,7 @@ static inline void caw_encdec (unsigned int *data, int len)
|
|||
// encrypt second section partially
|
||||
for(; i < len; i += distance)
|
||||
{
|
||||
data[i] ^= caw_longKey[b++];
|
||||
data[i] ^= s_uEncryptionKey[b++];
|
||||
|
||||
if(b >= enclen)
|
||||
{
|
||||
|
@ -118,7 +108,7 @@ static inline void caw_encdec (unsigned int *data, int len)
|
|||
}
|
||||
}
|
||||
|
||||
static inline unsigned int caw_checksum(const unsigned int *data, int len)
|
||||
inline unsigned int ZipUtils::ccChecksumPvr(const unsigned int *data, int len)
|
||||
{
|
||||
unsigned int cs = 0;
|
||||
const int cslen = 128;
|
||||
|
@ -133,8 +123,6 @@ static inline unsigned int caw_checksum(const unsigned int *data, int len)
|
|||
return cs;
|
||||
}
|
||||
|
||||
// --------------------- ZipUtils ---------------------
|
||||
|
||||
// memory in iPhone is precious
|
||||
// Should buffer factor be 1.5 instead of 2 ?
|
||||
#define BUFFER_INC_FACTOR (2)
|
||||
|
@ -377,16 +365,16 @@ int ZipUtils::ccInflateCCZFile(const char *path, unsigned char **out)
|
|||
unsigned int* ints = (unsigned int*)(compressed+12);
|
||||
int enclen = (fileLen-12)/4;
|
||||
|
||||
caw_encdec(ints, enclen);
|
||||
ccDecodeEncodedPvr(ints, enclen);
|
||||
|
||||
#if COCOS2D_DEBUG > 0
|
||||
// verify checksum in debug mode
|
||||
unsigned int calculated = caw_checksum(ints, enclen);
|
||||
unsigned int calculated = ccChecksumPvr(ints, enclen);
|
||||
unsigned int required = CC_SWAP_INT32_BIG_TO_HOST( header->reserved );
|
||||
|
||||
if(calculated != required)
|
||||
{
|
||||
CCLOG("cocos2d: Can't decrypt image file: Invalid decryption key");
|
||||
CCLOG("cocos2d: Can't decrypt image file. Is the decryption key valid?");
|
||||
delete [] compressed;
|
||||
return -1;
|
||||
}
|
||||
|
@ -426,6 +414,18 @@ int ZipUtils::ccInflateCCZFile(const char *path, unsigned char **out)
|
|||
return len;
|
||||
}
|
||||
|
||||
void ZipUtils::ccSetPvrEncryptionKeyPart(int index, unsigned int value)
|
||||
{
|
||||
CCAssert(index >= 0, "Cocos2d: key part index cannot be less than 0");
|
||||
CCAssert(index <= 3, "Cocos2d: key part index cannot be greater than 3");
|
||||
|
||||
if(s_uEncryptedPvrKeyParts[index] != value)
|
||||
{
|
||||
s_uEncryptedPvrKeyParts[index] = value;
|
||||
s_bEncryptionKeyIsValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------- ZipFile ---------------------
|
||||
// from unzip.cpp
|
||||
#define UNZ_MAXFILENAMEINZIP 256
|
||||
|
|
|
@ -28,42 +28,22 @@ THE SOFTWARE.
|
|||
|
||||
namespace cocos2d
|
||||
{
|
||||
/**
|
||||
* Set the TexturePacker encryption key
|
||||
*
|
||||
* If your key used to encrypt the pvr.ccz file is
|
||||
* aaaaaaaabbbbbbbbccccccccdddddddd
|
||||
* you have to call this function 4 times:
|
||||
* caw_setkey_part(0, 0xaaaaaaaa);
|
||||
* caw_setkey_part(1, 0xbbbbbbbb);
|
||||
* caw_setkey_part(2, 0xcccccccc);
|
||||
* caw_setkey_part(3, 0xdddddddd);
|
||||
*
|
||||
* Distribute the call accross some files but make sure
|
||||
* to call all of the parts *before* loading the first
|
||||
* spritesheet.
|
||||
*
|
||||
* @param index part of the key [0..3]
|
||||
* @param value value of the key part
|
||||
*/
|
||||
void caw_setkey_part(int index, uint32_t value);
|
||||
|
||||
/* XXX: pragma pack ??? */
|
||||
/** @struct CCZHeader
|
||||
*/
|
||||
struct CCZHeader {
|
||||
unsigned char sig[4]; // signature. Should be 'CCZ!' 4 bytes
|
||||
unsigned short compression_type; // should 0
|
||||
unsigned short version; // should be 2 (although version type==1 is also supported)
|
||||
unsigned int reserved; // Reserved for users.
|
||||
unsigned int len; // size of the uncompressed file
|
||||
unsigned char sig[4]; // signature. Should be 'CCZ!' 4 bytes
|
||||
unsigned short compression_type; // should 0
|
||||
unsigned short version; // should be 2 (although version type==1 is also supported)
|
||||
unsigned int reserved; // Reserved for users.
|
||||
unsigned int len; // size of the uncompressed file
|
||||
};
|
||||
|
||||
enum {
|
||||
CCZ_COMPRESSION_ZLIB, // zlib format.
|
||||
CCZ_COMPRESSION_BZIP2, // bzip2 format (not supported yet)
|
||||
CCZ_COMPRESSION_GZIP, // gzip format (not supported yet)
|
||||
CCZ_COMPRESSION_NONE, // plain (not supported yet)
|
||||
CCZ_COMPRESSION_ZLIB, // zlib format.
|
||||
CCZ_COMPRESSION_BZIP2, // bzip2 format (not supported yet)
|
||||
CCZ_COMPRESSION_GZIP, // gzip format (not supported yet)
|
||||
CCZ_COMPRESSION_NONE, // plain (not supported yet)
|
||||
};
|
||||
|
||||
class ZipUtils
|
||||
|
@ -108,9 +88,38 @@ namespace cocos2d
|
|||
*/
|
||||
static int ccInflateCCZFile(const char *filename, unsigned char **out);
|
||||
|
||||
/**
|
||||
* Set the pvr.ccz encryption key
|
||||
*
|
||||
* If your key used to encrypt the pvr.ccz file is
|
||||
* aaaaaaaabbbbbbbbccccccccdddddddd
|
||||
* you have to call this function 4 times:
|
||||
* ZipUtils::caw_setkey_part(0, 0xaaaaaaaa);
|
||||
* ZipUtils::caw_setkey_part(1, 0xbbbbbbbb);
|
||||
* ZipUtils::caw_setkey_part(2, 0xcccccccc);
|
||||
* ZipUtils::caw_setkey_part(3, 0xdddddddd);
|
||||
*
|
||||
* Distribute the call across some files but make sure
|
||||
* to call all of the parts *before* loading the first
|
||||
* spritesheet.
|
||||
*
|
||||
* Note that encrpytion is *never* 100% secure and the key code
|
||||
* can be cracked by knowledgable persons.
|
||||
*
|
||||
* @param index part of the key [0..3]
|
||||
* @param value value of the key part
|
||||
*/
|
||||
static void ccSetPvrEncryptionKeyPart(int index, unsigned int value);
|
||||
|
||||
private:
|
||||
static int ccInflateMemoryWithHint(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int *outLength,
|
||||
unsigned int outLenghtHint);
|
||||
unsigned int outLenghtHint);
|
||||
static inline void ccDecodeEncodedPvr (unsigned int *data, int len);
|
||||
static inline unsigned int ccChecksumPvr(const unsigned int *data, int len);
|
||||
|
||||
static unsigned int s_uEncryptedPvrKeyParts[4];
|
||||
static unsigned int s_uEncryptionKey[1024];
|
||||
static bool s_bEncryptionKeyIsValid;
|
||||
};
|
||||
|
||||
// forward declaration
|
||||
|
|
|
@ -44,10 +44,10 @@ void TextureAtlasEncryptionDemo::onEnter()
|
|||
|
||||
// Load the encrypted atlas
|
||||
// 1) Set the encryption keys or step 2 will fail
|
||||
caw_setkey_part(0, 0xaaaaaaaa);
|
||||
caw_setkey_part(1, 0xbbbbbbbb);
|
||||
caw_setkey_part(2, 0xcccccccc);
|
||||
caw_setkey_part(3, 0xdddddddd);
|
||||
ZipUtils::ccSetPvrEncryptionKeyPart(0, 0xaaaaaaaa);
|
||||
ZipUtils::ccSetPvrEncryptionKeyPart(1, 0xbbbbbbbb);
|
||||
ZipUtils::ccSetPvrEncryptionKeyPart(2, 0xcccccccc);
|
||||
ZipUtils::ccSetPvrEncryptionKeyPart(3, 0xdddddddd);
|
||||
|
||||
// 2) Load the encrypted atlas
|
||||
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("Images/encryptedAtlas.plist", "Images/encryptedAtlas.pvr.ccz");
|
||||
|
|
Loading…
Reference in New Issue