python中cryptography庫的實現(xiàn)
1-安裝
pip install cryptography
2-cryptography學習
查看cryptography的目錄結(jié)構(gòu)
cryptography/ hazmat/ # 主要目錄,對稱加解密的庫文件都在此目錄下 backends/ # 此目錄暫不做研究,此目錄跟openssl關聯(lián)較大 bindings/ # 此目錄暫不做研究,此目錄跟openssl有關 primitives/ # 本文主要學習此目錄下的內(nèi)容,包含對數(shù)據(jù)的填充,對稱加解密,以及非對稱加解密,公鑰和私鑰的簽名驗簽 asymmetric/ 非對稱密碼相關內(nèi)容,有需要可對文件內(nèi)容詳細了解【常用rsa.py】 ciphers/ 對稱加密算法內(nèi)容,本文主要講述的內(nèi)容 -- aead.py:aesd算法內(nèi)容,含ChaCha20Poly1305、AESCCM、AESGCM、AESOCB3。 -- algorithms.py:對稱算法的主要內(nèi)容,含AES、Camellia、TripleDES、ChaCha20、SM4等等 -- base.py:實際使用中基本用不到 -- modes.py:加密模式 kdf/ # 加密密鑰派生和密鑰存儲相關,有需要自行了解 serialization/ 序列化相關,有需要自行了解 twofactor/ 該模塊包含與雙因素認證相關的算法。目前,它包含了一種基于基于哈希的消息身份驗證碼(HMAC)來生成和驗證一次性密碼值的算法。有需要自行了解 -- cmac.py:cmac相關 -- constant_time.py -- hashes.py:加密哈希函數(shù)接 -- hmac.py:hmac算法 -- keywrap.py:沒有用過 -- padding.py:填充 -- poly1305.py:poly1305算法 -- ....其他文件 x509/ # x509證書相關內(nèi)容 -- fernet.py:對稱算法的實現(xiàn),使用cryptography最基礎的使用,
2.1-fernet的使用
cryptography最基本的使用
Fernet方法的簡單介紹
classmethod generate_key():類方法,用于生成base64-encoded 32-byte key. encrypt(data):實例方法,加密數(shù)據(jù) encrypt_at_time(data, current_time):使用顯式傳遞的當前時間加密傳遞的數(shù)據(jù) decrypt(token, ttl=None):實例方法,解密數(shù)據(jù) decrypt_at_time(token, ttl, current_time):使用顯式傳遞的當前時間來解密令牌 extract_timestamp(token):返回該令牌的時間戳。然后,調(diào)用者可以決定令牌是否即將到期,例如,發(fā)出一個新的令牌 MultiFernet(fernets):MultiFernet類,這個類為Fernet實現(xiàn)了密鑰流轉(zhuǎn)。它接受一個Fernet實例列表,并實現(xiàn)相同的API
Fernet的使用示例
示例來源于庫文檔介紹中的內(nèi)容
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'...' # 每一次的結(jié)果都是不同的 >>> f.decrypt(token) b'my deep dark secret'
2.2-padding填充
padding.py
提供PKCS7和ANSIX923填充方式PKCS7
:填充到指定長度,填充內(nèi)容為填充的長度ANSIX923
:填充最后一個字節(jié)為長度,其余的為0
這里以PKCS7為例:
import binascii from cryptography.hazmat.primitives import padding class MyPadding: def __init__(self, block_size: int): self.block_size = block_size def 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 result def unpadding(self, unpadding_data): unpadder = padding.PKCS7(block_size=self.block_size).unpadder() result = unpadder.update(unpadding_data) + unpadder.finalize() return result if __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的使用。
- 實例hash對象hashes.HASH(hashes.‘hash_name’()) -> 把‘hash_name’替換為哈希算法名即可,比如SHA1,SHA256等等,如果不清楚支持哪些,可以查看hashes.py文件,里面有列舉
- 如果hash內(nèi)容很多,可以分多次update,沒有內(nèi)容了,最后finalize即可
- HASH:SHA1,SHA512_224,SHA512_256,SHA224,SHA256,SHA384,SHA512,SHA3_224,SHA3_256,SHA3_384,SHA3_512,SHAKE128,SHAKE256,MD5,BLAKE2b,BLAKE2s,SM3
>>> 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模式結(jié)合。使用AES加密內(nèi)容,然后解密內(nèi)容的一個簡單例子:
>>> 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'
封裝使用:
如需要使用其他算法,只需要根據(jù)下方封裝的,簡單修改即可,大部分只需要修改加解密中使用的算法名稱即可
#!/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_padding MODES_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 = 128 key_sizes = frozenset([128, 192, 256, 512]) def __init__(self, alg_key: bytes = None, alg_modes: str = 'CBC', alg_iv: bytes = b'1234567812345678'): # 默認key_size,為32 if alg_key is None: self.__alg_key = gen_key(32) else: self.__alg_key = alg_key self.__alg_iv = alg_iv self.__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_key def 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 = iv def encrypt(self, plain_data: str): """ 輸入字符串,完成加密操作 :param plain_data: 明文字符串 :return: 16進制密文字符串 """ # 完成數(shù)據(jù)填充,轉(zhuǎn)為bytes后的填充數(shù)據(jù) 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() # 轉(zhuǎn)為大寫的16進制字符串輸出 return binascii.b2a_hex(result).upper().decode() def decrypt(self, cipher_data: str): """ 輸入16進制密文數(shù)據(jù),返回原文 :param cipher_data: 16進制密文數(shù)據(jù)字符串 :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) # 轉(zhuǎn)為大寫的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: 6EAE64A7B78A5C0985A1CADA8FAAB7D0 plain: hello world key: b'4f56291a9aaa86fbd341ac5ca0bb10fa5d583d281b55f853172e83197effa0c2' iv: b'31323334353637383132333435363738' alg_name: AES '''
2.5-asymmetric(非對稱算法RSA為例)
asymmetric
對應的位置在//cryptography/hazmat/primitives/asymmetric
路徑下,cryptography
庫支持多種非對稱算法,包括:ed25519、RSA、dh、dsa、ed448等。這個以最常見的RSA算法為例。
按照官方文檔中的介紹,主要內(nèi)容為:
Generation
:生成一個RSA私鑰key loading
:加載PEM格式的密鑰Key serialization
:密鑰序列化,可以獲取一個base64格式的密鑰Signing
:用私鑰對消息進行簽名,公鑰可以對結(jié)果進行驗簽Verification
:對應公鑰對消息的驗簽Encryption
:使用公鑰對數(shù)據(jù)進行加密,這樣只有擁有私鑰的才可已經(jīng)進行解密Decryption
:私鑰解密公鑰加密的信息Padding
:RSA簽名需要一個特定的散列函數(shù),并且需要使用填充,加密的時候也會涉及到對消息的填充Numbers
:包含RSA密鑰的組成,可以獲取到對應公鑰和私鑰的組成,一般不建議使用。Handling partial RSA private keys
:用不到,一般都是專業(yè)的密碼使用者才有可能用到Key interfaces
:密鑰對應的主要接口
查看asymmetric
目錄下的rsa.py
文件,根據(jù)源碼中的內(nèi)容,學習上述的主要內(nèi)容
函數(shù):generate_private_key
def generate_private_key( public_exponent: int, key_size: int, backend: typing.Any = None, )-> RSAPrivateKey: pass ''' public_exponent:指數(shù),這個根據(jù)密碼學的知識,這個默認都是傳65537 key_size Parameters ? public_exponent (int) – 指數(shù),這個根據(jù)密碼學的知識,這個默認都是傳65537 ? key_size (int) – 指的是私鑰長度(位),如1024bit,2048bit,4096bit ? backend - 默認即可 Returns 返回 RSAPrivateKey 類 ,這個類也是在`rsa.py`文件中定義好的 '''
類:RSAPrivateKey(私鑰類)
class RSAPrivateKey(metaclass=abc.ABCMeta): @abc.abstractmethod def decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes: """ 解密提供的密文。可以看到傳參除了密文外,還需要填充算法,對應的填充算法可以查看`asymmetric`下的padding.py """ @property @abc.abstractmethod def key_size(self) -> int: """ 密鑰的長度,也就說通過generate_private_key函數(shù)傳入的key_size """ @abc.abstractmethod def public_key(self) -> RSAPublicKey: """ 與此私鑰關聯(lián)的RSAPublicKey(也是一個類,公鑰類)。 """ @abc.abstractmethod def sign( self, data: bytes, padding: AsymmetricPadding, algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], ) -> bytes: """ 對消息進行簽名.涉及填充算法,以及hash算法 """ @abc.abstractmethod def private_numbers(self) -> RSAPrivateNumbers: """ 返回RSAPrivateNumbers類,一般很少用到,不做具體研究 """ @abc.abstractmethod def private_bytes( self, encoding: _serialization.Encoding, format: _serialization.PrivateFormat, encryption_algorithm: _serialization.KeySerializationEncryption, ) -> bytes: """ 返回私鑰的序列化 """
類:RSAPublicKey(公鑰類)
class RSAPublicKey(metaclass=abc.ABCMeta): @abc.abstractmethod def encrypt(self, plaintext: bytes, padding: AsymmetricPadding) -> bytes: """ 加密給定的明文 """ @property @abc.abstractmethod def key_size(self) -> int: """ 公共模的比特長度。 """ @abc.abstractmethod def public_numbers(self) -> RSAPublicNumbers: """ 返回 RSAPublicNumbers 類 """ @abc.abstractmethod def public_bytes( self, encoding: _serialization.Encoding, format: _serialization.PublicFormat, ) -> bytes: """ 返回公鑰的序列化 """ @abc.abstractmethod def verify( self, signature: bytes, data: bytes, padding: AsymmetricPadding, algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], ) -> None: """ 對消息進行驗簽 """ @abc.abstractmethod def recover_data_from_signature( self, signature: bytes, padding: AsymmetricPadding, algorithm: typing.Optional[hashes.HashAlgorithm], ) -> bytes: """ 從簽名中恢復原始數(shù)據(jù)。 """ @abc.abstractmethod def __eq__(self, other: object) -> bool: """ Checks equality. """
rsa.py的其他內(nèi)容
- class RSAPrivateNumbers:RSAPrivateNumbers類,前面內(nèi)容中提到的,獲取私鑰的組成的內(nèi)容,比如p,q,d等等。如果是外部知道這些私鑰組成值,也可以用類方法private_key,返回RSAPrivateKey類
- class RSAPublicNumbers:RSAPublicNumbers類,前面內(nèi)容中提到的,獲取公鑰的組成的內(nèi)容。比如e,n,如果是外部知道這些公鑰組成值,也可以用類方法public_key,返回RSAPublicKey類
- 等等(其他是配套對函數(shù),有興趣自行了解)
非對稱算法下的padding.py的使用
對應文件的位置:跟rsa.py文件位于同一級目錄下,這個padding文件是專門用于非對稱算法中的填充,只提供了3種填充方式:
PKCS1v15
:一個簡單的填充方案,可用于簽名和加密。不建議PKCS1v15
用于新應用,官方建議說是加密首選OAEP
,簽名首選PSS
PSS
:RSA
簽名推薦的填充算法。不能與RSA
加密一起使用OAEP
:RSA
加密的填充算法。它不能與RSA
簽名一起使用
# 示例 類PKCS1v15:無需任何參數(shù),是最簡單的填充方式,每次的結(jié)果都是一樣 類OAEP:需要3個參數(shù) 參數(shù): ? mgf – 掩碼生成函數(shù)對象. 只支持 MGF1. ? algorithm – 哈希算法的一個實例 ? label (bytes) – 要設置的應用標簽(沒了解),默認None即可. 類PSS:需要2個參數(shù) 參數(shù): ? mgf – 掩碼生成函數(shù)對象. 只支持 MGF1. ? salt_length (int) – 鹽的長度。建議將其設置為PSS.DIGEST_LENGTH或PSS.MAX_LENGTH.
示例
結(jié)合上述的內(nèi)容,rsa主要內(nèi)容可以分為以下四部分
- 生成密鑰對->對應私鑰類->私鑰類中有對應獲取公鑰類的方法
- 公鑰和私鑰對應的方法:常見的就是加密,解密,簽名,驗簽
- 公鑰和私鑰的序列化
- 公鑰和私鑰組成部分的獲取,或根據(jù)對應的值生成對應的公鑰類私鑰類
其他:serialization目錄用于序列化私鑰和公鑰的內(nèi)容,將公鑰和私鑰保存或加載,這里不做具體介紹,只給出示例,有需要可以去了解serialization下的內(nèi)容
- 密鑰生成,加密,解密,簽名,驗簽,查看密鑰對信息,序列化
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 # 以下示例均來自官方文檔的的內(nèi)容,加以整合 # 生成密鑰對,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,返回簽名結(jié)果 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("signature :",binascii.b2a_hex(signature)) # 驗證簽名:有公鑰、消息、簽名值和所使用的簽名算法,這個是沒有返回值,驗簽失敗會引發(fā)異常: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:涉及的功能還有l(wèi)oad公鑰和私鑰,可加載pem,der等格式的數(shù)據(jù),以及證書相關的數(shù)據(jù),有需要可以去了解 '''
結(jié)果:
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庫的實現(xiàn)的文章就介紹到這了,更多相關python cryptography庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python?Pygame實戰(zhàn)之紅心大戰(zhàn)游戲的實現(xiàn)
說起Windows自帶的游戲,相信許多80、90后的朋友都不陌生。本文就將利用Python中的Pygame模塊實現(xiàn)一下windows經(jīng)典游戲之一的紅心大戰(zhàn),需要的可以參考一下2022-02-02