【python】cryptography库学习
【python】cryptography库学习
- cryptography学习
- 1-安装
- 2-cryptography学习
- 2.1-fernet的使用
- 2.2-padding填充
- 2.3-Hash
- 2.4-ciphers(对称算法AES为例)
- 2.5-asymmetric(非对称算法RSA为例)
- 函数:generate_private_key
- 类:RSAPrivateKey(私钥类)
- 类:RSAPublicKey(公钥类)
- rsa.py的其他内容
- 非对称算法下的padding.py的使用
- 示例
学习cryptography的基本使用,后续有需要再做详细补充
cryptography学习
1-安装
pip install cryptography
2-cryptography学习
查看cryptography的目录结构
cryptography/hazmat/ # 主要目录,对称加解密的库文件都在此目录下backends/ # 此目录暂不做研究,此目录跟openssl关联较大bindings/ # 此目录暂不做研究,此目录跟openssl有关primitives/ # 本文主要学习此目录下的内容,包含对数据的填充,对称加解密,以及非对称加解密,公钥和私钥的签名验签asymmetric/ 非对称密码相关内容,有需要可对文件内容详细了解【常用rsa.py】ciphers/ 对称加密算法内容,本文主要讲述的内容-- aead.py:aesd算法内容,含ChaCha20Poly1305、AESCCM、AESGCM、AESOCB3。-- algorithms.py:对称算法的主要内容,含AES、Camellia、TripleDES、ChaCha20、SM4等等-- base.py:实际使用中基本用不到-- modes.py:加密模式kdf/ # 加密密钥派生和密钥存储相关,有需要自行了解serialization/ 序列化相关,有需要自行了解twofactor/ 该模块包含与双因素认证相关的算法。目前,它包含了一种基于基于哈希的消息身份验证码(HMAC)来生成和验证一次性密码值的算法。有需要自行了解-- cmac.py:cmac相关-- constant_time.py-- hashes.py:加密哈希函数接-- hmac.py:hmac算法-- keywrap.py:没有用过-- padding.py:填充-- poly1305.py:poly1305算法-- ....其他文件x509/ # x509证书相关内容-- fernet.py:对称算法的实现,使用cryptography最基础的使用,
2.1-fernet的使用
cryptography最基本的使用
-
Fernet方法的简单介绍
classmethod generate_key():类方法,用于生成base64-encoded 32-byte key.encrypt(data):实例方法,加密数据 encrypt_at_time(data, current_time):使用显式传递的当前时间加密传递的数据decrypt(token, ttl=None):实例方法,解密数据 decrypt_at_time(token, ttl, current_time):使用显式传递的当前时间来解密令牌extract_timestamp(token):返回该令牌的时间戳。然后,调用者可以决定令牌是否即将到期,例如,发出一个新的令牌MultiFernet(fernets):MultiFernet类,这个类为Fernet实现了密钥流转。它接受一个Fernet实例列表,并实现相同的API
-
Fernet的使用示例
示例来源于库文档介绍中的内容
Cryptography Documentation Release 43.0.0.dev1
>>> from cryptography.fernet import Fernet >>> key = Fernet.generate_key() >>> f = Fernet(key) >>> token = f.encrypt(b"my deep dark secret") >>> token b'...' # 每一次的结果都是不同的 >>> f.decrypt(token) b'my deep dark secret'
2.2-padding填充
padding.py
提供PKCS7和ANSIX923填充方式
PKCS7
:填充到指定长度,填充内容为填充的长度
ANSIX923
:填充最后一个字节为长度,其余的为0
这里以PKCS7为例:
import binascii
from cryptography.hazmat.primitives import paddingclass MyPadding:def __init__(self, block_size: int):self.block_size = block_sizedef padding(self, padding_data):b_padding_data = padding_data.encode('utf8')padder = padding.PKCS7(block_size=self.block_size).padder()result = padder.update(b_padding_data) + padder.finalize()return resultdef unpadding(self, unpadding_data):unpadder = padding.PKCS7(block_size=self.block_size).unpadder()result = unpadder.update(unpadding_data) + unpadder.finalize()return resultif __name__ == '__main__':my_padding = MyPadding(128)data = "123456789"p = my_padding.padding(data)print(p)print(type(p))print(binascii.b2a_hex(p))d = my_padding.unpadding(p)print(d)'''b'123456789\x07\x07\x07\x07\x07\x07\x07'<class 'bytes'>b'31323334353637383907070707070707'b'123456789''''
ANSIX923:
>>> padder = padding.ANSIX923(128).padder()
>>> padded_data = padder.update(b"11111111111111112222222222")
>>> padded_data += padder.finalize()
>>> padded_data
b'11111111111111112222222222\x00\x00\x00\x00\x00\x06'
>>> unpadder = padding.ANSIX923(128).unpadder()
>>> data = unpadder.update(padded_data)
>>> data += unpadder.finalize()
>>> data
b'11111111111111112222222222'
2.3-Hash
这里简单的展示cryptography库hash的使用。
>>> from cryptography.hazmat.primitives import hashes
>>> digest = hashes.Hash(hashes.SHA256())
>>> digest.update(b"abc")
>>> digest.update(b"123")
>>> digest.finalize()
b'l\xa1=R\xcap\xc8\x83\xe0\xf0\xbb\x10\x1eBZ\x89\xe8bM\xe5\x1d\xb2\xd29%\x93\xafj\
x84\x11\x80\x90'
如果不想使用cryptography的hash,可以使用python自带的hashlib库完成
import hashlib__hash__ = [ 'md5','sha1','sha224','sha256','sha384','sha512','blake2b','blake2s','ripemd160','whirlpool','sha3_224','sha3_256','sha3_384','sha3_512','sm3',]class MyHash:def __init__(self, hash_name: str):self.hash_name = hash_name.lower()def hash(self, hash_data: str):if self.hash_name not in __hash__:raise "unsupported hash, confirm the input hash name"hash_object = hashlib.new(self.hash_name)hash_object.update(hash_data.encode('utf-8'))return hash_object.hexdigest()if __name__ == '__main__':data = 'abc123'my_hash = MyHash('SHA256')print(my_hash.hash(data))
2.4-ciphers(对称算法AES为例)
AES等算法和CBC模式结合。使用AES加密内容,然后解密内容的一个简单例子:
>>> import os
>>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
>>> key = os.urandom(32)
>>> iv = os.urandom(16)
>>> cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
>>> encryptor = cipher.encryptor()
>>> ct = encryptor.update(b"a secret message") + encryptor.finalize()
>>> decryptor = cipher.decryptor()
>>> decryptor.update(ct) + decryptor.finalize()
b'a secret message'
封装使用:
如需要使用其他算法,只需要根据下方封装的,简单修改即可,大部分只需要修改加解密中使用的算法名称即可
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
需要IV的加密模式:CBC、OFB、CFB、CFB8加密算法:["AES","Camellia","TripleDES","Blowfish","CAST5","ARC4","IDEA","SEED","ChaCha20","SM4"]
"""
import binascii
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import my_paddingMODES_NAME = ["CBC", "ECB", "OFB", "CFB"]def gen_key(key_len):return os.urandom(key_len)def _model_object(alg_modes, alg_iv):if alg_modes.upper() not in MODES_NAME:raise "unsupported modes, confirm the input hash name"modes_dict = {"CBC": modes.CBC(alg_iv),"ECB": modes.ECB(),"OFB": modes.OFB(alg_iv),"CFB": modes.CFB(alg_iv)}return modes_dict.get(alg_modes.upper())def hex2string(hex_string):bytes_string = binascii.a2b_hex(hex_string)return bytes_string.decode('utf8')class MyAES:name = 'AES'block_size = 128key_sizes = frozenset([128, 192, 256, 512])def __init__(self,alg_key: bytes = None,alg_modes: str = 'CBC',alg_iv: bytes = b'1234567812345678'):# 默认key_size,为32if alg_key is None:self.__alg_key = gen_key(32)else:self.__alg_key = alg_keyself.__alg_iv = alg_ivself.__alg_modes = _model_object(alg_modes, alg_iv)def get_key(self):return binascii.b2a_hex(self.__alg_key)def set_key(self, alg_key: bytes):# 对alg_key进行判断if not isinstance(alg_key, bytes):raise TypeError("Type error: {0} is not an instance of bytes".format(type(alg_key)))self.__alg_key = alg_keydef get_iv(self):return binascii.b2a_hex(self.__alg_iv)def set_iv(self, iv: bytes):if not isinstance(iv, bytes):raise TypeError("Type error: {0} is not an instance of bytes".format(type(iv)))self.__alg_iv = ivdef encrypt(self, plain_data: str):"""输入字符串,完成加密操作:param plain_data: 明文字符串:return: 16进制密文字符串"""# 完成数据填充,转为bytes后的填充数据data_padding = my_padding.MyPadding(MyAES.block_size).padding(plain_data)# aes对象my_alg = Cipher(algorithms.AES(self.__alg_key), self.__alg_modes)encryptor = my_alg.encryptor()# 加密操作完成result = encryptor.update(data_padding) + encryptor.finalize()# 转为大写的16进制字符串输出return binascii.b2a_hex(result).upper().decode()def decrypt(self, cipher_data: str):"""输入16进制密文数据,返回原文:param cipher_data: 16进制密文数据字符串:return:"""cipher_data_bytes = binascii.a2b_hex(cipher_data)my_alg = Cipher(algorithms.AES(self.__alg_key), self.__alg_modes)decrypt = my_alg.decryptor()# 解密操作完成result = decrypt.update(cipher_data_bytes) + decrypt.finalize()data_unpadding = my_padding.MyPadding(MyAES.block_size).unpadding(result)# 转为大写的16进制字符串输出return binascii.b2a_hex(data_unpadding).upper().decode()if __name__ == '__main__':aes = MyAES()data = 'hello world'cipher = aes.encrypt(data)plain = aes.decrypt(cipher)print('cipher:', cipher)print('plain:', hex2string(plain))print('key:', aes.get_key())print('iv:', aes.get_iv())print('alg_name:', aes.name)'''cipher: 6EAE64A7B78A5C0985A1CADA8FAAB7D0plain: hello worldkey: b'4f56291a9aaa86fbd341ac5ca0bb10fa5d583d281b55f853172e83197effa0c2'iv: b'31323334353637383132333435363738'alg_name: AES'''
2.5-asymmetric(非对称算法RSA为例)
asymmetric
对应的位置在//cryptography/hazmat/primitives/asymmetric
路径下,cryptography
库支持多种非对称算法,包括:ed25519、RSA、dh、dsa、ed448等。这个以最常见的RSA算法为例。
按照官方文档中的介绍,主要内容为:
Generation
:生成一个RSA私钥key loading
:加载PEM格式的密钥Key serialization
:密钥序列化,可以获取一个base64格式的密钥Signing
:用私钥对消息进行签名,公钥可以对结果进行验签Verification
:对应公钥对消息的验签Encryption
:使用公钥对数据进行加密,这样只有拥有私钥的才可已经进行解密Decryption
:私钥解密公钥加密的信息Padding
:RSA签名需要一个特定的散列函数,并且需要使用填充,加密的时候也会涉及到对消息的填充Numbers
:包含RSA密钥的组成,可以获取到对应公钥和私钥的组成,一般不建议使用。Handling partial RSA private keys
:用不到,一般都是专业的密码使用者才有可能用到Key interfaces
:密钥对应的主要接口
查看
asymmetric
目录下的rsa.py
文件,根据源码中的内容,学习上述的主要内容
函数:generate_private_key
def generate_private_key(public_exponent: int,key_size: int,backend: typing.Any = None,
)-> RSAPrivateKey:pass'''
public_exponent:指数,这个根据密码学的知识,这个默认都是传65537
key_sizeParameters
• public_exponent (int) – 指数,这个根据密码学的知识,这个默认都是传65537
• key_size (int) – 指的是私钥长度(位),如1024bit,2048bit,4096bit
• backend - 默认即可
Returns
返回 RSAPrivateKey 类 ,这个类也是在`rsa.py`文件中定义好的
'''
类:RSAPrivateKey(私钥类)
class RSAPrivateKey(metaclass=abc.ABCMeta):@abc.abstractmethoddef decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes:"""解密提供的密文。可以看到传参除了密文外,还需要填充算法,对应的填充算法可以查看`asymmetric`下的padding.py"""@property@abc.abstractmethoddef key_size(self) -> int:"""密钥的长度,也就说通过generate_private_key函数传入的key_size"""@abc.abstractmethoddef public_key(self) -> RSAPublicKey:"""与此私钥关联的RSAPublicKey(也是一个类,公钥类)。"""@abc.abstractmethoddef sign(self,data: bytes,padding: AsymmetricPadding,algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm],) -> bytes:"""对消息进行签名.涉及填充算法,以及hash算法"""@abc.abstractmethoddef private_numbers(self) -> RSAPrivateNumbers:"""返回RSAPrivateNumbers类,一般很少用到,不做具体研究"""@abc.abstractmethoddef private_bytes(self,encoding: _serialization.Encoding,format: _serialization.PrivateFormat,encryption_algorithm: _serialization.KeySerializationEncryption,) -> bytes:"""返回私钥的序列化"""
类:RSAPublicKey(公钥类)
class RSAPublicKey(metaclass=abc.ABCMeta):@abc.abstractmethoddef encrypt(self, plaintext: bytes, padding: AsymmetricPadding) -> bytes:"""加密给定的明文"""@property@abc.abstractmethoddef key_size(self) -> int:"""公共模的比特长度。"""@abc.abstractmethoddef public_numbers(self) -> RSAPublicNumbers:"""返回 RSAPublicNumbers 类"""@abc.abstractmethoddef public_bytes(self,encoding: _serialization.Encoding,format: _serialization.PublicFormat,) -> bytes:"""返回公钥的序列化"""@abc.abstractmethoddef verify(self,signature: bytes,data: bytes,padding: AsymmetricPadding,algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm],) -> None:"""对消息进行验签"""@abc.abstractmethoddef recover_data_from_signature(self,signature: bytes,padding: AsymmetricPadding,algorithm: typing.Optional[hashes.HashAlgorithm],) -> bytes:"""从签名中恢复原始数据。"""@abc.abstractmethoddef __eq__(self, other: object) -> bool:"""Checks equality."""
rsa.py的其他内容
class RSAPrivateNumbers
:RSAPrivateNumbers
类,前面内容中提到的,获取私钥的组成的内容,比如p,q,d等等。如果是外部知道这些私钥组成值,也可以用类方法private_key
,返回RSAPrivateKey
类class RSAPublicNumbers
:RSAPublicNumbers
类,前面内容中提到的,获取公钥的组成的内容。比如e,n,如果是外部知道这些公钥组成值,也可以用类方法public_key
,返回RSAPublicKey
类- 等等(其他是配套对函数,有兴趣自行了解)
非对称算法下的padding.py的使用
对应文件的位置:跟rsa.py文件位于同一级目录下,这个padding文件是专门用于非对称算法中的填充,只提供了3种填充方式:
PKCS1v15
:一个简单的填充方案,可用于签名和加密。不建议PKCS1v15
用于新应用,官方建议说是加密首选OAEP
,签名首选PSS
PSS
:RSA
签名推荐的填充算法。不能与RSA
加密一起使用OAEP
:RSA
加密的填充算法。它不能与RSA
签名一起使用
# 示例
类PKCS1v15:无需任何参数,是最简单的填充方式,每次的结果都是一样类OAEP:需要3个参数参数:• mgf – 掩码生成函数对象. 只支持 MGF1.• algorithm – 哈希算法的一个实例• label (bytes) – 要设置的应用标签(没了解),默认None即可.类PSS:需要2个参数参数:• mgf – 掩码生成函数对象. 只支持 MGF1.• salt_length (int) – 盐的长度。建议将其设置为PSS.DIGEST_LENGTH或PSS.MAX_LENGTH.
示例
结合上述的内容,rsa主要内容可以分为以下四部分
- 生成密钥对->对应私钥类->私钥类中有对应获取公钥类的方法
- 公钥和私钥对应的方法:常见的就是加密,解密,签名,验签
- 公钥和私钥的序列化
- 公钥和私钥组成部分的获取,或根据对应的值生成对应的公钥类私钥类
其他:serialization目录用于序列化私钥和公钥的内容,将公钥和私钥保存或加载,这里不做具体介绍,只给出示例,有需要可以去了解serialization下的内容
- 密钥生成,加密,解密,签名,验签,查看密钥对信息,序列化
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import serialization
import binascii# 以下示例均来自官方文档的的内容,加以整合
# 生成密钥对,generate_private_key返回的是RSAPrivateKey类
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)# 获取对应的公钥类RSAPublicKey
public_key = private_key.public_key()# 使用私钥完成一些操作,解密,签名
# 使用公钥完成一些操作,加密,验签
# 签名,填充方式可以改为pkcs1v15,padding.PKCS1v15,返回签名结果
sign_message = b"A message I want to sign"
signature = private_key.sign(sign_message,padding.PSS(mgf=padding.MGF1(hashes.SHA256()),salt_length=padding.PSS.MAX_LENGTH),hashes.SHA256())print("message:",binascii.b2a_hex(message))# 验证签名:有公钥、消息、签名值和所使用的签名算法,这个是没有返回值,验签失败会引发异常:InvalidSignature
try:public_key.verify(signature,sign_message,padding.PSS(mgf=padding.MGF1(hashes.SHA256()),salt_length=padding.PSS.MAX_LENGTH),hashes.SHA256())print("verify:True")
except Exception:print("verify:False")# 加密操作
encrypted_message = b"encrypted data"
ciphertext = public_key.encrypt(encrypted_message,padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),algorithm=hashes.SHA256(),label=None))print("encrypted_message:",encrypted_message)
print("ciphertext:",binascii.b2a_hex(ciphertext))# 解密操作
plaintext = private_key.decrypt(ciphertext,padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),algorithm=hashes.SHA256(),label=None))
print("plaintext:",plaintext)print("\n\nRSAPrivateNumbers和RSAPublicNumbers:")
print("\n--RSAPrivateNumbers")
private_numbers = private_key.private_numbers()
print("private_key_p:",private_numbers.p)
print("private_key_q:",private_numbers.q)
print("private_key_d:",private_numbers.d)print("\n--RSAPublicNumbers")
public_numbers = public_key.public_numbers()
print("public_numbers_e:",public_numbers.e)
print("public_numbers_n:",public_numbers.n)print("\n\n序列化:")
print("private_key(加密):")
pem1 = private_key.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.BestAvailableEncryption(b'mypassword'))
# 将mypassword改为具体的密码
print(pem1.splitlines())
print("\nprivate_key(不加密):")
pem2 = private_key.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.TraditionalOpenSSL,encryption_algorithm=serialization.NoEncryption())
print(pem2.splitlines())print("\npublic_key:")
pem3 = public_key.public_bytes(encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo)
print(pem3.splitlines())'''
serialization:涉及的功能还有load公钥和私钥,可加载pem,der等格式的数据,以及证书相关的数据,有需要可以去了解
'''
结果:
message: b'41206d65737361676520492077616e7420746f207369676e'
verify:True
encrypted_message: b'encrypted data'
ciphertext: b'2de0f1fe1b5d72b947b8dbf71d05c38dc68bd651726070e606b4a9458d7c0fa16dfb07172171ba859a3409218e0b7ecad7b17fe56fd35bb49e31f0841acde909975620e83a1877219d15238f6688347431c36feb7663b177a966493109fe231e99e670f25d3ffc110a5676446026760ab739adb18fec25880eac014b1f2954a3b73db5678434bf60863dd06004dc829d221d3379e3cc063a6b4b85bfc5be169cfc299635a4e49b78054c57e792122b6b9aed137f7aedf25bc597788e0dd504e7b1c1da9afb8b6f80fe302ae51695473df63062990689afb466c96971756afd83326ac45839a031060194a0eed3aa169712cf6a4269a3cc16a5b10f5c605806c3'
plaintext: b'encrypted data'RSAPrivateNumbers和RSAPublicNumbers:--RSAPrivateNumbers
private_key_p: 147707585390291063655757186262664106581403583389769944190047479079802050557725461099143359285822400756601173686331008082783603762936206021035899801451983264373148026750004290322897832812789405156566036002605846423080016655535724545169357406940078465489591648499524311055428140666709043701951435405479083981507
private_key_q: 129818834990747146076466076783245566173460449186750491874222727814890697974924830062686005653997995728519629633284989915391162771546276906687785728345643383550878857450814037005853925931576826949107171864400879318575256878287526216494946410211681273209849751153418151910847326891086641035970617228184947974907
private_key_d: 8810065303547375928762349845316578013736506843080962512785868984734235290147877769264533096278362621787580696227653983919152226155921915698934833065258407586046747526250001963974218056036596580241940226949193816099076733090875075170550805899822656343465349396304500236060334137387244149410275988416202842542643262376837913857243207448439181111570332656768871231679656608370503370807857876773764088762784617137105654224500539668074456531405130162650453503803762719548271686520860271816511040217898091202461965447102304587164219886390683471833950962879479877256508594964292975127590603085155442999424663885457883776781--RSAPublicNumbers
public_numbers_e: 65537
public_numbers_n: 19175226654663889483686962299907428291529655241439907017383929316612785301398873015319640846560893067121406664962032451400135480242458058156856037813351939755130872193811111511174598277655024080213743703416336724973770112469751247100806621044026350130573166065079473679741161647303238677556416507350559120976572285358670246819946035044400185934220271734966395030418149358791928954989911148327721467003737750718274576389626687388317759384228357042486488866743832265506806649718988419123733129099398851518371219540705498141408901068424765912060559147570293587318212074428767533901711200492332308159704597121102288044849序列化:
private_key(加密):
[b'-----BEGIN ENCRYPTED PRIVATE KEY-----',
b'MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQIgxxwKU52uh4HZra', b'9yMxDwICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEOmuIolT9bVH3sVl', b'FarjNV8EggTQizU+Wlfb7PPYR7Pw2/QZl3Br4q79fDrdwNTWBcF5gZg7/+2tkFCn', b'X61/kcYkt9r+znyzjRQ6q3DeW2kfGL6iKEpHnon8OZcg23ZadNw4ossUDGg0dQWD', b'xzXZ8ztM+saQW05gl622cBjcpmWH7rrD6EjOMKMSwEh1iowrnb/1vk/h5cbe72fv', b'JWAPyQMLlRZyFncXukXY2UQe5+8wJquNoSmr4bBdWy5BshUstZEj7+bquzhOn4nm', b'VL1E/u6fhx3F3nfq9HfZg5BCZo1g0otMlcNUo7ecKdqQ6Cx4P0CwoJEYd9Rr1v5O', b'KV5M0tcp7Nt1FdTX0gTJZXYa8rMor+uvjuLV8cd8e9ygxRbdAau/X0Jh6tbKS/fh', b'EI7BxHaaiZXR7wNx08A/Sbup09Bo8awebjr+gEZuiwW2lO5UvEaqXI6g3w7H2SmK', b'xB5zRa6vtZkoobUZfKLDkRYW8Q7wIm6/zfUQ/xB6V0rgVZgVZ5Yo4nQnq/teqkEC', b'MuhI++rC7liTrpydf3lr+OI67WpbHnzgodNSSNp579p1SbGYcDSQK2/FOMmEfINE', b'2+2AAcAU2pNbj/XGyE8EEl/5wv/IHCbGQXOiJhxZcFIL/cbJh9r3zM4UJQRek91k', b'fQ5UF+sJF9D7iH8+6wH3iWKRAhyRtbukHQ1J1b+qH9GwPfkJM6JTR221WfyoAi84', b'3B+BxZLRWu1rTmMu3erUt90Gua9oDfQ5awvMr7c4ng3i1lFw9uT8xPlxr9GPbA4v', b'pU5/E+VTRo6PghuDLZarTdIHH2VURW1gEzttJiVgODRyN0MEEEC80vWTW6L3gnZO', b'fYufxLySQvxULeAJL+VkRKqQQa8xC8CogLXFa+nM4qIcgU83gjfaYk6VEf/M3Fkh', b'gHinbWdRdXL4WPBLqWtGIZa5/Ybt+ElEbonPZBaasIySp0BBtKjhdQhEtf3nGh0i', b'/Mo7RnWPd5B8SPmFx9Sy0boLMle4OxsWog2lXpN0Nf3zJeSgh9AohDLm1vvxadT+', b'FVQZXN5Y2pOKbK+H621r3kDy9HqSotISa20HLGs58bSEY4YSLwzOUAcFqjBb70t4', b'oP+j0lYse8ZcAZ7sW9uubekYeA55vIKDZKuNuysnpm5QEF42Zhq1Cz0VSS/addPs', b'KbgDqSVqCALqwdWcy5K3PXa77IwZorXg1woVvL/iw7PZoJ26XB8dSPk7jD75Lza7', b'W542mxrg6TrHVZfcDEpGEchWj4Nh/80NGxSwHXEiTRow4sHxfCePyK2N61YjBykw', b'//QXjBhB3R4nDZUxvAkwkEU1mV89U9TOtF3L9pEFSeA2Z3Vlyo57++yGsPtPeIvI', b'uFg9fSL9EjOgjWNjgfa3Mn2UBWV+eOi9LTH5M6Xslhqu0/2QPF8Z2TQ9i1RjecaD', b'eaezPrgjOq9IL9NERjaT8t1ocnfZbPbNUDmAGWVC0bi16WSM/QqzagzOxVrhevoN', b'YjBKh0PF29C0d05R6nc9jW8HJAHj/CEkUtx+S4LcCYMiBwFJwHeCfYXzOYx2iLkW', b'8q7FVndB11mxg9VYDf7aXpgItNTEwTl8iJRXhLE1FDA6dO2g1t1gMmZwIvdGNXc4', b'Qta6kOyRqypsMsxmu/5U87XxgR99D5Fyljt1F3T/3ir3hIjk2xIOze8=',
b'-----END ENCRYPTED PRIVATE KEY-----']private_key(不加密):
[b'-----BEGIN RSA PRIVATE KEY-----',
b'MIIEpAIBAAKCAQEAl+WlWH3VkNfRFXjxpmNrTskYDEF/MFGufYy5gfZ8+p9O2Cwk', b'RC2s6jv8dtdxi+a+GUvnks54xdnKAeOAgdd9HHs9hK0DmeGymVFUUfglfgIm3xm5', b'A33i2m6Eg/5Uipq3fVPx4sqlME2uHJs4Vb/4wN+Tz/F2xllIsSzeHR3oKg8EYc0w', b'oW3EHqLpvBUy+V5OIjlkajXFLpCIFlYMAXGbDJ9jTNP4IU8sDUc1MDCB4MyNE9Qs', b'YTjujj8YFbNmTEM3RSMV/oCTtsEmVIjxENNMb94+8tmpzMku//oQALTwZ9aKJsoV', b'VERVmu42gxJtRIYWrIpkhf713GWYUUdBwiTDMQIDAQABAoIBAEXKBmkdD6XH8tG5', b'ytVW8nO1Yy4mXai2rsQShx0WQh/oWBJsXZFRpxPL0dhMbmgH8SmwPUqvQMAuq2io', b'vV9qwZn3abFuyKvIDgXxXxt2Nsupc3Cn4eCf0z3m702x6efw5ANaMVWxI6qI1klg', b'a8bCOCltz/0HhTnmxcZZxgd8uTGxFQ431w5iqnWJ26u57eSjoxLPdAQxqbBVbwOY', b'x2clL/5MK9VDroVn6k/dnQlKjJ1YhCOLq9AlAQ8kaudhB7xNGp19d9k5LJJKZCjX', b'SuGA1Fi0Dk0AvyUsK5IQ83LutT5jZezKNE8wkc1ryj+OnYBi9zbqArdi0Euam/aT', b'4Sq1xw0CgYEA0lezj+p6vasX14PlVic/rdlmpWqQqWHZR6kltOtK+x50W0QHHtPC', b'fTyDk3hJ4DczzBmjsyVHQPjkw3dqY3KtSWOrInjoJGGOBxQgv85c+uaLXsh9iOM2', b'H64JYHboXcp5G2+So3nz6mzrlB/j9St/CrZB6d1RenWJH6y86nWrOsMCgYEAuN4/', b'kb/aZ7PbdGK71zjCHqCGK9EvV3Lo0rn/HUQSr8g/kiBsKtXOLwi9vaF+VM5xVcJ2', b'DvH835CP7zoF6/58NAh90I5nOCJ6Ukt9VsWJvx7+78QSykU9L0BJLWarA6nQlEis', b'kNSNB1NE27Zu3KHnXRaFM+LKv4pxP9CJ+Bb24vsCgYEAwBPCLxuJ9gV1AiK5nBC/', b'P7wU1d0YOPTXe27kte9fSy2mR2k5r1bkdYR7CoF/xLXkIO8Q45iZFqWyESTNC/8+', b'apQPRK1wHzjOf3xL45tIoP1CK82dhREm7Yr5mRM8Ydlw+jLKj2nf6SSJg3wTqGCN', b'5HRGgI7PxqnqC/irktbdBA0CgYEAmKBMxW0qyPFR3p3hTUf75ENNYoGa30zscYXD', b'3QqljuD5sw/3ncnVJznFRPk+jo++PDqHM8GPr5fvbWdvGi6Jpn/YN8ZJ66tzZ9wR', b'SAFgvxy9B4DOrpZJdGhTwhsAV87seHAjoJMLOCAEOo08rAUzOcRtBrBYCZkn9LKc', b'Jen3vN8CgYAStWv4jLNEGcJWweAIgQlGoaJPLGEd5aGP7au2NWtUsG1cbj8NUYox', b'CAweSjQrmvA1fHIWrMO3Cc99/04/aRQwHcLdgqCVMXBDIe9tuBo/QhTTcfC5bGye', b'X/HTMjfXHpsBUocsDpeQ/zeoKclZFQUsUbVg2Bfs292kaFr7YginHQ==',
b'-----END RSA PRIVATE KEY-----']public_key:
[b'-----BEGIN PUBLIC KEY-----',
b'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl+WlWH3VkNfRFXjxpmNr', b'TskYDEF/MFGufYy5gfZ8+p9O2CwkRC2s6jv8dtdxi+a+GUvnks54xdnKAeOAgdd9', b'HHs9hK0DmeGymVFUUfglfgIm3xm5A33i2m6Eg/5Uipq3fVPx4sqlME2uHJs4Vb/4', b'wN+Tz/F2xllIsSzeHR3oKg8EYc0woW3EHqLpvBUy+V5OIjlkajXFLpCIFlYMAXGb', b'DJ9jTNP4IU8sDUc1MDCB4MyNE9QsYTjujj8YFbNmTEM3RSMV/oCTtsEmVIjxENNM', b'b94+8tmpzMku//oQALTwZ9aKJsoVVERVmu42gxJtRIYWrIpkhf713GWYUUdBwiTD',
b'MQIDAQAB',
b'-----END PUBLIC KEY-----']
相关文章:

【python】cryptography库学习
【python】cryptography库学习 cryptography学习1-安装2-cryptography学习2.1-fernet的使用2.2-padding填充2.3-Hash2.4-ciphers(对称算法AES为例)2.5-asymmetric(非对称算法RSA为例)函数:generate_private_key类:RSAPrivateKey&a…...

解密!抖音百万粉丝博主三维地图视频都用到了什么GIS数据和技术
引言 在抖音上有许多诸如三维地图科普局、三维地图看世界和三维地图鉴赏等百万粉丝博主靠着三维地图科普城市、景区、人文和地理视频获赞百万,在我们浏览视频时犹如身临其境一般,那么制作这些视频需要什么GIS技术呢?如何利用MapMost技术自己…...

Python知识点:如何使用Kubernetes与Python进行容器编排
Kubernetes 是一个开源的容器编排平台,用于自动化容器化应用的部署、管理和扩展。结合 Python,你可以通过 Kubernetes API 和工具,如 kubectl 和 kubernetes-client 库,来编写和管理容器化应用。以下是如何使用 Kubernetes 和 Pyt…...

Markdown与Word中插入图片的方法及比较
在撰写文档时,无论是技术文档、博客还是学术论文,插入图片都是非常常见的需求。本文将对比两种流行的文本编辑工具——Markdown和Microsoft Word——在插入图片方面的异同点。 Markdown插入图片 如何插入图片 在Markdown中插入图片非常简单࿰…...

Vue3+Vite安装配置tailwindCss
考虑到官网不是很好访问,这里记录一下简单步骤方便小友查阅 1. 安装依赖 npm install -D tailwindcss postcss autoprefixer2. 初始化配置文件 npx tailwindcss init -p3.配置模板路径 /** type {import(tailwindcss).Config} */ export default {content: [&quo…...

大数据学习-Spark基础入门
一、Spark是什么? Stack Overflow的数据可以看出,2015年开始Spark每月的问题提交数量已经超越Hadoop,而2018年Spark Python版本的API PySpark每月的问题提交数量也已超过Hadoop。2019年排名Spark第一,PySpark第二;而十…...

C语言:链表插入
链表的插入分为头插入,中间插入和尾插入。 具体方法如下: #include<stdio.h> #include<stdlib.h>typedef struct node {int s;struct node* pnext; }list;list* addnode(list** pphead, list** ppend, int n) {list* ptemp malloc(sizeof…...

xss 一些例子
目录 XSS 1.Ma Spaghet!编辑 2.Jefff编辑 3.Ugandan Knuckles编辑 4.Ricardo Milos编辑 5.Ah Thats Hawt编辑 6.Ligma编辑 7.Mafia编辑 简单解法就是换一个函数 作者得原意解法 8.Ok, Boomer编辑 XSS 1.Ma Spaghet! 这里接收了一个somebody参数&…...

基于Docker compose部署Confluence 8.3.4及设置数据持久化存储的总结
基于Docker compose部署Confluence 8.3.4及设置数据持久化存储的总结 一、环境信息二、安装部署三、向导 介绍如何基于Docker、Docker Compose的方式安装部署Confluence 8.3.4,并且设置数据的持久化存储。 一、环境信息 操作系统:CentOS 7.9 Docker Ver…...

eNSP 华为交换机生成树协议
华为交换机生成树协议 生成树协议原理与作用 选举一个交换机作为根网桥(生成树的根),计算出到其他所有交换机的最佳路径,把备用路径的端口设为堵塞状态(逻辑上关闭备用路径),当最佳路径故障再…...

flutter事件与消息通知
事件与消息通知 一、原始指针事件(触摸事件) 命中测试 事件阶段:手指按下、手指移动、手指抬起事件冒泡,无法停止冒泡Listener 组件:监听原始触摸事件 onPointerDown:手指按下回调onPointerMove:手指移动回调onPointerUp:手指抬起回调onPointerCancel:触摸事件取消回…...

Oracle PL/SQL存储过程和函数简单示例
以下是关于Oracle PL/SQL存储过程和函数的一些问题和答案: 问题1:什么是Oracle PL/SQL? 答案:Oracle PL/SQL(Procedural Language Extensions to SQL)是Oracle对SQL的过程语言扩展,它是一种编…...

同态加密和SEAL库的介绍(十)CKKS 参数心得 2
写在前面: 本篇继续上篇的测试,首先针对密文深度乘法情况,虽然密文乘法本就是应该尽量避免的(时间和内存成本过高),更不用说深度乘法了,但是为了测试的完整性,还是做一下方便大家比对…...

Debug-021-el-table实现分页多选的效果(切换分页,仍可以保持前一页的选中效果)
前情提要: 这个功能实现很久了,但是一直没有留意如何实现,今天想分享一下。具体就是我们展示table数据的时候,表格中的数据多数情况是分页展示,毕竟数据量太多,分页的确是有必要的。那么我们有业务需要给表…...

FPGA开发——DS18B20读取温度并且在数码管上显示
一、简介 在上一篇文章中我们对于DS18B20的相关理论进行了详细的解释,同时也对怎样使用DS18B20进行了一个简单的叙述。在这篇文章我们通过工程来实现DS18B20的温度读取并且实现在数码管伤显示。 1、基本实现思路 根据不同时刻的操作,我们可以使用一个状…...

电流测量分流电阻
电流测量分流电阻 测量电流的设备称为安培计。大多数现代安培计测量已知电阻的精密电阻上的电压降。电流的计算使用欧姆定律:我五R 大多数电流表都内置电阻器来测量电流。但是,当电流对于电流表来说太高时,需要不同的设置。解决方案是将电流…...

MES系统:智能化排班排产的全面解决方案
MES(制造执行系统)管理系统通过集成多种先进技术、实时数据采集与分析、优化算法应用以及与其他系统的协同工作,实现了智能化排班排产功能。以下是该功能的详细实现方式: 数据集成与实时采集:MES系统与ERP、SCM、设备管…...

50道深度NLP和人工智能领域面试题+答案
编者按:分享一个很硬核的免费人工智能学习网站,通俗易懂,风趣幽默, 可以当故事来看,轻松学习。 什么是自然语言处理(NLP)?自然语言处理是一种人工智能领域,致力于使计算机…...

最小矩阵宽度(85%用例)C卷(JavaPythonC++Node.jsC语言)
给定一个矩阵,包含N*M个整数,和一个包含K个整数的数组。 现在要求在这个矩阵中找一个宽度最小的子矩阵,要求子矩阵包含数组中所有的整数。 输入描述: 第一行输入两个正整数N,M,表示矩阵大小。 接下来N行M列表示矩阵内容。 下一行包含一个正整数K。 下一行包含K个整数,…...

STM32数据按字符截取与转换
目录 1. 截取2. 转换 1. 截取 以SW,33,55,78,\r\n为例 char* pa,pb,pc,pd,pe; uint8_t usart5_rxsavebuf[] "SW,12,32,33,55,78,\r\n";strtok((char *)usart5_rxsavebuf, ","); pa strtok(NULL, ","); pb strtok(NULL, ","); pc …...

使用kubeadm快速部署一套K8S集群
一、Kubernetes概述 1.1 Kubernetes是什么 Kubernetes是Google在2014年开源的一个容器集群管理系统,Kubernetes简称K8S。 K8S用于容器化应用程序的部署,扩展和管理。 K8S提供了容器编排,资源调度,弹性伸缩,部署管理…...

【Kotlin】在Kotlin项目中使用AspectJ
前言 AOP编程在Java开发中是一个非常火热的话题,最著名的库为AspectJ Kotlin项目中,通过Gradle插件,也能够使用该库,这是我们下面讲解的重点 由于AspectJ的原理是在预编译阶段,通过插件修改代码,生成代理…...

web实现drag拖拽布局
这种拖拽布局功能其实在电脑操作系统或者桌面应用里面是经常使用的基础功能,只是有时候在进行web开发的时候,对这个功能需求量不够明显,但却是很好用,也很实用。能够让用户自己拖拽布局,方便查看某个区域更多内容&…...

Linux网络编程—listen、accept、connect
一、网络四件套 #include <sys/types.h> //头文件;这四个文件一包,基本网络就无问题了; #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> 二、listen 监听:将套…...

logback.xml自定义标签节点
logback.xml自定义标签节点 问题 <?xml version"1.0" encoding"UTF-8" ?> <configuration scan"true" scanPeriod"60 seconds" debug"false"><appender name"console" class"ch.qos.logb…...

探索DevExpress WinForms:.NET世界中的UI库之星
开篇概述 作为一名资深的技术专家,我对.NET开发和UI库有着深入的了解。今天,我要向您介绍的是DevExpress WinForms —— 一款在.NET开发领域广受欢迎的开源UI库。它以其强大的功能、优雅的设计和卓越的性能,成为了众多开发者的首选。 主体讲解…...

零基础学习Redis(4) -- 常用数据结构介绍
我们之前提到过,redis中key只能是字符串类型,而value有多种类型。 redis中的数据结构有自己独特的实现方式能根据特定的场景进行优化 1. string(字符串) 内部编码: raw:最基本的字符串,类比我们平常使用的Stringin…...

Python实现水果忍者(开源)
一、整体介绍: 1.1 前言: 游戏代码基于Python制作经典游戏案例-水果忍者做出一些改动,优化并增加了一些功能。作为自己Python阶段学习的结束作品,文章最后有源码链接。 1.2 Python主要知识: (1…...

Windows自动化3️⃣WindowsPC拽起时长问题解决方案
问题描述: Windows应用从点击, 到加载完成, 需要一定的时间后台是否已经启动过当前程序?启动后, 前后台应用关闭问题等 我的解决思路: 首先检查进程 , 当前进程是否在运行, 如果进程在运行, 需要先关闭进程 关闭进程后, 开始我们的自动化流程, 去拽起 应用 拽起应用后, 可以先…...

一篇文章入门Java虚拟机(JVM)
JVM全称是Java Virtual Machine,中文译名Java虚拟机。本质上是一个运行在计算机上的程序 一,JVM的功能 功能描述解释和运行对字节码文件中的指令,实时的解释成机器码,让计算机执行内存管理自动为对象、方法等分配内存࿱…...