简单的远程加解密文件
2016-04-07 20:48
267 查看
本例通过客户端和服务器端来为大家展示一下AES来远程加解密文件(相关库的使用请自行搜索),通过socket来进行客户端和服务器的通信,客户端对服务器发送过来的密钥字符串、
iv值和一个字符串(可以为任意值),对客户端相应的文件进行加密操作,在这里大家可以将所有的文件都进行加密操作,请自行测试,但是请大家在测试期间,
不要使用自己重要的文件来测试,可以创建一些无用的文件来测试。
各位大牛请绕过,不要喷 ......
客户端主要是使用服务器上发送过来的key长度进行判断是否为16的整数倍,如果不够则使用随机数来将key填充到AES加解密的要求为止,然后使用getKey将所有生成的随机数进行保存,
然后再将其加密后,发送到服务器上。加密的密钥是服务器上发送过来的key加上getKey本地生成的随机数字符串,在不知道服务器上保存的数据和密钥及长度,大大增加了解密的难度。
具体的客户端代码如下:
""" write by HuSoul """ # 客户端代码 # -*- coding:utf-8 -*- import random from Crypto.Cipher import AES import socket # 使用AES加密文件的函数 def AESEncrypt_File(fs,key=b'123456789!@#$%^&',iv='3333333333333333',keyList='123456789!@#$%^&*(ABCDEFGHI'): keyLength = len(key) getKey = '' # 保存在本地生成的所有随机数 key_b = key # 加密随机数的密钥 if keyLength not in [16,24,32]: if keyLength < 16: key_b = key_b + keyList[6:16 - keyLength + 6] # 至于这个密钥的选择可以自己定义一个空间,保证该密钥是16的整数倍 for i in range(16 - keyLength): r = chr(random.randint(33,126)) # 生成随机数 33-126的可见字符 key += r # 将发送过来不够长度的密钥,加上随机字符到合法的密钥 getKey += r elif 16 < keyLength < 24: key_b = key_b + keyList[9:24 - keyLength + 9] for i in range(24 - keyLength): r = chr(random.randint(33,126)) key += r getKey += r elif 24 < keyLength < 32: key_b = key_b + keyList[11:32 - keyLength + 11] for i in range(32 - keyLength): r = chr(random.randint(33,126)) key += r getKey += r else: key = key[0:32] cipherFile = AES.new(key,AES.MODE_CBC,iv) # 生成加密时使用的实际密码 enKey = AES.new(key_b,AES.MODE_CBC,iv) x = len(fs) % 16 # 因为AES分块大小固定为16字节,所以要判断输入的文本是否为16字节的整数倍 fs_pad = '' if x != 0: fs_pad = fs + '0' * (16 - x) # 当不是16字节的整数倍,就使用 '0' 字符补足 print('fs_pad is :' + fs_pad) print(len(fs_pad)) print(len(fs_pad) % 16) msg = cipherFile.encrypt(fs_pad) # 加密文件流 if len(getKey.strip()) < 16: getKey += '*' * (16 - len(getKey)) remainingKey = enKey.encrypt(getKey) # 加密剩下的key return msg,remainingKey # 使用AES解密文件的函数 def AESDecrypt_File(fs,key=b'123456789!@#$%^&',iv='3333333333333333'): # AES key must be either 16, 24, or 32 bytes long cipher = AES.new(key,AES.MODE_CBC,iv) x = len(fs) % 16 # 因为AES分块大小固定为16字节,所以要判断输入的文本是否为16字节的整数倍 fs_pad = fs if x != 0: fs_pad += '0' * (16 - x) # 当不是16字节的整数倍,就使用 '0' 字符补足 print('fs_pad is :' + fs_pad) print(len(fs_pad)) print(len(fs_pad) % 16) msg_pd = cipher.decrypt(fs_pad) return msg_pd def EncryptFile(fs,key=b'123456789!@#$%^&',iv='3333333333333333',keyList=''): getFile = open(fs,'rb') getFile.seek(0,0) fs_msg = getFile.read() getFile.close() # encrypt src FileStream fsCon = fs.split('.') fen = open(fsCon[0]+'_b.'+ fsCon[1],'wb') fen_msg,getKey = AESEncrypt_File(fs_msg,key,iv,keyList) fen.writelines(fen_msg) fen.close() return getKey def DecryptFile(fs,key=b'123456789!@#$%^&',iv='3333333333333333'): getFile = open(fs,'rb') getFile.seek(0,0) fs_msg = getFile.read() getFile.close() # decrypt src FileStream fsCon = fs.split('.') fde = open(fsCon[0] + 'b.' + fsCon[1],'wb') fde_msg = AESDecrypt_File(fs_msg,key,iv) fde.writelines(fde_msg) fde.close() # 与服务器通信 def Connection(): """ Connecting by Client :return: """ ID = 12345678 Host = '127.0.0.1' Port = 7896 # 先获取相应的密钥信息 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.bind((Host,Port)) s.listen(5) q = True getKey = '' while True: conn,addr = s.accept() while q: # 接收相应的密钥 iv string receive = conn.recv(1024) info = receive.split(':') if info[0] == 'en': # Encrypt test getKey = EncryptFile('Desert.jpg',info[1],info[2],info[3]) conn.close() print('file is already encrypt successfully') q = False # 再发送剩余的密钥给服务器 c2s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) c2s.connect((Host,9999)) c2s.sendall(str(ID) + '0x255' + getKey) c2s.close() elif info[0] == 'de': # Decrypt test DecryptFile('Desert_b.jpg',info[1],info[2]) conn.close() print('file is already decrypt successfully') # 发送信息给服务器 c2s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) c2s.connect((Host,9999)) c2s.sendall('de:Decrypt Successfully ...') c2s.close() q = False if __name__ == '__main__': Connection()
在服务器端则只需使用socket进行对客户端进行连接(对于socket的使用请自行搜索),设置相关的参数和值,发送相应的数据和命令来达到加解密远程文件的操作。
# 服务器端的代码 # -*- coding:utf-8 -*- import socket from Crypto.Cipher import AES Host = '127.0.0.1' Port = 9999 # key key = 'testtest' # iv iv = '1234567890QWERTY' # iv是要求要16位、24位和32位的,与加密的密钥长度一样,这个值可以自己修改 # keyList keyList = '1$d9Ry*g2^Sj0&b%3)+6}vP4@,Wv-+A)' # 用于加密随机数时,填充到密钥的后面的字符集 keyLength = len(key) # 加密代码 s2cEn = socket.socket(socket.AF_INET,socket.SOCK_STREAM) s2cEn.connect((Host,7896)) s2cEn.sendall('en'+ ':' + key + ':' + iv + ':' + keyList) # 获取远程主机发送过来的加密随机数字符串 ss = socket.socket(socket.AF_INET,socket.SOCK_STREAM) ss.bind((Host,Port)) ss.listen(5) q = True getKey = '' while True: conn,addr = ss.accept() while q: remainingKey = conn.recv(1024) conn.close() print('Successful to get the person key by : ' + str(addr)) q = False if keyLength not in [16,24,32]: if keyLength < 16: key_b = key + keyList[6:16 - keyLength + 6] elif 16 < keyLength < 24: key_b = key + keyList[9:24 - keyLength + 9] elif 24 < keyLength < 32: key_b = key + keyList[11:32 - keyLength + 11] else: key = key[0:32] # decrypt received remainingKey remainKey = remainingKey.split('0x255') print('remainKey[1] : ' + remainKey[1]) decryptRekey = AES.new(key_b,AES.MODE_CBC,iv) getKey = decryptRekey.decrypt(remainKey[1]) print(getKey) # 获取随机数 # 解密代码 getKey = '12345678' # 随机数字符串,从上述的加密代码中控制台输出的getKey值 deKey = key + getKey s2cDe = socket.socket(socket.AF_INET,socket.SOCK_STREAM) s2cDe.connect((Host,7896)) s2cDe.sendall('de' + ':' + deKey + ':' + iv)
当你要解密远程文件时,调用解密代码进行解密文件,但是此时应当将上述加密的代码注释,当然你可以用一个选项来选择相应的操作, 对远程主机进行操作,可以修改适当的代码来达到你的需求。 至于上述的过程虽然没有将所有的代码都解释的很清楚,但是我相信代码上的注释大家还是可以看懂的。虽然这段代码的意义不大,在一些加密文件的手段上也是用代码堆积而成的, 但是我希望可以给大家编写程序时带来灵感,通过不同的案例来启发大家对编程的热爱。 免责声明: 请勿用于非法用途,如有盗用,后果自负,一切责任与本人无关
作者:http://www.cnblogs.com/GHost-Ma/ 出处:http://www.cnblogs.com/GHost-Ma/ 版权:本文版权归作者和博客园共有 转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
相关文章推荐
- HNOI模拟4.7 yist
- MRD文档的写作----产品经理深入浅出课程
- 坑爹的rectOfInterest
- [POJ 3764] The xor-longest Path (Tire树 + 贪心)
- 分布式版本控制系统Git------初涉Git
- weblogic uddiexplorer的漏洞
- Django中的Model(操作表) - 第五轻柔的code - 博客园
- 筛素数——POJ 2909 Goldbach's Conjecture
- 互斥锁与条件变量
- ROS--tutorial命令记录
- android中的相对布局RelativeLayout
- 生产消费模型实例C++11
- [置顶] windows上node-webkit安装sqlite、socket的那些坑
- 。
- Java基础几个问题
- 1050. 螺旋矩阵(25)
- 『NYIST』第八届河南省ACM竞赛训练赛[正式赛一] E题
- nyoj 91 阶乘之和
- 李娜跟姜山
- 返回一个整数数组中最大子数组的和。