使用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加密遊戲資源文件加密

相關文章
相關標籤/搜索