简单的远程加解密文件


本例通过客户端和服务器端来为大家展示一下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/
 版权:本文版权归作者和博客园共有
 转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
posted @ 2016-04-07 20:48  N_Vampire  阅读(709)  评论(0编辑  收藏  举报