当前位置:编程学习 > 网站相关 >>

使用AES加密游戏资源文件

在研究Angry Birds的过程中了解到其部分lua脚本文件被进行了加密,关于如何解密以及如何找到解密key的方法见前一篇博客。游戏资源文件加密是pc上的游戏必做的一件事,虽然无论何种加密方法都无法阻止别人的破解,但是加密至少能够提高应用被破解的门槛,说白了就是不能让随便一个人都能看到里面的一切。
Andgry Birds对lua文件的加密采用的是AES加密算法,使用CBC模式,另外原始文件内容还进行了7z压缩。为了能够解密,AES加密的key必然会保存在应用的某个地方,所以别人还是能够找到破解的方法,能够还原出原始的资源文件,具体用到的方法就是前一篇博客里说到的。
在学习如何解密的过程中找到了一篇不错的文章,介绍如何使用Python的PyCrypto模块来对文件进行AES加密,并且提供了python编写的加密解密源代码,在后面的评论中有人将其进行了改造,支持streamio模式的加密解密,也就是可以操作内存数据。
代码具有很高的实用价值,如果需要在自己的应用中添加一个加密模块,这是个不错的开始,虽然不一定会采用python来实现。
代码如下:
001 #!/usr/bin/env python
002 #
003 # Code adapted from: http://eli.thegreenplace.net/2010/06/25/aes-encryption-of-files-in-python-with-pycrypto/
004 #
005 #
006 
007 import os, random, struct
008 from Crypto.Cipher import AES
009 from StringIO import StringIO
010 import hashlib
011 import base64
012 
013 ## def encrypt_file(key, in_filename, out_filename=None, chunksize=64*1024):
014 ## ( This is an adaptation from using filenames in order that StringIO can be used to encrypt a string. )
015 ## Note: If in_file / out_file is provided, open with +b!
016 
017 def encrypt_file(key, in_file, out_file=None, chunksize=64*1024):
018     """ Encrypts a file using AES (CBC mode) with the
019         given key.
020 
021         key:
022             The encryption key - a string that must be
023             either 16, 24 or 32 bytes long. Longer keys
024             are more secure.
025 
026         in_file:
027             Input file
028 
029         out_file:
030             If None, a StringIO will be returned.
031 
032         chunksize:
033             Sets the size of the chunk which the function
034             uses to read and encrypt the file. Larger chunk
035             sizes can be faster for some files and machines.
036             chunksize must be divisible by 16.
037     """
038     if not out_file:
039         out_file = StringIO()
040 
041     iv = ''.join(chr(random.randint(0, 0xFF)) for i in range(16))
042     encryptor = AES.new(key, AES.MODE_CBC, iv)
043 
044     in_file.seek(0,2)
045     filesize=in_file.tell()
046     in_file.seek(0)
047 
048     # filesize = os.path.getsize(in_file)
049 
050     infile=in_file
051 
052     outfile=out_file
053     outfile.seek(0)
054 
055     outfile.write(struct.pack('<Q', filesize))
056     outfile.write(iv)
057 
058     while True:
059 
060         chunk = infile.read(chunksize)
061         if len(chunk) == 0:
062             break
063         elif len(chunk) % 16 != 0:
064             chunk += ' ' * (16 - len(chunk) % 16)
065 
066         outfile.write(encryptor.encrypt(chunk))
067 
068     outfile.seek(0)
069     return outfile
070 
071 ## def decrypt_file(key, in_filename, out_filename=None, chunksize=24*1024):
072 ## ( This is an adaptation from using filenames in order that StringIO can be used to encrypt a string. )
073 ## Note: If in_file / out_file is provided, open with +b!
074 
075 def decrypt_file(key, in_file, out_file=None, chunksize=24*1024):
076     """ Decrypts a file using AES (CBC mode) with the
077         given key. Parameters are similar to encrypt_file.
078     """
079     if not out_file:
080         out_file = StringIO()
081 
082     infile=in_file
083     infile.seek(0)
084 
085     outfile=out_file
086     outfile.seek(0)
087 
088     origsize = struct.unpack('<Q', infile.read(struct.calcsize('Q')))[0]
089     iv = infile.read(16)
090     decryptor = AES.new(key, AES.MODE_CBC, iv)
091 
092     while True:
093         chunk = infile.read(chunksize)
094         if len(chunk) == 0:
095             break
096         outfile.write(decryptor.decrypt(chunk))
097 
098     outfile.truncate(origsize)
099 
100     outfile.seek(0)
101     return outfile
102 
103 # Method suggested by Eli by turn mnemonic password into 32 byte key.
104 def getHashKey(aKey):
105     return hashlib.sha256(aKey).digest()
106 
107 # My ( J. Norment's ) Additions
108 def getInFile(aFileName=None):
109     if not aFileName:
110         return StringIO()
111     else:
112         return open(aFileName,'rb')
113 
114 def getOutFile(aFileName=None):
115     if not aFileName:
116         return StringIO()
117     else:
118         return open(aFileName,'wb')
119 
120 def getB64encoded(aString):
121     return base64.b64encode(aString)
122&nb

补充:综合编程 , 安全编程 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,