使用AES加密游戏资源文件

在研究Angry Birds的过程当中了解到其部分lua脚本文件被进行了加密,关于如何解密以及如何找到解密key的方法见前一篇博客。游戏资源文件加密是pc上的游戏必作的一件事,虽然不管何种加密方法都没法阻止别人的破解,可是加密至少可以提升应用被破解的门槛,说白了就是不能让随便一我的都能看到里面的一切。python

Andgry Birds对lua文件的加密采用的是AES加密算法,使用CBC模式,另外原始文件内容还进行了7z压缩。为了可以解密,AES加密的key必然会保存在应用的某个地方,因此别人仍是可以找到破解的方法,可以还原出原始的资源文件,具体用到的方法就是前一篇博客里说到的。android

在学习如何解密的过程当中找到了一篇不错的文章,介绍如何使用Python的PyCrypto模块来对文件进行AES加密,而且提供了python编写的加密解密源代码,在后面的评论中有人将其进行了改造,支持streamio模式的加密解密,也就是能够操做内存数据。算法

代码具备很高的实用价值,若是须要在本身的应用中添加一个加密模块,这是个不错的开始,虽然不必定会采用python来实现。dom

代码以下:ide

#!/usr/bin/env python
#
# Code adapted from: http://eli.thegreenplace.net/2010/06/25/aes-encryption-of-files-in-python-with-pycrypto/
#
#

import os, random, struct
from Crypto.Cipher import AES
from StringIO import StringIO
import hashlib
import base64

## def encrypt_file(key, in_filename, out_filename=None, chunksize=64*1024):
## ( This is an adaptation from using filenames in order that StringIO can be used to encrypt a string. )
## Note: If in_file / out_file is provided, open with +b!

def encrypt_file(key, in_file, out_file=None, chunksize=64*1024):
    """ Encrypts a file using AES (CBC mode) with the
        given key.

        key:
            The encryption key - a string that must be
            either 16, 24 or 32 bytes long. Longer keys
            are more secure.

        in_file:
            Input file

        out_file:
            If None, a StringIO will be returned.

        chunksize:
            Sets the size of the chunk which the function
            uses to read and encrypt the file. Larger chunk
            sizes can be faster for some files and machines.
            chunksize must be divisible by 16.
    """
    if not out_file:
        out_file = StringIO()

    iv = ''.join(chr(random.randint(0, 0xFF)) for i in range(16))
    encryptor = AES.new(key, AES.MODE_CBC, iv)

    in_file.seek(0,2)
    filesize=in_file.tell()
    in_file.seek(0)

    # filesize = os.path.getsize(in_file)

    infile=in_file

    outfile=out_file
    outfile.seek(0)

    outfile.write(struct.pack('<Q', filesize))
    outfile.write(iv)

    while True:

        chunk = infile.read(chunksize)
        if len(chunk) == 0:
            break
        elif len(chunk) % 16 != 0:
            chunk += ' ' * (16 - len(chunk) % 16)

        outfile.write(encryptor.encrypt(chunk))

    outfile.seek(0)
    return outfile

## def decrypt_file(key, in_filename, out_filename=None, chunksize=24*1024):
## ( This is an adaptation from using filenames in order that StringIO can be used to encrypt a string. )
## Note: If in_file / out_file is provided, open with +b!

def decrypt_file(key, in_file, out_file=None, chunksize=24*1024):
    """ Decrypts a file using AES (CBC mode) with the
        given key. Parameters are similar to encrypt_file.
    """
    if not out_file:
        out_file = StringIO()

    infile=in_file
    infile.seek(0)

    outfile=out_file
    outfile.seek(0)

    origsize = struct.unpack('<Q', infile.read(struct.calcsize('Q')))[0]
    iv = infile.read(16)
    decryptor = AES.new(key, AES.MODE_CBC, iv)

    while True:
        chunk = infile.read(chunksize)
        if len(chunk) == 0:
            break
        outfile.write(decryptor.decrypt(chunk))

    outfile.truncate(origsize)

    outfile.seek(0)
    return outfile

# Method suggested by Eli by turn mnemonic password into 32 byte key.
def getHashKey(aKey):
    return hashlib.sha256(aKey).digest()

# My ( J. Norment's ) Additions
def getInFile(aFileName=None):
    if not aFileName:
        return StringIO()
    else:
        return open(aFileName,'rb')

def getOutFile(aFileName=None):
    if not aFileName:
        return StringIO()
    else:
        return open(aFileName,'wb')

def getB64encoded(aString):
    return base64.b64encode(aString)

def getB64decoded(aString):
    return base64.b64decode(aString)

原创文章,转载请注明: 转载自All-iPad.net学习

本文连接地址: 使用AES加密游戏资源文件加密

相关文章
相关标签/搜索