python RSA加密、解密、签名
python中用于RSA加解密的庫有好久個,本文主要講解rsa、M2Crypto、Crypto這三個庫對于RSA加密、解密、簽名、驗簽的知識點。
知識基礎
加密是為了保證傳輸內容隱私,簽名是為了保證消息真實性。
服務器存私鑰,客戶端存公鑰。(服務器和客戶端關系可以考慮為 1:N)
客戶端往服務器傳輸內容,更多考慮是隱私性,所以公鑰簽名、私鑰解密。
服務器往客戶端傳輸內容,更多考慮真實性,所以私鑰簽名,公鑰驗簽。
消息的摘要生的算法常用的是MD5或者SHA1,消息內容不一樣,生成的摘要信息一定不一樣。
真實性的考慮一方面是內容由私鑰擁有者發出,另一方面內容在傳輸過程中沒有改變過,所以簽名的對象是傳輸信息生成的消息摘要(摘要內容短,簽名也會快些)。
每次加密的長度需要小于密鑰長度-特殊位(128位公鑰,最長可加密128-11=117位明文)。
每次解密的長度需要小于密鑰的長度(128位私鑰解密,解密密文長度需要小于等于128位)。
如果加解密內容過長,就需要分段加密、解密。
PEM格式的密鑰為base64位文本格式。
環境配置
環境:MAC
python版本:2.7.15(因為公司用的版本都是這個,建議用python3的)
IED:PyCharm
密鑰:PEM文件
rsa
示例代碼
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | # -*- coding: UTF-8 -*- # ! /usr/bin/env python import?base64 import?rsa from?rsa?import?common ? ? # 使用 rsa庫進行RSA簽名和加解密 class?RsaUtil(object): ????PUBLIC_KEY_PATH?=?'/Users/anonyper/Desktop/key/company_rsa_public_key.pem'??# 公鑰 ????PRIVATE_KEY_PATH?=?'/Users/anonyper/Desktop/key/company_rsa_private_key.pem'??# 私鑰 ? ????# 初始化key ????def?__init__(self, ?????????????????company_pub_file=PUBLIC_KEY_PATH, ?????????????????company_pri_file=PRIVATE_KEY_PATH): ? ????????if?company_pub_file: ????????????self.company_public_key?=?rsa.PublicKey.load_pkcs1_openssl_pem(open(company_pub_file).read()) ????????if?company_pri_file: ????????????self.company_private_key?=?rsa.PrivateKey.load_pkcs1(open(company_pri_file).read()) ? ????def?get_max_length(self, rsa_key, encrypt=True): ????????"""加密內容過長時 需要分段加密 換算每一段的長度. ????????????:param rsa_key: 鑰匙. ????????????:param encrypt: 是否是加密. ????????""" ????????blocksize?=?common.byte_size(rsa_key.n) ????????reserve_size?=?11??# 預留位為11 ????????if?not?encrypt:??# 解密時不需要考慮預留位 ????????????reserve_size?=?0 ????????maxlength?=?blocksize?-?reserve_size ????????return?maxlength ? ????# 加密 支付方公鑰 ????def?encrypt_by_public_key(self, message): ????????"""使用公鑰加密. ????????????:param message: 需要加密的內容. ????????????加密之后需要對接過進行base64轉碼 ????????""" ????????encrypt_result?=?b'' ????????max_length?=?self.get_max_length(self.company_public_key) ????????while?message: ????????????input?=?message[:max_length] ????????????message?=?message[max_length:] ????????????out?=?rsa.encrypt(input,?self.company_public_key) ????????????encrypt_result?+=?out ????????encrypt_result?=?base64.b64encode(encrypt_result) ????????return?encrypt_result ? ????def?decrypt_by_private_key(self, message): ????????"""使用私鑰解密. ????????????:param message: 需要加密的內容. ????????????解密之后的內容直接是字符串,不需要在進行轉義 ????????""" ????????decrypt_result?=?b"" ? ????????max_length?=?self.get_max_length(self.company_private_key,?False) ????????decrypt_message?=?base64.b64decode(message) ????????while?decrypt_message: ????????????input?=?decrypt_message[:max_length] ????????????decrypt_message?=?decrypt_message[max_length:] ????????????out?=?rsa.decrypt(input,?self.company_private_key) ????????????decrypt_result?+=?out ????????return?decrypt_result ? ????# 簽名 商戶私鑰 base64轉碼 ????def?sign_by_private_key(self, data): ????????"""私鑰簽名. ????????????:param data: 需要簽名的內容. ????????????使用SHA-1 方法進行簽名(也可以使用MD5) ????????????簽名之后,需要轉義后輸出 ????????""" ????????signature?=?rsa.sign(str(data), priv_key=self.company_private_key,?hash='SHA-1') ????????return?base64.b64encode(signature) ? ????def?verify_by_public_key(self, message, signature): ????????"""公鑰驗簽. ????????????:param message: 驗簽的內容. ????????????:param signature: 對驗簽內容簽名的值(簽名之后,會進行b64encode轉碼,所以驗簽前也需轉碼). ????????""" ????????signature?=?base64.b64decode(signature) ????????return?rsa.verify(message, signature,?self.company_public_key) ? ? message?=?'hell world' print("明文內容:>>> ") print(message) rsaUtil?=?RsaUtil() encrypy_result?=?rsaUtil.encrypt_by_public_key(message) print("加密結果:>>> ") print(encrypy_result) decrypt_result?=?rsaUtil.decrypt_by_private_key(encrypy_result) print("解密結果:>>> ") print(decrypt_result) sign?=?rsaUtil.sign_by_private_key(message) print("簽名結果:>>> ") print(sign) print("驗簽結果:>>> ") print(rsaUtil.verify_by_public_key(message, sign)) ? #執行結果 明文內容:>>> hell world 加密結果:>>> sWx9r30CCLXip0iemCb2r1gsZIedgLp1Vmk9uCDaQttcQNftwQyI98shN2Hpn7snE27ziJnH6qYmaf68TWBerhJVGEzr16wLYInVft0Bj0+kcCmLL7tMJRZWydqHi/YzgIfsFEvqLOUFv6E9bCAXhJkikacBAG4FWTMBrXUQHjE= 解密結果:>>> hell world 簽名結果:>>> GS3MPpb4zMLIL7mqcxZEevOoH1Fse9fjHefWIUpDaMplhoPUNK85TreYmOwvF8QJNxgLcJoKKfRm51gemsQd1/e1FBPo/4VS3kvneJyLUtQAPdOOl+R4h//0gFec+ELI+KS8A74Dkm2bFKztZ4BxIcWD63pHRiGAnS8+cQeq2QM= 驗簽結果:>>> True |
知識點
- rsa計算密鑰長度的方式是?common.byte_size(rsa_key.n)
- rsa加密:rsa.encrypt(message, pub_key)
- rsa解密:rsa.decrypt(crypto, priv_key)
- rsa簽名:rsa.sign(message, priv_key, hash)
- rsa驗簽:rsa.verify(message, signature, pub_key)
- rsa默認沒有私鑰加密,公鑰解密的方法(加解密傳入錯誤的key會報錯,如果想實現私鑰加密,公鑰解密可以自行模擬底層代碼實現)
- 簽名只能用私鑰(用到私鑰的n值,公鑰沒有n值,n、d、e具體什么意思請百度RSA算法原理)
- rsa加載公鑰和私鑰的方法不同
- rsa私鑰簽名時,需要傳入的是不是具體的摘要信息(字符串),而是簽名信息的hash對象(對象)
- 不同版本的rsa驗簽成功之后返回結果不一樣,有的是True,有的是返回生成摘要算法名:如sha1
Crypto
示例代碼
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | # -*- coding: UTF-8 -*- # ! /usr/bin/env python import?base64 from?Crypto.Cipher?import?PKCS1_v1_5 as PKCS1_v1_5_cipper from?Crypto.Signature?import?PKCS1_v1_5 from?Crypto.PublicKey?import?RSA from?Crypto.Hash?import?SHA ? import?Crypto ? ? # 使用 rsa庫進行RSA簽名和加解密 ? ? class?RsaUtil(object): ????PUBLIC_KEY_PATH?=?'/Users/anonyper/Desktop/key/company_rsa_public_key.pem'??# 公鑰 ????PRIVATE_KEY_PATH?=?'/Users/anonyper/Desktop/key/company_rsa_private_key.pem'??# 私鑰 ? ????# 初始化key ????def?__init__(self, ?????????????????company_pub_file=PUBLIC_KEY_PATH, ?????????????????company_pri_file=PRIVATE_KEY_PATH): ? ????????if?company_pub_file: ????????????self.company_public_key?=?RSA.importKey(open(company_pub_file).read()) ????????if?company_pri_file: ????????????self.company_private_key?=?RSA.importKey(open(company_pri_file).read()) ? ????def?get_max_length(self, rsa_key, encrypt=True): ????????"""加密內容過長時 需要分段加密 換算每一段的長度. ????????????:param rsa_key: 鑰匙. ????????????:param encrypt: 是否是加密. ????????""" ????????blocksize?=?Crypto.Util.number.size(rsa_key.n)?/?8 ????????reserve_size?=?11??# 預留位為11 ????????if?not?encrypt:??# 解密時不需要考慮預留位 ????????????reserve_size?=?0 ????????maxlength?=?blocksize?-?reserve_size ????????return?maxlength ? ????# 加密 支付方公鑰 ????def?encrypt_by_public_key(self, encrypt_message): ????????"""使用公鑰加密. ????????????:param encrypt_message: 需要加密的內容. ????????????加密之后需要對接過進行base64轉碼 ????????""" ????????encrypt_result?=?b'' ????????max_length?=?self.get_max_length(self.company_public_key) ????????cipher?=?PKCS1_v1_5_cipper.new(self.company_public_key) ????????while?encrypt_message: ????????????input_data?=?encrypt_message[:max_length] ????????????encrypt_message?=?encrypt_message[max_length:] ????????????out_data?=?cipher.encrypt(input_data) ????????????encrypt_result?+=?out_data ????????encrypt_result?=?base64.b64encode(encrypt_result) ????????return?encrypt_result ? ????# 加密 支付方私鑰 ????def?encrypt_by_private_key(self, encrypt_message): ????????"""使用私鑰加密. ????????????:param encrypt_message: 需要加密的內容. ????????????加密之后需要對接過進行base64轉碼 ????????""" ????????encrypt_result?=?b'' ????????max_length?=?self.get_max_length(self.company_private_key) ????????cipher?=?PKCS1_v1_5_cipper.new(self.company_public_key) ????????while?encrypt_message: ????????????input_data?=?encrypt_message[:max_length] ????????????encrypt_message?=?encrypt_message[max_length:] ????????????out_data?=?cipher.encrypt(input_data) ????????????encrypt_result?+=?out_data ????????encrypt_result?=?base64.b64encode(encrypt_result) ????????return?encrypt_result ? ????def?decrypt_by_public_key(self, decrypt_message): ????????"""使用公鑰解密. ????????????:param decrypt_message: 需要解密的內容. ????????????解密之后的內容直接是字符串,不需要在進行轉義 ????????""" ????????decrypt_result?=?b"" ????????max_length?=?self.get_max_length(self.company_public_key,?False) ????????decrypt_message?=?base64.b64decode(decrypt_message) ????????cipher?=?PKCS1_v1_5_cipper.new(self.company_public_key) ????????while?decrypt_message: ????????????input_data?=?decrypt_message[:max_length] ????????????decrypt_message?=?decrypt_message[max_length:] ????????????out_data?=?cipher.decrypt(input_data, '') ????????????decrypt_result?+=?out_data ????????return?decrypt_result ? ????def?decrypt_by_private_key(self, decrypt_message): ????????"""使用私鑰解密. ????????????:param decrypt_message: 需要解密的內容. ????????????解密之后的內容直接是字符串,不需要在進行轉義 ????????""" ????????decrypt_result?=?b"" ????????max_length?=?self.get_max_length(self.company_private_key,?False) ????????decrypt_message?=?base64.b64decode(decrypt_message) ????????cipher?=?PKCS1_v1_5_cipper.new(self.company_private_key) ????????while?decrypt_message: ????????????input_data?=?decrypt_message[:max_length] ????????????decrypt_message?=?decrypt_message[max_length:] ????????????out_data?=?cipher.decrypt(input_data, '') ????????????decrypt_result?+=?out_data ????????return?decrypt_result ? ????# 簽名 商戶私鑰 base64轉碼 ????def?sign_by_private_key(self, message): ????????"""私鑰簽名. ????????????:param message: 需要簽名的內容. ????????????簽名之后,需要轉義后輸出 ????????""" ????????cipher?=?PKCS1_v1_5.new(self.company_private_key)??# 用公鑰簽名,會報錯 raise TypeError("No private key") 如下 ????????# if not self.has_private(): ????????#?? raise TypeError("No private key") ????????hs?=?SHA.new(message) ????????signature?=?cipher.sign(hs) ????????return?base64.b64encode(signature) ? ????def?verify_by_public_key(self, message, signature): ????????"""公鑰驗簽. ????????????:param message: 驗簽的內容. ????????????:param signature: 對驗簽內容簽名的值(簽名之后,會進行b64encode轉碼,所以驗簽前也需轉碼). ????????""" ????????signature?=?base64.b64decode(signature) ????????cipher?=?PKCS1_v1_5.new(self.company_public_key) ????????hs?=?SHA.new(message) ? ????????# digest = hashlib.sha1(message).digest()? # 內容摘要的生成方法有很多種,只要簽名和解簽用的是一樣的就可以 ? ????????return?cipher.verify(hs, signature) ? ? ? message?=?'hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world' print("明文內容:>>> ") print(message) rsaUtil?=?RsaUtil() encrypy_result?=?rsaUtil.encrypt_by_public_key(message) print("加密結果:>>> ") print(encrypy_result) decrypt_result?=?rsaUtil.decrypt_by_private_key(encrypy_result) print("解密結果:>>> ") print(decrypt_result) sign?=?rsaUtil.sign_by_private_key(message) print("簽名結果:>>> ") print(sign) print("驗簽結果:>>> ") print(rsaUtil.verify_by_public_key(message, sign)) ? #執行結果: 明文內容:>>> hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world 加密結果:>>> PC8/knkmszKby2pHtlKJa/Uv7EADImNhrFwZQK3YHpwPwDpt5A4bFTxsDu2o8U0yc+X50+M3Bi53C0sOHjiOCStG/Bp1nfowHQBgUFCETp4G3fpLAl7eWynqqu6gInjHQeNMbBz1wvRhSiXoMB2lJm8b9fLuzDuQQRFZPqD356kgTKnBM+lju4HE4zMjAT8jMam5Z4EnmaRfX7kYDGzga+PgbkkGon354i3CRhuRWtpvQeXnmjZq8MpfDC6//L7I/vvw4/LMJhiQJkXUbGEgSok8yg6jZzGx+bllc+qn7DH5nkNZKkOnqaeJHbEktgdhua/QXJcRR/5Lm0Y8ovs54A== 解密結果:>>> hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world 簽名結果:>>> VinHhT+iJfDvIgseJ0ZsmJcLk+yDdx0323B6vMKMUHDlUF2HDWqQhEEoqmSstjsSfR/T+4829t5DhtaJ5w1O7K7ZyP/+yu/lupc8apmfYSIziozi3vPy20p/CYNaXAy0LLGOwrtVNn3jTaq7Gb0yI4/Zhin2jNmTk09g8Qx9rGI= 驗簽結果:>>> True |
知識點
- Crypto計算密鑰長度的方法是 Crypto.Util.number.size(rsa_key.n) / 8(一個字節8位)
- Crypto導入密鑰的方法是同一個 RSA.importKey(self, externKey, passphrase=None),externKey為密鑰內容
- Crypto加密方法:Crypto.Cipher.PKCS1_v1_5.new(key).encrypt(self, message)
- Crypto解密方法:Crypto.Cipher.PKCS1_v1_5.new(key).decrypt(self, message)
- Crypto簽名方法:Crypto.Signature.PKCS1_v1_5.new(key).sign(self, mhash)
- Crypto驗簽方法:Crypto.Signature.PKCS1_v1_5_cipper.new(key).verifyverify(self, mhash, S)
- Crypto公鑰、私鑰都可以互相加解密
- Crypto只能私鑰簽名,公鑰驗簽,簽名傳入公鑰會報錯(底層有key.has_private()判斷)
- Crypto私鑰簽名時,需要傳入的是消息的摘要內容,所以摘要可以由不同的實現方式只要驗簽時摘要算法一致即可。
- Crypto驗簽之后成功返回結果True(不知道會不會與其他的)
M2Crypto
示例代碼
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | # -*- coding: UTF-8 -*- # ! /usr/bin/env python import?base64 import?M2Crypto from?M2Crypto?import?EVP ? ? # 使用 M2Crypto庫進行RSA簽名和加解密 class?RsaUtil(object): ????PUBLIC_KEY_PATH?=?'/Users/anonyper/Desktop/key/company_rsa_public_key.pem'??# 公鑰 ????PRIVATE_KEY_PATH?=?'/Users/anonyper/Desktop/key/company_rsa_private_key.pem'??# 私鑰 ? ????# 初始化key ????def?__init__(self, ?????????????????company_pub_file=PUBLIC_KEY_PATH, ?????????????????company_pri_file=PRIVATE_KEY_PATH): ? ????????if?company_pub_file: ????????????self.company_public_key?=?M2Crypto.RSA.load_pub_key(company_pub_file) ????????if?company_pri_file: ????????????self.company_private_key?=?M2Crypto.RSA.load_key(company_pri_file) ? ????def?get_max_length(self, rsa_key, encrypt=True): ????????"""加密內容過長時 需要分段加密 換算每一段的長度. ????????????:param rsa_key: 鑰匙. ????????????:param encrypt: 是否是加密. ????????""" ????????blocksize?=?rsa_key.__len__()?/?8 ????????reserve_size?=?11??# ????????if?not?encrypt: ????????????reserve_size?=?0 ????????maxlength?=?blocksize?-?reserve_size ????????return?maxlength ? ????# 加密 支付方公鑰 ????def?encrypt_by_public_key(self, encrypt_message): ????????"""使用公鑰加密. ????????????:param encrypt_message: 需要加密的內容. ????????????加密之后需要對接過進行base64轉碼 ????????""" ????????encrypt_result?=?b'' ????????max_length?=?self.get_max_length(self.company_public_key) ????????print(max_length) ????????while?encrypt_message: ????????????input_data?=?encrypt_message[:max_length] ????????????encrypt_message?=?encrypt_message[max_length:] ????????????out_data?=?self.company_public_key.public_encrypt(input_data, M2Crypto.RSA.pkcs1_padding) ????????????encrypt_result?+=?out_data ????????encrypt_result?=?base64.b64encode(encrypt_result) ????????return?encrypt_result ? ????# 加密 支付方私鑰 ????def?encrypt_by_private_key(self, encrypt_message): ????????"""使用私鑰加密. ????????????:param encrypt_message: 需要加密的內容. ????????????加密之后需要對接過進行base64轉碼 ????????""" ????????encrypt_result?=?b'' ????????max_length?=?self.get_max_length(self.company_private_key) ????????while?encrypt_message: ????????????input_data?=?encrypt_message[:max_length] ????????????encrypt_message?=?encrypt_message[max_length:] ????????????out_data?=?self.company_private_key.private_encrypt(input_data, M2Crypto.RSA.pkcs1_padding) ????????????encrypt_result?+=?out_data ????????encrypt_result?=?base64.b64encode(encrypt_result) ????????return?encrypt_result ? ????def?decrypt_by_public_key(self, decrypt_message): ????????"""使用公鑰解密. ????????????:param decrypt_message: 需要解密的內容. ????????????解密之后的內容直接是字符串,不需要在進行轉義 ????????""" ????????decrypt_result?=?b"" ????????max_length?=?self.get_max_length(self.company_private_key,?False) ????????decrypt_message?=?base64.b64decode(decrypt_message) ????????while?decrypt_message: ????????????input_data?=?decrypt_message[:max_length] ????????????decrypt_message?=?decrypt_message[max_length:] ????????????out_data?=?self.company_public_key.public_encrypt(input_data, M2Crypto.RSA.pkcs1_padding) ????????????decrypt_result?+=?out_data ????????return?decrypt_result ? ????def?decrypt_by_private_key(self, decrypt_message): ????????"""使用私鑰解密. ????????????:param decrypt_message: 需要解密的內容. ????????????解密之后的內容直接是字符串,不需要在進行轉義 ????????""" ????????decrypt_result?=?b"" ????????max_length?=?self.get_max_length(self.company_private_key,?False) ????????decrypt_message?=?base64.b64decode(decrypt_message) ????????while?decrypt_message: ????????????input_data?=?decrypt_message[:max_length] ????????????decrypt_message?=?decrypt_message[max_length:] ????????????out_data?=?self.company_private_key.private_decrypt(input_data, M2Crypto.RSA.pkcs1_padding) ????????????decrypt_result?+=?out_data ????????return?decrypt_result ? ????# 簽名 商戶私鑰 base64轉碼 ????def?sign_by_private_key(self, message): ????????"""私鑰簽名. ????????????:param message: 需要簽名的內容. ????????????簽名之后,需要轉義后輸出 ????????""" ????????hs?=?EVP.MessageDigest('sha1') ????????hs.update(message) ????????digest?=?hs.final() ????????# digest = hashlib.sha1(message).digest() # 內容摘要的生成方法有很多種,只要簽名和解簽用的是一樣的就可以 ????????signature?=?self.company_private_key.sign(digest) ????????# self.company_public_key.sign(digest)? # 用公鑰簽名IDE會崩 ????????return?base64.b64encode(signature) ? ????def?verify_by_public_key(self, message, signature): ????????"""公鑰驗簽. ????????????:param message: 驗簽的內容. ????????????:param signature: 對驗簽內容簽名的值(簽名之后,會進行b64encode轉碼,所以驗簽前也需轉碼). ????????""" ????????hs?=?EVP.MessageDigest('sha1') ????????hs.update(message) ????????digest?=?hs.final() ????????# digest = hashlib.sha1(message).digest()? # 內容摘要的生成方法有很多種,只要簽名和解簽用的是一樣的就可以 ????????signature?=?base64.b64decode(signature) ????????return?self.company_public_key.verify(digest, signature) ? ? message?=?'hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world' print("明文內容:>>> ") print(message) rsaUtil?=?RsaUtil() encrypy_result?=?rsaUtil.encrypt_by_public_key(message) print("加密結果:>>> ") print(encrypy_result) decrypt_result?=?rsaUtil.decrypt_by_private_key(encrypy_result) print("解密結果:>>> ") print(decrypt_result) sign?=?rsaUtil.sign_by_private_key(message) print("簽名結果:>>> ") print(sign) print("驗簽結果:>>> ") print(rsaUtil.verify_by_public_key(message, sign)) ? ? #執行結果 明文內容:>>> hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world 加密結果:>>> fu4RgyOaokEcLmA5k0otMirZoiFBDBkEgycgehEajtPU+xP7Wf5rN05kwbsDNI7/kUR5wOvS0XE8jD1nYmKv4uBWfR5Z28BHdK20uue/8zTnPgdsAmRdzA6Lb2EIk/g38o2EtRZ4jILNOdikpW0kYpYRdaJgoHTWTOlE/RL9zcVKzYELFPpWui2jZ8EVMe+6ZiPkRKCKL571f/OTb1qOdg4GTiowZCNMIknTxXawvZl9Funz7TNz0WsNDejL+r3tM8erwhE0ygIMtemOiVy8yBVsHpHPzfdlNRoXXgtgupFEgVgEOODUp9y4LzX6UDf0+i8uI7/SpyQoa9jSpcsIjA== 解密結果:>>> hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world 簽名結果:>>> VinHhT+iJfDvIgseJ0ZsmJcLk+yDdx0323B6vMKMUHDlUF2HDWqQhEEoqmSstjsSfR/T+4829t5DhtaJ5w1O7K7ZyP/+yu/lupc8apmfYSIziozi3vPy20p/CYNaXAy0LLGOwrtVNn3jTaq7Gb0yI4/Zhin2jNmTk09g8Qx9rGI= 驗簽結果:>>> 1 |
知識點
- M2Crypto計算密鑰長度的方法是 rsa_key.len() / 8(一個字節8位)
- M2Crypto導入密鑰的方法是不同 M2Crypto.RSA.load_pub_key(file),M2Crypto.RSA.load_key(file)//還有其他的,不列舉了,使用load_key(file)傳入公鑰地址會報錯。
- M2Crypto加密解密代碼:(RSA class下)
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def?public_encrypt(self, data, padding): ????# type: (bytes, int) -> bytes ????assert?self.check_key(),?'key is not initialised' ????return?m2.rsa_public_encrypt(self.rsa, data, padding) ? def?public_decrypt(self, data, padding): ????# type: (bytes, int) -> bytes ????assert?self.check_key(),?'key is not initialised' ????return?m2.rsa_public_decrypt(self.rsa, data, padding) ? def?private_encrypt(self, data, padding): ????# type: (bytes, int) -> bytes ????assert?self.check_key(),?'key is not initialised' ????return?m2.rsa_private_encrypt(self.rsa, data, padding) ? def?private_decrypt(self, data, padding): ????# type: (bytes, int) -> bytes ????assert?self.check_key(),?'key is not initialised' ????return?m2.rsa_private_decrypt(self.rsa, data, padding) |
- 公鑰和私鑰具體實現RSA的代碼:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | class?RSA_pub(RSA): ? ????""" ????Object interface to an RSA public key. ????""" ????#公鑰調用下面方法直接報錯 ????def?private_encrypt(self,?*argv): ????????# type: (*Any) -> None ????????raise?RSAError('RSA_pub object has no private key') ????#公鑰調用下面方法直接報錯 ????def?private_decrypt(self,?*argv): ????????# type: (*Any) -> None ????????raise?RSAError('RSA_pub object has no private key') |
- M2Crypto簽名和驗簽 sign(self, digest, algo='sha1'):/verify(self, data, signature, algo='sha1'):
- M2Crypto公鑰、私鑰都可以互相加解密
- M2Crypto只能私鑰簽名,公鑰驗簽,簽名傳入公鑰會報錯(公鑰可以調用簽名方法,但是IDE崩潰了)
- M2Crypto私鑰簽名時,需要傳入的是消息的摘要內容,所以摘要可以由不同的實現方式只要驗簽時摘要算法一致即可。
- M2Crypto驗簽之后成功返回結果1(不知道會不會與其他的)
其他注意事項
- base64位encode和decode時,可以傳入編碼集,UTF-8會將+轉化為u,將/轉化為t
- 在和服務器交互時,‘+’、‘=’、‘/’ 等特殊字符可能會被轉義,造成客戶端和服務器內容細微的不一致而導致驗簽失敗,尤其是兩邊使用的語言不通,所以要協商好轉義方案。
-
更多資訊或疑問內容添加小編微信,?回復 “Python” ,領取更多資料哦
? ?? ?
總結
以上是生活随笔為你收集整理的python RSA加密、解密、签名的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: union区别
- 下一篇: python3爬取百度图片