通过客户端加密保护数据

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,内容安全 1000次 1年
云备份 Cloud Backup,100GB 3个月
简介: 客户端加密是指用户数据在发送给远端服务器之前就完成加密,而加密所用的密钥的明文只保留在本地,从而可以保证用户数据安全,即使数据泄漏别人也无法解密得到原始数据。 本文介绍如何基于oss的现有python sdk版本, 通过客户端加密来保护数据。 原理介绍 用户本地维护一对rsa密钥(rsa_pr

客户端加密是指用户数据在发送给远端服务器之前就完成加密,而加密所用的密钥的明文只保留在本地,从而可以保证用户数据安全,即使数据泄漏别人也无法解密得到原始数据。

本文介绍如何基于oss的现有python sdk版本, 通过客户端加密来保护数据。

原理介绍

  1. 用户本地维护一对rsa密钥(rsa_private_keyrsa_public_key)
  2. 每次上传object时,随机生成一个AES256类型的对称密钥data_key,然后用data_key加密原始content得到encrypt_content.
  3. rsa_public_key加密data_key, 得到encrypt_data_key, 作为用户的自定义meta放入请求头部,和encrypt_content一起发送到oss
  4. get object时,首先得到encrypt_content以及用户自定义meta中的encrypt_data_key
  5. 用户使用rsa_private_key解密encrypt_data_key得到data_key,然后用data_key解密encrypt_content得到原始content

:本文用户的密钥为非对称的RSA密钥, 加密object content时用的AES256-CTR算法, 详情可参考PyCrypto Document。本文旨在介绍如何通过object的自定义meta来实现客户端加密,至于加密密匙类型及加密算法,用户可以根据自己的需要进行选择。

架构图

client_encrypt

准备工作

  1. python sdk的安装和使用,参考 python sdk 快速安装
  2. 安装PyCrypto库
pip install pycrypto

完整python 示例代码

# -*- coding: utf-8 -*-

import os
import shutil
import base64
import random

import oss2

from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
from Crypto.Cipher import AES
from Crypto import Random
from Crypto.Util import Counter

# aes 256, key always is 32 bytes
_AES_256_KEY_SIZE = 32
_AES_CTR_COUNTER_BITS_LEN = 8 * 16

class AESCipher:
    def __init__(self, key=None, start=None):
        self.key = key
        self.start = start
        if not self.key:
            self.key = Random.new().read(_AES_256_KEY_SIZE)
        if not self.start:
            self.start = random.randint(1, 10)
        ctr = Counter.new(_AES_CTR_COUNTER_BITS_LEN, initial_value=self.start)
        self.cipher = AES.new(self.key, AES.MODE_CTR, counter=ctr)

    def encrypt(self, raw):
        return self.cipher.encrypt(raw)

    def decrypt(self, enc):
        return self.cipher.decrypt(enc)

# 首先初始化AccessKeyId、AccessKeySecret、Endpoint等信息。
# 通过环境变量获取,或者把诸如“<你的AccessKeyId>”替换成真实的AccessKeyId等。
#
# 以杭州区域为例,Endpoint可以是:
#   http://oss-cn-hangzhou.aliyuncs.com
#   https://oss-cn-hangzhou.aliyuncs.com
# 分别以HTTP、HTTPS协议访问。
access_key_id = os.getenv('OSS_TEST_ACCESS_KEY_ID', '<你的AccessKeyId>')
access_key_secret = os.getenv('OSS_TEST_ACCESS_KEY_SECRET', '<你的AccessKeySecret>')
bucket_name = os.getenv('OSS_TEST_BUCKET', '<你的Bucket>')
endpoint = os.getenv('OSS_TEST_ENDPOINT', '<你的访问域名>')

# 确认上面的参数都填写正确了
for param in (access_key_id, access_key_secret, bucket_name, endpoint):
    assert '<' not in param, '请设置参数:' + param

##### 0 prepare ########
# 0.1 生成rsa key文件并保存到disk 
rsa_private_key_obj = RSA.generate(2048)
rsa_public_key_obj = rsa_private_key_obj.publickey()
encrypt_obj = PKCS1_OAEP.new(rsa_public_key_obj)
decrypt_obj = PKCS1_OAEP.new(rsa_private_key_obj)

# save to local disk 
file_out = open("private_key.pem", "w")
file_out.write(rsa_private_key_obj.exportKey())
file_out.close()
file_out = open("public_key.pem", "w")
file_out.write(rsa_public_key_obj.exportKey())
file_out.close()

# 0.2 创建Bucket对象,所有Object相关的接口都可以通过Bucket对象来进行
bucket = oss2.Bucket(oss2.Auth(access_key_id, access_key_secret), endpoint, bucket_name)
obj_name = 'test-sig-1'
content = "test content"

#### 1 Put Object  ####
# 1.1 生成加密这个object所用的一次性的对称密钥 encrypt_cipher, 其中的key 和 start为随机生成的value
encrypt_cipher = AESCipher()

# 1.2 将辅助解密的信息用公钥加密后存到object的自定义meta中. 后续当我们get object时,就可以根据自定义meta,用私钥解密得到原始content
headers = {}
headers['x-oss-meta-x-oss-key'] = base64.b64encode(encrypt_obj.encrypt(encrypt_cipher.key))
headers['x-oss-meta-x-oss-start'] = base64.b64encode(encrypt_obj.encrypt(str(encrypt_cipher.start)))

# 1.3. 用 encrypt_cipher 对原始content加密得到encrypt_content
encryt_content = encrypt_cipher.encrypt(content)

# 1.4 上传object
result = bucket.put_object(obj_name, encryt_content, headers)
if result.status / 100 != 2:
    exit(1)

#### 2 Get Object ####
# 2.1 下载得到加密后的object
result = bucket.get_object(obj_name)
if result.status / 100 != 2:
    exit(1)
resp = result.resp
download_encrypt_content = resp.read()

# 2.2 从自定义meta中解析出之前加密这个object所用的key 和 start 
download_encrypt_key = base64.b64decode(resp.headers.get('x-oss-meta-x-oss-key', ''))
key = decrypt_obj.decrypt(download_encrypt_key)
download_encrypt_start = base64.b64decode(resp.headers.get('x-oss-meta-x-oss-start', ''))
start = int(decrypt_obj.decrypt(download_encrypt_start))

# 2.3 生成解密用的cipher, 并解密得到原始content
decrypt_cipher = AESCipher(key, start)
download_content = decrypt_cipher.decrypt(download_encrypt_content)
if download_content != content:
    print "Error!"
else:
    print "Decrypt ok. Content is: %s" % download_content
目录
相关文章
|
1月前
|
存储 安全 数据安全/隐私保护
解锁Python安全新姿势!AES加密:让你的数据穿上防弹衣,无惧黑客窥探?
【8月更文挑战第1天】在数字化时代,确保数据安全至关重要。AES(高级加密标准)作为一种强大的对称密钥加密算法,能有效保护数据免遭非法获取。AES支持128/192/256位密钥,通过多轮复杂的加密过程提高安全性。在Python中,利用`pycryptodome`库可轻松实现AES加密:生成密钥、定义IV,使用CBC模式进行加密与解密。需要注意的是,要妥善管理密钥并确保每次加密使用不同的IV。掌握AES加密技术,为数据安全提供坚实保障。
107 2
|
9天前
|
存储 安全 算法
RSA在手,安全我有!Python加密解密技术,让你的数据密码坚不可摧
【9月更文挑战第11天】在数字化时代,信息安全至关重要。传统的加密方法已难以应对日益复杂的网络攻击。RSA加密算法凭借其强大的安全性和广泛的应用场景,成为保护敏感数据的首选。本文介绍RSA的基本原理及在Python中的实现方法,并探讨其优势与挑战。通过使用PyCryptodome库,我们展示了RSA加密解密的完整流程,帮助读者理解如何利用RSA为数据提供安全保障。
27 5
|
12天前
|
安全 数据安全/隐私保护 Python
情书也能加密?Python AES&RSA,让每一份数据都充满爱的密码
【9月更文挑战第8天】在这个数字化时代,情书不再局限于纸笔,也可能以电子形式在网络中传递。为了确保其安全,Python提供了AES和RSA等加密工具,为情书编织爱的密码。首先,通过安装pycryptodome库,我们可以利用AES对称加密算法高效保护数据;接着,使用RSA非对称加密算法加密AES密钥和IV,进一步增强安全性。即使情书被截获,没有正确密钥也无法解读内容。让我们用Python为爱情编织一张安全的网,守护每份珍贵情感。
27 2
|
1月前
|
JavaScript 算法 数据安全/隐私保护
烯牛数据JS逆向:MD5数据加密?不存在的!
烯牛数据JS逆向:MD5数据加密?不存在的!
53 1
|
1月前
|
安全 数据安全/隐私保护 Python
|
1月前
|
JavaScript 数据安全/隐私保护 Python
东方财富股票数据JS逆向:secids字段和AES加密实战
东方财富股票数据JS逆向:secids字段和AES加密实战
59 0
|
1月前
|
数据采集 JavaScript 前端开发
同花顺股票数据逆向:Cookie加密和Hook注入
同花顺股票数据逆向:Cookie加密和Hook注入
74 0
|
2月前
|
安全 网络协议 网络安全
SSL(Secure Sockets Layer)是一种安全协议,用于在客户端和服务器之间建立加密的通信通道。
SSL(Secure Sockets Layer)是一种安全协议,用于在客户端和服务器之间建立加密的通信通道。
|
2月前
|
算法 安全 数据安全/隐私保护
支付系统---微信支付09------数字签名,现在Bob想要给Pink写一封信,信件的内容不需要加密,怎样能够保证信息的完整性,使用信息完整性的主要手段是摘要算法,散列函数,哈希函数,H称为数据指纹
支付系统---微信支付09------数字签名,现在Bob想要给Pink写一封信,信件的内容不需要加密,怎样能够保证信息的完整性,使用信息完整性的主要手段是摘要算法,散列函数,哈希函数,H称为数据指纹