Пример #1
0
 def upload_file(cls, user, data):
     from hashlib import sha512
     from config import allowed_file_suffix_list
     filename = data.filename
     assert len(filename) <= 64, 'filename too long (>64B)'
     assert filename_pattern.fullmatch(filename), 'no unicode character allowed'
     filename_suffix = filename.rsplit('.', maxsplit=1)[-1]
     assert filename_suffix in allowed_file_suffix_list, 'banned file type'
     f = File.query.filter(and_(File.creator_id == user.id_, File.filename == filename)).first()
     assert not f, 'file already exists'
     content = data.read()
     assert len(content) < 1*1024*1024, 'file too large (>=10MB)'
     user_id = str(user.id_)+'/'
     if not path.exists(storage_path+user_id):
         if not path.exists(storage_path):
             mkdir(storage_path)
         mkdir(storage_path+user_id)
     # 计算原文件的哈希
     hash_value = sha512(content).hexdigest()
     # 判断文件是否存在
     if not path.exists(storage_path+user_id+hash_value):
         # 加密并存储。加密前得先还原出对称密钥。
         content = secret.symmetric_encrypt(secret.decrypt(user.encrypted_symmetric_key), content)
         # 同时计算签名
         signature = secret.sign(content)
         # 保存密文与签名
         with open(storage_path+user_id+hash_value, 'wb') as f:
             f.write(content)
         with open(storage_path+user_id+hash_value+'.sig', 'wb') as f:
             f.write(signature)
     creator_id = user.id_
     file = File(creator_id=creator_id, filename=filename, hash_value=hash_value)
     db.session.add(file)
     db.session.commit()
Пример #2
0
def show_msg_detail():
    from config import domain_name, sy_private_key
    from flask import jsonify
    from models import Share
    import secret, traceback

    try:
        shareid = request.form['sid']
        msgid = request.form['mid']
        share = Share.get_by(id_=shareid)
        Message.set_readed(msgid)
        link = 'http://' + domain_name + '/share/verify?fid=' + str(
            share.fid) + '&nonce=' + share.nonce
        # 使用服务器私钥解密分享码
        sk = secret.decrypt(bytes.fromhex(sy_private_key), share.enc_sharekey)
        return jsonify(link=link, sharekey=sk.hex())
    except Exception as e:
        return e.args
Пример #3
0
    def download_file(cls, user, fid, type_):
        from flask import make_response, send_file
        from collections import OrderedDict
        import unicodedata
        from werkzeug.http import dump_options_header
        from werkzeug.urls import url_quote

        f = File.query.filter(File.fileid == fid).first()
        assert f, '文件不存在'
        hash_value = f.sha256
        filename = f.filename
        user_ = OnlineUser.query.filter(OnlineUser.usrid == user.usrid).first()
        # 获取私钥解密得对称密钥
        Pk = user_.Pk
        enc_key = secret.decrypt(Pk, user.symkey)
        with open(storage_path + str(user.usrid) + '/' + hash_value, 'rb') as f_:
            content = f_.read()
            if type_ == 'encrypted':
                filename = filename + '.encrypted'
            elif type_ == 'hashvalue':
                content = hash_value
                filename = filename + '.hash'
            else:
                content = secret.symmetric_decrypt(enc_key, content)
                if type_ == 'signature':
                    content = secret.sign(Pk, content)
                    filename = filename + '.sig'
            response = make_response(content)
            filenames = OrderedDict()
            try:
                filename = filename.encode('latin-1')
            except UnicodeEncodeError:
                filenames['filename'] = unicodedata.normalize('NFKD', filename).encode('latin-1', 'ignore')
                filenames['filename*']: "UTF-8''{}".format(url_quote(filename))
            else:
                filenames['filename'] = filename
            response.headers.set('Content-Disposition', 'attachment', **filenames)
            return response
