python RSA加密、解密、签名
python中用于RSA加解密的庫(kù)有好久個(gè),本文主要講解rsa、M2Crypto、Crypto這三個(gè)庫(kù)對(duì)于RSA加密、解密、簽名、驗(yàn)簽的知識(shí)點(diǎn)。
知識(shí)基礎(chǔ)
加密是為了保證傳輸內(nèi)容隱私,簽名是為了保證消息真實(shí)性。
服務(wù)器存私鑰,客戶端存公鑰。(服務(wù)器和客戶端關(guān)系可以考慮為 1:N)
客戶端往服務(wù)器傳輸內(nèi)容,更多考慮是隱私性,所以公鑰簽名、私鑰解密。
服務(wù)器往客戶端傳輸內(nèi)容,更多考慮真實(shí)性,所以私鑰簽名,公鑰驗(yàn)簽。
消息的摘要生的算法常用的是MD5或者SHA1,消息內(nèi)容不一樣,生成的摘要信息一定不一樣。
真實(shí)性的考慮一方面是內(nèi)容由私鑰擁有者發(fā)出,另一方面內(nèi)容在傳輸過(guò)程中沒(méi)有改變過(guò),所以簽名的對(duì)象是傳輸信息生成的消息摘要(摘要內(nèi)容短,簽名也會(huì)快些)。
每次加密的長(zhǎng)度需要小于密鑰長(zhǎng)度-特殊位(128位公鑰,最長(zhǎng)可加密128-11=117位明文)。
每次解密的長(zhǎng)度需要小于密鑰的長(zhǎng)度(128位私鑰解密,解密密文長(zhǎng)度需要小于等于128位)。
如果加解密內(nèi)容過(guò)長(zhǎng),就需要分段加密、解密。
PEM格式的密鑰為base64位文本格式。
環(huán)境配置
環(huán)境:MAC
python版本:2.7.15(因?yàn)楣居玫陌姹径际沁@個(gè),建議用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庫(kù)進(jìn)行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): ????????"""加密內(nèi)容過(guò)長(zhǎng)時(shí) 需要分段加密 換算每一段的長(zhǎng)度. ????????????:param rsa_key: 鑰匙. ????????????:param encrypt: 是否是加密. ????????""" ????????blocksize?=?common.byte_size(rsa_key.n) ????????reserve_size?=?11??# 預(yù)留位為11 ????????if?not?encrypt:??# 解密時(shí)不需要考慮預(yù)留位 ????????????reserve_size?=?0 ????????maxlength?=?blocksize?-?reserve_size ????????return?maxlength ? ????# 加密 支付方公鑰 ????def?encrypt_by_public_key(self, message): ????????"""使用公鑰加密. ????????????:param message: 需要加密的內(nèi)容. ????????????加密之后需要對(duì)接過(guò)進(jìn)行base64轉(zhuǎn)碼 ????????""" ????????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: 需要加密的內(nèi)容. ????????????解密之后的內(nèi)容直接是字符串,不需要在進(jìn)行轉(zhuǎn)義 ????????""" ????????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轉(zhuǎn)碼 ????def?sign_by_private_key(self, data): ????????"""私鑰簽名. ????????????:param data: 需要簽名的內(nèi)容. ????????????使用SHA-1 方法進(jìn)行簽名(也可以使用MD5) ????????????簽名之后,需要轉(zhuǎn)義后輸出 ????????""" ????????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): ????????"""公鑰驗(yàn)簽. ????????????:param message: 驗(yàn)簽的內(nèi)容. ????????????:param signature: 對(duì)驗(yàn)簽內(nèi)容簽名的值(簽名之后,會(huì)進(jìn)行b64encode轉(zhuǎn)碼,所以驗(yàn)簽前也需轉(zhuǎn)碼). ????????""" ????????signature?=?base64.b64decode(signature) ????????return?rsa.verify(message, signature,?self.company_public_key) ? ? message?=?'hell world' print("明文內(nèi)容:>>> ") print(message) rsaUtil?=?RsaUtil() encrypy_result?=?rsaUtil.encrypt_by_public_key(message) print("加密結(jié)果:>>> ") print(encrypy_result) decrypt_result?=?rsaUtil.decrypt_by_private_key(encrypy_result) print("解密結(jié)果:>>> ") print(decrypt_result) sign?=?rsaUtil.sign_by_private_key(message) print("簽名結(jié)果:>>> ") print(sign) print("驗(yàn)簽結(jié)果:>>> ") print(rsaUtil.verify_by_public_key(message, sign)) ? #執(zhí)行結(jié)果 明文內(nèi)容:>>> hell world 加密結(jié)果:>>> sWx9r30CCLXip0iemCb2r1gsZIedgLp1Vmk9uCDaQttcQNftwQyI98shN2Hpn7snE27ziJnH6qYmaf68TWBerhJVGEzr16wLYInVft0Bj0+kcCmLL7tMJRZWydqHi/YzgIfsFEvqLOUFv6E9bCAXhJkikacBAG4FWTMBrXUQHjE= 解密結(jié)果:>>> hell world 簽名結(jié)果:>>> GS3MPpb4zMLIL7mqcxZEevOoH1Fse9fjHefWIUpDaMplhoPUNK85TreYmOwvF8QJNxgLcJoKKfRm51gemsQd1/e1FBPo/4VS3kvneJyLUtQAPdOOl+R4h//0gFec+ELI+KS8A74Dkm2bFKztZ4BxIcWD63pHRiGAnS8+cQeq2QM= 驗(yàn)簽結(jié)果:>>> True |
知識(shí)點(diǎn)
- rsa計(jì)算密鑰長(zhǎng)度的方式是?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驗(yàn)簽:rsa.verify(message, signature, pub_key)
- rsa默認(rèn)沒(méi)有私鑰加密,公鑰解密的方法(加解密傳入錯(cuò)誤的key會(huì)報(bào)錯(cuò),如果想實(shí)現(xiàn)私鑰加密,公鑰解密可以自行模擬底層代碼實(shí)現(xiàn))
- 簽名只能用私鑰(用到私鑰的n值,公鑰沒(méi)有n值,n、d、e具體什么意思請(qǐng)百度RSA算法原理)
- rsa加載公鑰和私鑰的方法不同
- rsa私鑰簽名時(shí),需要傳入的是不是具體的摘要信息(字符串),而是簽名信息的hash對(duì)象(對(duì)象)
- 不同版本的rsa驗(yàn)簽成功之后返回結(jié)果不一樣,有的是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庫(kù)進(jìn)行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): ????????"""加密內(nèi)容過(guò)長(zhǎng)時(shí) 需要分段加密 換算每一段的長(zhǎng)度. ????????????:param rsa_key: 鑰匙. ????????????:param encrypt: 是否是加密. ????????""" ????????blocksize?=?Crypto.Util.number.size(rsa_key.n)?/?8 ????????reserve_size?=?11??# 預(yù)留位為11 ????????if?not?encrypt:??# 解密時(shí)不需要考慮預(yù)留位 ????????????reserve_size?=?0 ????????maxlength?=?blocksize?-?reserve_size ????????return?maxlength ? ????# 加密 支付方公鑰 ????def?encrypt_by_public_key(self, encrypt_message): ????????"""使用公鑰加密. ????????????:param encrypt_message: 需要加密的內(nèi)容. ????????????加密之后需要對(duì)接過(guò)進(jìn)行base64轉(zhuǎn)碼 ????????""" ????????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: 需要加密的內(nèi)容. ????????????加密之后需要對(duì)接過(guò)進(jìn)行base64轉(zhuǎn)碼 ????????""" ????????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: 需要解密的內(nèi)容. ????????????解密之后的內(nèi)容直接是字符串,不需要在進(jìn)行轉(zhuǎn)義 ????????""" ????????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: 需要解密的內(nèi)容. ????????????解密之后的內(nèi)容直接是字符串,不需要在進(jìn)行轉(zhuǎn)義 ????????""" ????????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轉(zhuǎn)碼 ????def?sign_by_private_key(self, message): ????????"""私鑰簽名. ????????????:param message: 需要簽名的內(nèi)容. ????????????簽名之后,需要轉(zhuǎn)義后輸出 ????????""" ????????cipher?=?PKCS1_v1_5.new(self.company_private_key)??# 用公鑰簽名,會(huì)報(bào)錯(cuò) 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): ????????"""公鑰驗(yàn)簽. ????????????:param message: 驗(yàn)簽的內(nèi)容. ????????????:param signature: 對(duì)驗(yàn)簽內(nèi)容簽名的值(簽名之后,會(huì)進(jìn)行b64encode轉(zhuǎn)碼,所以驗(yàn)簽前也需轉(zhuǎn)碼). ????????""" ????????signature?=?base64.b64decode(signature) ????????cipher?=?PKCS1_v1_5.new(self.company_public_key) ????????hs?=?SHA.new(message) ? ????????# digest = hashlib.sha1(message).digest()? # 內(nèi)容摘要的生成方法有很多種,只要簽名和解簽用的是一樣的就可以 ? ????????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("明文內(nèi)容:>>> ") print(message) rsaUtil?=?RsaUtil() encrypy_result?=?rsaUtil.encrypt_by_public_key(message) print("加密結(jié)果:>>> ") print(encrypy_result) decrypt_result?=?rsaUtil.decrypt_by_private_key(encrypy_result) print("解密結(jié)果:>>> ") print(decrypt_result) sign?=?rsaUtil.sign_by_private_key(message) print("簽名結(jié)果:>>> ") print(sign) print("驗(yàn)簽結(jié)果:>>> ") print(rsaUtil.verify_by_public_key(message, sign)) ? #執(zhí)行結(jié)果: 明文內(nèi)容:>>> hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world 加密結(jié)果:>>> PC8/knkmszKby2pHtlKJa/Uv7EADImNhrFwZQK3YHpwPwDpt5A4bFTxsDu2o8U0yc+X50+M3Bi53C0sOHjiOCStG/Bp1nfowHQBgUFCETp4G3fpLAl7eWynqqu6gInjHQeNMbBz1wvRhSiXoMB2lJm8b9fLuzDuQQRFZPqD356kgTKnBM+lju4HE4zMjAT8jMam5Z4EnmaRfX7kYDGzga+PgbkkGon354i3CRhuRWtpvQeXnmjZq8MpfDC6//L7I/vvw4/LMJhiQJkXUbGEgSok8yg6jZzGx+bllc+qn7DH5nkNZKkOnqaeJHbEktgdhua/QXJcRR/5Lm0Y8ovs54A== 解密結(jié)果:>>> hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world 簽名結(jié)果:>>> VinHhT+iJfDvIgseJ0ZsmJcLk+yDdx0323B6vMKMUHDlUF2HDWqQhEEoqmSstjsSfR/T+4829t5DhtaJ5w1O7K7ZyP/+yu/lupc8apmfYSIziozi3vPy20p/CYNaXAy0LLGOwrtVNn3jTaq7Gb0yI4/Zhin2jNmTk09g8Qx9rGI= 驗(yàn)簽結(jié)果:>>> True |
知識(shí)點(diǎn)
- Crypto計(jì)算密鑰長(zhǎng)度的方法是 Crypto.Util.number.size(rsa_key.n) / 8(一個(gè)字節(jié)8位)
- Crypto導(dǎo)入密鑰的方法是同一個(gè) RSA.importKey(self, externKey, passphrase=None),externKey為密鑰內(nèi)容
- 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驗(yàn)簽方法:Crypto.Signature.PKCS1_v1_5_cipper.new(key).verifyverify(self, mhash, S)
- Crypto公鑰、私鑰都可以互相加解密
- Crypto只能私鑰簽名,公鑰驗(yàn)簽,簽名傳入公鑰會(huì)報(bào)錯(cuò)(底層有key.has_private()判斷)
- Crypto私鑰簽名時(shí),需要傳入的是消息的摘要內(nèi)容,所以摘要可以由不同的實(shí)現(xiàn)方式只要驗(yàn)簽時(shí)摘要算法一致即可。
- Crypto驗(yàn)簽之后成功返回結(jié)果True(不知道會(huì)不會(huì)與其他的)
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庫(kù)進(jìn)行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): ????????"""加密內(nèi)容過(guò)長(zhǎng)時(shí) 需要分段加密 換算每一段的長(zhǎng)度. ????????????: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: 需要加密的內(nèi)容. ????????????加密之后需要對(duì)接過(guò)進(jìn)行base64轉(zhuǎn)碼 ????????""" ????????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: 需要加密的內(nèi)容. ????????????加密之后需要對(duì)接過(guò)進(jìn)行base64轉(zhuǎn)碼 ????????""" ????????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: 需要解密的內(nèi)容. ????????????解密之后的內(nèi)容直接是字符串,不需要在進(jìn)行轉(zhuǎn)義 ????????""" ????????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: 需要解密的內(nèi)容. ????????????解密之后的內(nèi)容直接是字符串,不需要在進(jìn)行轉(zhuǎn)義 ????????""" ????????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轉(zhuǎn)碼 ????def?sign_by_private_key(self, message): ????????"""私鑰簽名. ????????????:param message: 需要簽名的內(nèi)容. ????????????簽名之后,需要轉(zhuǎn)義后輸出 ????????""" ????????hs?=?EVP.MessageDigest('sha1') ????????hs.update(message) ????????digest?=?hs.final() ????????# digest = hashlib.sha1(message).digest() # 內(nèi)容摘要的生成方法有很多種,只要簽名和解簽用的是一樣的就可以 ????????signature?=?self.company_private_key.sign(digest) ????????# self.company_public_key.sign(digest)? # 用公鑰簽名IDE會(huì)崩 ????????return?base64.b64encode(signature) ? ????def?verify_by_public_key(self, message, signature): ????????"""公鑰驗(yàn)簽. ????????????:param message: 驗(yàn)簽的內(nèi)容. ????????????:param signature: 對(duì)驗(yàn)簽內(nèi)容簽名的值(簽名之后,會(huì)進(jìn)行b64encode轉(zhuǎn)碼,所以驗(yàn)簽前也需轉(zhuǎn)碼). ????????""" ????????hs?=?EVP.MessageDigest('sha1') ????????hs.update(message) ????????digest?=?hs.final() ????????# digest = hashlib.sha1(message).digest()? # 內(nèi)容摘要的生成方法有很多種,只要簽名和解簽用的是一樣的就可以 ????????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("明文內(nèi)容:>>> ") print(message) rsaUtil?=?RsaUtil() encrypy_result?=?rsaUtil.encrypt_by_public_key(message) print("加密結(jié)果:>>> ") print(encrypy_result) decrypt_result?=?rsaUtil.decrypt_by_private_key(encrypy_result) print("解密結(jié)果:>>> ") print(decrypt_result) sign?=?rsaUtil.sign_by_private_key(message) print("簽名結(jié)果:>>> ") print(sign) print("驗(yàn)簽結(jié)果:>>> ") print(rsaUtil.verify_by_public_key(message, sign)) ? ? #執(zhí)行結(jié)果 明文內(nèi)容:>>> hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world 加密結(jié)果:>>> fu4RgyOaokEcLmA5k0otMirZoiFBDBkEgycgehEajtPU+xP7Wf5rN05kwbsDNI7/kUR5wOvS0XE8jD1nYmKv4uBWfR5Z28BHdK20uue/8zTnPgdsAmRdzA6Lb2EIk/g38o2EtRZ4jILNOdikpW0kYpYRdaJgoHTWTOlE/RL9zcVKzYELFPpWui2jZ8EVMe+6ZiPkRKCKL571f/OTb1qOdg4GTiowZCNMIknTxXawvZl9Funz7TNz0WsNDejL+r3tM8erwhE0ygIMtemOiVy8yBVsHpHPzfdlNRoXXgtgupFEgVgEOODUp9y4LzX6UDf0+i8uI7/SpyQoa9jSpcsIjA== 解密結(jié)果:>>> hell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell worldhell world 簽名結(jié)果:>>> VinHhT+iJfDvIgseJ0ZsmJcLk+yDdx0323B6vMKMUHDlUF2HDWqQhEEoqmSstjsSfR/T+4829t5DhtaJ5w1O7K7ZyP/+yu/lupc8apmfYSIziozi3vPy20p/CYNaXAy0LLGOwrtVNn3jTaq7Gb0yI4/Zhin2jNmTk09g8Qx9rGI= 驗(yàn)簽結(jié)果:>>> 1 |
知識(shí)點(diǎn)
- M2Crypto計(jì)算密鑰長(zhǎng)度的方法是 rsa_key.len() / 8(一個(gè)字節(jié)8位)
- M2Crypto導(dǎo)入密鑰的方法是不同 M2Crypto.RSA.load_pub_key(file),M2Crypto.RSA.load_key(file)//還有其他的,不列舉了,使用load_key(file)傳入公鑰地址會(huì)報(bào)錯(cuò)。
- 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) |
- 公鑰和私鑰具體實(shí)現(xiàn)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. ????""" ????#公鑰調(diào)用下面方法直接報(bào)錯(cuò) ????def?private_encrypt(self,?*argv): ????????# type: (*Any) -> None ????????raise?RSAError('RSA_pub object has no private key') ????#公鑰調(diào)用下面方法直接報(bào)錯(cuò) ????def?private_decrypt(self,?*argv): ????????# type: (*Any) -> None ????????raise?RSAError('RSA_pub object has no private key') |
- M2Crypto簽名和驗(yàn)簽 sign(self, digest, algo='sha1'):/verify(self, data, signature, algo='sha1'):
- M2Crypto公鑰、私鑰都可以互相加解密
- M2Crypto只能私鑰簽名,公鑰驗(yàn)簽,簽名傳入公鑰會(huì)報(bào)錯(cuò)(公鑰可以調(diào)用簽名方法,但是IDE崩潰了)
- M2Crypto私鑰簽名時(shí),需要傳入的是消息的摘要內(nèi)容,所以摘要可以由不同的實(shí)現(xiàn)方式只要驗(yàn)簽時(shí)摘要算法一致即可。
- M2Crypto驗(yàn)簽之后成功返回結(jié)果1(不知道會(huì)不會(huì)與其他的)
其他注意事項(xiàng)
- base64位encode和decode時(shí),可以傳入編碼集,UTF-8會(huì)將+轉(zhuǎn)化為u,將/轉(zhuǎn)化為t
- 在和服務(wù)器交互時(shí),‘+’、‘=’、‘/’ 等特殊字符可能會(huì)被轉(zhuǎn)義,造成客戶端和服務(wù)器內(nèi)容細(xì)微的不一致而導(dǎo)致驗(yàn)簽失敗,尤其是兩邊使用的語(yǔ)言不通,所以要協(xié)商好轉(zhuǎn)義方案。
-
更多資訊或疑問(wèn)內(nèi)容添加小編微信,?回復(fù) “Python” ,領(lǐng)取更多資料哦
? ?? ?
總結(jié)
以上是生活随笔為你收集整理的python RSA加密、解密、签名的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: union区别
- 下一篇: python3爬取百度图片