.. Python-SecureHTTP documentation master file, created by
sphinx-quickstart on Fri Jan 4 14:49:36 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
=================
Python-SecureHTTP
=================
.. toctree::
:maxdepth: 1
.. currentmodule:: SecureHTTP
通过使用RSA+AES让HTTP传输更加安全,即C/S架构的加密通信! (Make HTTP transmissions more secure via RSA+AES, encrypted communication for C/S architecture.)
|PyPI| |Pyversions| |implementation|
------------------
安装(Installation)
------------------
*使用pip安装*:
.. code:: bash
# 正式版(Release)
$ pip install -U SecureHTTP
# 开发版(Dev)
$ pip install -U git+https://github.com/staugur/Python-SecureHTTP.git@master
*关于依赖库*:
SecureHTTP依赖pycryptodomex。
PyCryptodome是PyCrypto的一个分支,它为PyCrypto的最后一个正式版本(2.6.1)带来了一些增强功能,如支持pypy。
PyCryptodomex即PyCryptodome,区别在于导入包名不同,前者导入包名是Cryptodome,后者是Crypto(同pycrypto)。
**注意:v0.5.0开始,已经弃用PyCrypto/PyCryptodome!**
---------------
测试用例(Test)
---------------
*温馨提示:完整的测试要求安装php、go以便运行多语言测试*
.. code:: bash
$ git clone https://github.com/staugur/Python-SecureHTTP && cd Python-SecureHTTP
$ make dev && make test
---------------
简单示例(Demo)
---------------
1. AES加密、解密
.. code:: python
from SecureHTTP import AESEncrypt, AESDecrypt
# 加密后的密文
ciphertext = AESEncrypt('ThisIsASecretKey', 'Hello World!', output="hex")
# 解密后的明文
plaintext = AESDecrypt("ThisIsASecretKey", ciphertext, input="hex)
2. RSA加密、解密
.. code:: python
from SecureHTTP import RSAEncrypt, RSADecrypt, generate_rsa_keys
# 生成密钥对
(pubkey, privkey) = generate_rsa_keys(incall=True)
# 加密后的密文
ciphertext = RSAEncrypt(pubkey, 'Hello World!')
# 解密后的明文
plaintext = RSADecrypt(privkey, ciphertext)
3. C/S加解密示例: `点此查看以下模拟代码的真实WEB环境示例 `__
.. code:: python
# 模拟C/S请求
from SecureHTTP import EncryptedCommunicationClient, EncryptedCommunicationServer, generate_rsa_keys
post = {u'a': 1, u'c': 3, u'b': 2, u'data': ["a", 1, None]}
resp = {u'msg': None, u'code': 0}
# 生成密钥对
(pubkey, privkey) = generate_rsa_keys(incall=True)
# 初始化客户端类
client = EncryptedCommunicationClient(pubkey)
# 初始化服务端类
server = EncryptedCommunicationServer(privkey)
# NO.1 客户端加密数据
c1 = client.clientEncrypt(post)
# NO.2 服务端解密数据
s1 = server.serverDecrypt(c1)
# NO.3 服务端返回加密数据
s2 = server.serverEncrypt(resp)
# NO.4 客户端获取返回数据并解密
c2 = client.clientDecrypt(s2)
# 以上四个步骤即完成一次请求/响应
4. B/S加解密示例: `前端使用AES+RSA加密,后端解密 `__
--------------------------------------------------
加密传输通信的流程(Encrypted Transmission Process)
--------------------------------------------------
总体流程:客户端上传数据加密 ==> 服务端获取数据解密 ==> 服务端返回数据加密 ==> 客户端获取数据解密
NO.1 客户端上传数据加密流程::
1. 客户端随机产生一个16位的字符串,用以之后AES加密的秘钥,AESKey。
2. 使用RSA对AESKey进行公钥加密,RSAKey。
3. 参数加签,参考"加签、验签规则流程"。
4. 将明文的要上传的数据包(字典/Map)转为Json字符串,使用AESKey加密,得到JsonAESEncryptedData。
5. 封装为{key : RSAKey, value : JsonAESEncryptedData}的字典上传服务器,服务器只需要通过key和value,然后解析,获取数据即可。
NO.2 服务端获取数据解密流程::
1. 获取到RSAKey后用服务器私钥解密,获取到AESKey
2. 获取到JsonAESEncriptedData,使用AESKey解密,得到明文的客户端上传上来的数据。
3. 验签,参考"加签、验签规则流程"
4. 返回明文数据
NO.3 服务端返回数据加密流程::
1. 将要返回给客户端的数据(字典/Map)进行加签并将签名附属到数据中
2. 上一步得到的数据转成Json字符串,用AESKey加密处理,记为AESEncryptedResponseData
3. 封装数据{data : AESEncryptedResponseData}的形式返回给客户端
NO.4 客户端获取数据解密流程::
1. 客户端获取到数据后通过key为data得到服务器返回的已经加密的数据AESEncryptedResponseData
2. 对AESEncryptedResponseData使用AESKey进行解密,得到明文服务器返回的数据。
----------------------------------
加签、验签规则流程(Signature Rule)
----------------------------------
@加签、验签规则:
加签,即 ``EncryptedCommunicationClient.clientEncrypt`` 和 ``EncryptedCommunicationServer.serverEncrypt`` 方法,签名已经内置,支持传入 ``signIndex`` 参数生成不同签名。
验签,即 ``EncryptedCommunicationClient.clientDecrypt`` 和 ``EncryptedCommunicationServer.serverDecrypt`` 方法,验签已经内置,验签失败触发 ``SignError`` 错误。
signIndex::
False, 不签名、不验签
None, 签名数据中所有字段(目前版本,如果嵌套了无序数据类型,可能会验签失败)
str, 指定参与签名的字段,格式是"key1,key2",这是目前建议的一种方法,只针对部分核心字段签名和验签
@签名步骤:
1. 构造规范化的请求字符串
按照字母升序,对参数名称进行排序。
2. 排序后的参数以"参数名=值&"的形式连接,其中参数名和值要进行URL编码,使用UTF-8字符集,编码规则是::
2.1 对于字符 A-Z、a-z、0-9以及字符“-”、“_”、“.”、“~”不编码;
2.2 对于其他字符编码成“%XY”的格式,其中XY是字符对应ASCII码的16进制表示。比如英文的双引号(”)对应的编码就是%22.
2.3 英文空格( )编码为%20,而不是加号(+)。
3. 对以上规范化的字符串使用摘要算法得到签名
@验签步骤:
验签同签名类似。
@注意事项:
签名规则可以参考阿里云API签名
-----------------
CLI Documentation
-----------------
命令行工具用于辅助性功能,目前主要是用于生成RSA密钥对,有两种方法。
1. generate_rsa_keys.py
-----------------------
这是Python自身生成的RSA密钥对,它支持输出到控制台或写入文件、设置私钥密码等,请查看命令帮助::
# generate_rsa_keys.py -h
usage: generate_rsa_keys.py [-h] [-v] [-l {1024,2048,3072,4096}]
[-p PASSPHRASE] [-w]
optional arguments:
-h, --help show this help message and exit
-v, --version Print the SecureHTTP Version
-l {1024,2048,3072,4096}, --length {1024,2048,3072,4096}
Key length, default is 2048.
-p PASSPHRASE, --passphrase PASSPHRASE
The pass phrase used for protecting the private key.
-w, --write Write a key pair file in PEM format
2. generate_rsa_keys.sh
-----------------------
这是使用系统OpenSSL生成的RSA密钥对,此命令可以传递一个位置:密钥长度(默认1024),在当前目录保存4个文件,分别是pkcs1格式密钥对和pkcs8密钥对,比如::
generate_rsa_keys.sh 2048
SecureHTTP.js
-------------
请参考: `SecureHTTP.js `_
-----------------
API Documentation
-----------------
PS:
接口中函数返回值,正常情况下,Python2.7返回unicode,Python3.x返回str。
函数参数要求字符串的,一般建议py2中使用unicode,py3中使用bytes,请注意编码问题。
另,RSADecrypt解密中,新增一个sentinel参数,一个挺重要的解密失败的标记,关于此参数的建议,请参考:`Pycryptodomex接口文档 `_,注意文档中 ``Warning`` 部分。
.. automodule:: SecureHTTP
:members: RSAEncrypt, RSADecrypt, AESEncrypt, AESDecrypt, EncryptedCommunicationClient, EncryptedCommunicationServer, generate_rsa_keys, SignError, AESError, RSAError
:undoc-members:
:show-inheritance:
:noindex:
-------------------
更新日志(CHANGELOG)
-------------------
.. include:: ../CHANGELOG.rst
.. |PyPI| image:: https://img.shields.io/pypi/v/SecureHTTP.svg?style=popout
:target: https://pypi.org/project/SecureHTTP
.. |Pyversions| image:: https://img.shields.io/pypi/pyversions/SecureHTTP.svg
:target: https://pypi.org/project/SecureHTTP
.. |implementation| image:: https://img.shields.io/pypi/implementation/SecureHTTP.svg
:target: https://pypi.org/project/SecureHTTP