Пример #4
0
    def decrypt_and_encrypt(cls, fid, user, sym_key):
        from .file import File
        from .online_user import OnlineUser
        import secret

        # 获取私钥解密获得对称密钥
        usr = OnlineUser.query.filter(OnlineUser.usrid == user.usrid).first()
        Pk = usr.Pk
        enc_key = secret.decrypt(Pk, user.symkey)
        # 查询、读取本地存储的加密文件
        f = File.get_by(fileid = fid)
        hash_value = f.sha256
        with open(storage_path + str(user.usrid) + '/' + hash_value, 'rb') as f:
            content = f.read()

        # 解密文件
        content = secret.symmetric_decrypt(enc_key, content)
        # 用私钥签名
        sig = secret.sign(Pk, content)
        # 用新的会话密钥加密文件
        new_content = secret.symmetric_encrypt(sym_key, content)
        # 写入 shared_path
        user_id = str(user.usrid) + '/'
        head = shared_path + user_id
        full_path = head + hash_value
        if not path.exists(head):
            if not path.exists(shared_path):
                mkdir(shared_path)
            mkdir(head)

        # 判断文件是否存在
        # 分享文件夹要写入签名
        if not path.exists(full_path):
            with open(full_path, 'wb') as f:
                f.write(new_content)
            with open(full_path + '.sig', 'wb') as f:
                f.write(sig)
Пример #5
0
    def upload_file(cls, user, data):
        from hashlib import sha256
        from config import allowed_file_list

        filename = data.filename
        assert len(filename) <= 64, '文件名过长(>64B)'
        assert filename_pattern.fullmatch(filename), '文件名中不能包含以下字符:\n\\ / : * ? " < > |'
        mime_type = data.mimetype
        assert mime_type in allowed_file_list, '不支持的文件类型'

        content = data.read()
        hash_value = sha256(content).hexdigest()
        f = File.query.filter(and_(File.uid == user.usrid, File.sha256 == hash_value)).first()
        assert not f, '文件已存在'
        size = convert_bytes(len(content))
        assert len(content) < 20*1024*1024, '文件过大(>=20MB)'
        userid = str(user.usrid) + '/'
        hash_value = sha256(content).hexdigest()
        head = storage_path + userid
        if not path.exists(head):
            if not path.exists(storage_path):
                mkdir(storage_path)
            mkdir(head)
        if not path.exists(head + hash_value):
            # 还原对称密钥
            Pkv = OnlineUser.get_by(usrid = userid).Pk
            encrypted_symkey = User.get_by(usrid = userid).symkey
            symkey = secret.decrypt(Pkv, encrypted_symkey)
            # 加密
            content = secret.symmetric_encrypt(symkey, content)
            # 只保存密文
            with open(head + hash_value, 'wb') as f:
                f.write(content)
        fi = File(uid=user.usrid, filename=filename, size=size, sha256=hash_value)
        db.session.add(fi)
        db.session.commit()
Пример #6
0
 def download_file(cls, user, filename, type_):
     from flask import make_response
     f = File.query.filter(and_(File.creator_id == user.id_, File.filename == filename)).first()
     assert f, 'no such file ({})'.format(filename)
     hash_value = f.hash_value
     if type_ == 'hashvalue':
         content = hash_value
         filename = filename + '.hash'
     elif type_ == 'signature':
         # 读取签名
         with open(storage_path+str(user.id_)+'/'+hash_value+'.sig', 'rb') as f_:
             content = f_.read()
             filename = filename+'.sig'
     else:
         # 读取密文
         with open(storage_path+str(user.id_)+'/'+hash_value, 'rb') as f_:
             content = f_.read()
         if type_ == 'plaintext':
             content = secret.symmetric_decrypt(secret.decrypt(user.encrypted_symmetric_key), content)
         elif type_ == 'encrypted':
             filename = filename + '.encrypted'
     response = make_response(content)
     response.headers['Content-Disposition'] = 'attachment; filename={}'.format(filename)
     return response