首页 首页 大数据 大数据入门 查看内容

通过客户端加密保护数据

木马童年 2019-3-2 17:45 109 0

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

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

本文介绍如何基于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来实现客户端加密,于加密密匙类型及加密算法,用户可以根据自己的需要进行选择。

架构图

准备工作

  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

云栖社区站内文章,如需转载,请保留作者和出处(云栖社区),并邮件通知云栖社区(yqeditor@list.alibaba-inc.com)。

在不久的将来,多智时代一定会彻底走入我们的生活,有兴趣入行未来前沿产业的朋友,可以收藏多智时代,及时获取人工智能、大数据、云计算和物联网的前沿资讯和基础知识,让我们一起携手,引领人工智能的未来!

数据安全 原始数据
0
为您推荐
数据科学,数据分析和机器学习之间,有什么本质区别?

数据科学,数据分析和机器学习之间,有什么本质区别?

我们都知道机器学习,数据科学和数据分析是未来的发展方向。有些公司不仅利用大数据帮…...

什么样的人才是大数据人才呢?我们应该怎么定义和分类?

什么样的人才是大数据人才呢?我们应该怎么定义和分类

在未来世界,国家之间、区域之间甚至是公司之间的大数据人才的争夺战,将是愈演愈烈的…...

大数据现在处于什么阶段,入行大数据,需要学习哪些基础知识?

大数据现在处于什么阶段,入行大数据,需要学习哪些基

大数据的发展历程总体上可以划分为三个重要阶段,萌芽期、成熟期和大规模应用期…...

大数据技术怎么学习,在学习大数据之前,需要具备什么基础?

大数据技术怎么学习,在学习大数据之前,需要具备什么

  大数据又称黑暗数据,是指人脑无法处理的海量数据聚合成的信息资产,在民生、IT、…...

对于大数据开发的学习,最经典的学习路线是什么?

对于大数据开发的学习,最经典的学习路线是什么?

对于现代社会,大数据开发的重要性不言而喻,通过大量的数据处理、分析获取有价值的信…...

大数据时代,主要需要什么类型的人才?

大数据时代,主要需要什么类型的人才?

什么是大数据,大数据是主要指的是,无法在可承受的时间范围内用常规软件工具进行捕捉…...