您的位置:首页 > 其它

简单的远程加解密文件

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/
版权:本文版权归作者和博客园共有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: