HiveNetWebUtils.utils.cryptography 源代码

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# Copyright 2019 黎慧剑
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

"""
通用的加解密处理公共模块

@module cryptography
@file cryptography.py
"""

import os
import sys
import hashlib
import hmac
import base64
if sys.platform != 'win32':
    from Crypto import Random
    from Crypto.PublicKey import RSA
    from Crypto.Cipher import PKCS1_v1_5
else:
    from Cryptodome import Random
    from Cryptodome.PublicKey import RSA
    from Cryptodome.Cipher import PKCS1_v1_5  # 注: JS加密的内容 PKCS1_OAEP 没有办法解密
from HiveNetCore.utils.string_tool import StringTool
# 根据当前文件路径将包路径纳入, 在非安装的情况下可以引用到
sys.path.append(os.path.abspath(os.path.join(
    os.path.dirname(__file__), os.path.pardir, os.path.pardir)))


__MOUDLE__ = 'cryptography'  # 模块名
__DESCRIPT__ = u'通用的加解密处理公共模块'  # 模块描述
__VERSION__ = '0.1.0'  # 版本
__AUTHOR__ = u'黎慧剑'  # 作者
__PUBLISH__ = '2020.12.08'  # 发布日期


[文档]class HCrypto(object): """ 通用加解密公共模块 """ ############################# # 随机数产生函数 #############################
[文档] @classmethod def generate_salt(cls, str_len=8, chars="AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"): """ 随机生成盐字符串 @param {int} str_len=8 - 盐长度 @param {string} chars="AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz" - 生成盐包含的字符集合 @returns {str} - 生成的盐字符串 """ return StringTool.get_random_str( random_length=str_len, chars=chars )
[文档] @classmethod def generate_nonce(cls, length: int = 8, chars="AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789") -> str: """ 生成nonce随机字符串 @param {int} length=8 - 要生成的字符串长度 @param {string} chars="AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789" - 随机抽取的字符串内容 @returns {str} - 返回随机字符串 """ return StringTool.get_random_str(random_length=length, chars=chars)
############################# # Hash散列算法 #############################
[文档] @classmethod def md5(cls, value, encoding='utf-8', **kwargs) -> str: """ Md5加密算法 @param {str|bytes} value - 要加密的字符串或bytes数组 @param {str} encoding='utf-8' - 对value字符串的转换编码 @returns {str} - 返回加密后的字符串 """ _value = value if type(value) == str: _value = value.encode(encoding=encoding) return hashlib.md5(_value).hexdigest().upper()
[文档] @classmethod def sha1(cls, value: str, encoding='utf-8', **kwargs) -> str: """ SHA1加密算法 @param {str|bytes} value - 要加密的字符串或bytes数组 @param {str} encoding='utf-8' - 对value字符串的转换编码 @returns {str} - 返回加密后的字符串 """ _value = value if type(value) == str: _value = value.encode(encoding=encoding) return hashlib.sha1(_value).hexdigest().upper()
[文档] @classmethod def sha256(cls, value: str, encoding='utf-8', **kwargs) -> str: """ SHA256加密算法 @param {str|bytes} value - 要加密的字符串或bytes数组 @param {str} encoding='utf-8' - 对value字符串的转换编码 @returns {str} - 返回加密后的字符串 """ _value = value if type(value) == str: _value = value.encode(encoding=encoding) return hashlib.sha256(_value).hexdigest().upper()
[文档] @classmethod def sha512(cls, value: str, encoding='utf-8', **kwargs) -> str: """ SHA512加密算法 @param {str|bytes} value - 要加密的字符串或bytes数组 @param {str} encoding='utf-8' - 对value字符串的转换编码 @returns {str} - 返回加密后的字符串 """ _value = value if type(value) == str: _value = value.encode(encoding=encoding) return hashlib.sha512(_value).hexdigest().upper()
############################# # 不可逆加密算法 #############################
[文档] @classmethod def hmac_sha256(cls, value: str, key: str, encoding='utf-8') -> str: """ HMAC-SHA256加密算法 @param {str} value - 要加密的字符串内容 @param {str} key - 加密密钥 @param {str} encoding='utf-8' - 对value字符串的转换编码 @returns {str} - 返回加密后的字符串 """ _hash_obj = hmac.new( key.encode(), value.encode(encoding=encoding), digestmod=hashlib.sha256 ) return _hash_obj.hexdigest().upper()
############################# # RSA 加密 #############################
[文档] @classmethod def rsa_generate_key_pair(cls, bits: int = 1024, e: int = 65537, format: str = 'PEM', pkcs: int = 1, passphrase: str = None) -> tuple: """ 生成RSA密钥对 @param {int} bits=enum[*1024,2048,3072] - 密钥长度 @param {int} e=65537 - 公钥指数, 最小为65537, 不建议修改 @param {str} format=enum[*'PEM','DER','OpenSSH'] - 输出的密钥格式 PEM - 文本编码格式, 满足标准 `RFC1421`/`RFC1423` DER - 二进制格式 OpenSSH - 文本编码格式, 满足 OpenSSH 标准 @param {int} pkcs=enum[*1,8] - 私钥的结构标准 1 - 私钥编码为简单的 PKCS#1 结构(RSAPrivateKey) 2 - 私钥编码为 PKCS#8 结构(PrivateKeyInfo) @param {str} passphrase=None - 证书开启密码, 用于保护证书的输出内容 @returns {(bytes, bytes)} - 返回 (私钥字节数组, 公钥字节数组) """ _random_generator = Random.new().read _rsa = RSA.generate(bits, _random_generator, e=e) # 生成私钥 _private_key = _rsa.exportKey(format=format, pkcs=pkcs, passphrase=passphrase) # 生成公钥 _public_key = _rsa.publickey().exportKey(format=format, pkcs=pkcs) return (_private_key, _public_key)
[文档] @classmethod def rsa_get_key(cls, extern_key, passphrase=None): """ RSA获取密钥对象(公钥或私钥) @param {str|bytes} extern_key - 输入的密钥内容, 可以为字符串或bytes对象 @param {str} passphrase=None - 密钥的开启密码 @returns {Cryptodome.PublicKey.RSA.RsaKey} - 返回可以用于加解密的密钥对象 """ return RSA.import_key(extern_key, passphrase=passphrase)
[文档] @classmethod def rsa_encrypt(cls, rsa_key, data, encoding: str = 'utf-8', output_str: bool = True): """ RSA加密数据 注意: RSA支持加密数据长度跟密钥长度有关,因此不建议使用RSA加密大数据 @param {Cryptodome.PublicKey.RSA.RsaKey} rsa_key - 通过 rsa_get_key 获取到的 RsaKey 对象 @param {str|bytes} data - 要加密的数据, 支持字符串或字节数据两种类型 @param {str} encoding='utf-8' - 对字符串的转换编码 @param {bool} output_str=True - 输出结果是否转换为字符串格式 @returns {str|bytes} - 如果output_str为True, 则通过 base64.b64encode 转换为可打印字符输出, 否则返回二进制字节数组 """ _cipher_rsa = PKCS1_v1_5.new(rsa_key) # 进行数据转换 _data = data if type(data) == str: _data = bytes(data, encoding=encoding) # 进行加密处理 _encrypt_data = _cipher_rsa.encrypt(_data) # 将加密结果转换为 base64 编码字符串 if output_str: return base64.b64encode(_encrypt_data).decode(encoding='ascii') else: return _encrypt_data
[文档] @classmethod def rsa_decrypt(cls, rsa_key, encrypt_data, output_str: bool = True, encoding: str = 'utf-8'): """ 解密数据 @param {Cryptodome.PublicKey.RSA.RsaKey} rsa_key - 通过 rsa_get_key 获取到的 RsaKey 对象 @param {str|bytes} encrypt_data - 要解密的数据, 支持 base64 字符串或字节数据两种类型 @param {bool} output_str=True - 输出结果是否转换为真实字符串 (加密数据为字符串) @param {str} encoding='utf-8' - 数据结果转换为字符串的编码 @returns {bytes|str} - 解密后的结果, 如果 output_str 为 True 则为字符串, 否则为二进制字节数组 """ _cipher_rsa = PKCS1_v1_5.new(rsa_key) # 进行数据处理 _encrypt_data = encrypt_data if type(encrypt_data) == str: _encrypt_data = base64.b64decode(bytes(_encrypt_data, encoding='ascii')) # 解密 _bytes_data = _cipher_rsa.decrypt(_encrypt_data, None) # 看是否转换为字符串 if output_str: return _bytes_data.decode(encoding=encoding) else: return _bytes_data
if __name__ == '__main__': # 当程序自己独立运行时执行的操作 # 打印版本信息 print(('模块名: %s - %s\n' '作者: %s\n' '发布日期: %s\n' '版本: %s' % (__MOUDLE__, __DESCRIPT__, __AUTHOR__, __PUBLISH__, __VERSION__)))