Python中如何实现RSA加密,有PHP源码参考
最近对接第三方接口,有一个地方需要用 RSA 加密 ,接口方对 RSA 加密进行了修改,用 PYTHON 去写加密方法,看对方的 PHP 代码貌似把要加密的对象用\0 填充到 256 位 但是我用 pythonRSA 加密最多只能加密 245 位 这种情况应该咋处理? 附对面的 PHP 源码和我的 RSA 加密方法
对方给的 PHP 加密代码
<?php
$public_text = “123”;
$public_key_content="-----BEGIN CERTIFICATE-----
MIIEIjCCAwqgAwIBAgIFEDYSGTEwDQYJKoZIhvcNAQEFBQAwITELMAkGA1UEBhMC
Q04xEjAQBgNVBAoBCUNGQ0EgT0NBMTAeFw0xNTExMjMwOTE4NTZaFw0yMDExMjMw
OTE4NTZaMHcxCzAJBgNVBAYTAkNOMRIwEAYDVQQKEwlDRkNBIE9DQTExEDAOBgNV
BAsTB0hFTElQQVkxGTAXBgNVBAsTEE9yZ2FuaXphdGlvbmFsLTExJzAlBgNVBAMU
HjA1MUBoZWxpcGF5QDM0NDAxMDEwMDAyMzg4NTlAMTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAKcZmf6kn/swvVeqNODJJ46alD9RCFH/KkbbJjiVzAPg
uCG7NWZqFxwpHDSPeyc+JByBs02OI6zrZ00I2c/OoW006BtZlRugcg4Yxd4s4ih6
nTg4yCv0yT8bxtDmAGkPq/rf21rtDtWjKb4/GKYhVPp/fFlia4PT1xlCFww9qcuD
MhfCbpy1Q6Kg85uX4B3hUkl/7KAxYsG2Xb7ikOOMt+YWAPhLIoCdUe70av0Mu1LZ
x4GGTi0Guibg6eMgbxkHgbC6Xr47R6zjwPKKV+aMGpGf0WsyGBKIEDrJGXKeHKIQ
6O04ipwid8TQy8y5Hw5gi2JzHaXqv9eiK1w5HoL9x2ECAwEAAaOCAQkwggEFMB8G
A1UdIwQYMBaAFNHb6YiC5d0aj0yqAIy+fPKrG/bZMB4GCSqBHIahIAQBAwQREw80
NDAxMDEwMDAyMzg4NTkwSAYDVR0gBEEwPzA9BghggRyG7yoBATAxMC8GCCsGAQUF
BwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3VzL3VzLTE0Lmh0bTA3BgNVHR8E
MDAuMCygKqAohiZodHRwOi8vY3JsLmNmY2EuY29tLmNuL1JTQS9jcmwyMzg5LmNy
bDALBgNVHQ8EBAMCA+gwHQYDVR0OBBYEFAhR4S9aru6pskVYEzggUllxjJwwMBMG
A1UdJQQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4IBAQA0ZumHjLnhG3am
2/sT4fw/bMWrTUimNNY1tJ7bs3D0vRh4ZoHrX1fD8W2tsQqmnEOKBylmi3tIBhdb
4lI/AGigq4VUVYRYHGavNi2vVlzQaVFtfUq4bvuydR4EPe6kNkdNNvF2qxoj7KxB
dGMHdgwz4FnLPwy1VY+IRgABzJI1svjKrmWSeSEgX1vGZq/ItE1es2/P1tDJ2CiX
Z8cVqxamH1oshiYlpw1mObyQjUgCftK1kymwa7W37ohpePX0vKxfLkETBNbdqkAV
l+jBayMU7Tu6tLXj1Y/iO/AmsbfFmHAtKTivPd63r16HUxbZTmjMwFpTN8COhakJ
ocbql7dZ
-----END CERTIFICATE-----
";
$public_key= openssl_pkey_get_public($public_key_content);
openssl_public_encrypt(str_pad($public_text, 256, “\0”, STR_PAD_LEFT), $encrypted, $public_key, OPENSSL_NO_PADDING);
echo base64_encode($encrypted);
?>
我的 PYTHON 加密方法
def RSA_encrypt(message):
# message = ‘hello ghost, this is a plian text’
with open(‘ghost-public.pem’,“r”) as f:
key = f.read()
rsakey = RSA.importKey(key) # 导入读取到的公钥
cipher = Cipher_pkcs1_v1_5.new(rsakey) # 生成对象
cipher_text = base64.b64encode(cipher.encrypt(message.encode(encoding=“utf-8”))) # 通过生成的对象加密 message 明文,注意,在 python3 中加密的数据必须是 bytes 类型的数据,不能是 str 类型的数据
return cipher_text
Python中如何实现RSA加密,有PHP源码参考
感觉你俩的明文补全方式不一样,php 是手动补的"\0",python 是 pkcs1 padding
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import base64
# 生成RSA密钥对
def generate_rsa_keys():
key = RSA.generate(2048)
private_key = key.export_key()
public_key = key.publickey().export_key()
return private_key, public_key
# RSA加密
def rsa_encrypt(public_key_str, plaintext):
# 加载公钥
public_key = RSA.import_key(public_key_str)
# 使用PKCS1_OAEP填充方案(推荐)
cipher = PKCS1_OAEP.new(public_key)
# 加密数据
encrypted_data = cipher.encrypt(plaintext.encode('utf-8'))
# 转换为base64方便传输
return base64.b64encode(encrypted_data).decode('utf-8')
# RSA解密
def rsa_decrypt(private_key_str, encrypted_b64):
# 加载私钥
private_key = RSA.import_key(private_key_str)
# 使用PKCS1_OAEP填充方案
cipher = PKCS1_OAEP.new(private_key)
# 解码base64
encrypted_data = base64.b64decode(encrypted_b64)
# 解密数据
decrypted_data = cipher.decrypt(encrypted_data)
return decrypted_data.decode('utf-8')
# 使用示例
if __name__ == "__main__":
# 1. 生成密钥对
private_key, public_key = generate_rsa_keys()
print("公钥:\n", public_key.decode())
print("\n私钥:\n", private_key.decode())
# 2. 加密数据
message = "Hello, RSA Encryption!"
encrypted = rsa_encrypt(public_key, message)
print(f"\n加密后的数据 (base64): {encrypted}")
# 3. 解密数据
decrypted = rsa_decrypt(private_key, encrypted)
print(f"解密后的数据: {decrypted}")
安装依赖:
pip install pycryptodome
核心要点:
- 密钥生成:使用
RSA.generate()生成2048位密钥对 - 填充方案:必须使用
PKCS1_OAEP填充(PHP对应OPENSSL_PKCS1_OAEP_PADDING) - 编码处理:加密后建议用base64编码便于传输
对应PHP代码参考:
// PHP端加密(对应Python的rsa_encrypt)
$publicKey = openssl_pkey_get_public($publicKeyStr);
openssl_public_encrypt($plaintext, $encrypted, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);
$encryptedB64 = base64_encode($encrypted);
// PHP端解密(对应Python的rsa_decrypt)
$privateKey = openssl_pkey_get_private($privateKeyStr);
openssl_private_decrypt(base64_decode($encryptedB64), $decrypted, $privateKey, OPENSSL_PKCS1_OAEP_PADDING);
注意: Python和PHP之间互通时,确保双方使用相同的填充方案和密钥格式。
总结:用pycryptodome库,注意填充方案要和PHP保持一致。
搜索: python rsa no padding
还有, no padding 每次的结果应当是一样的
求一份 Python3 的无填充代码 网上找的代码一运行就报错
NotImplementedError: Use module Crypto.Cipher.PKCS1_OAEP instead
我用的这段代码 ,引用位置和引用文件都已经改过了
author__ = ‘owen’
date = ‘2017-11-22’
import base64
from Crypto.PublicKey import RSA
ENCRYPT_SALT = b’12345678901234567890123456789012345679801234’ # 44 char
RSA_KEY_PATH = ‘./’
class MyRSACrypto:
def cryptor( cls, plain_text ):
# print("\n================ crypto ========================\n")
if( not isinstance( plain_text, bytes ) ):
plain_text = plain_text.encode()
salt = ENCRYPT_SALT
base_dir = RSA_KEY_PATH
with open(base_dir + ‘master-public.pem’) as fp:
public_key = fp.read()
if(not public_key):
return None
rsa_cryptor = RSA.importKey( public_key )
plain_text = ( plain_text + salt )
# 无填充方式公钥加密
cipher_text = rsa_cryptor.encrypt( plain_text, 0 )
pad_cnt = 64 - len(cipher_text[0])
cipher_text_rsa = pad_cnt * b’\0’ + cipher_text[0]
cipher_text_b64 = base64.b64encode( cipher_text_rsa )
return cipher_text_b64.decode()[:-2]
def decryptor( cls, cipher_text_b64 ):
# print("\n================ decrypto ========================\n")
if( not isinstance( cipher_text_b64, bytes ) ):
cipher_text_b64 = cipher_text_b64.encode()
base_dir = RSA_KEY_PATH
with open( base_dir + ‘master-private.pem’ ) as fp:
private_key = fp.read()
if(not private_key):
return None
rsa_decryptor = RSA.importKey( private_key )
cipher_text = base64.b64decode( cipher_text_b64 + b"==" )
# 无填充方式私钥解密
plain_text = rsa_decryptor.decrypt( cipher_text )
return plain_text.decode()[:20]
if name == ‘main’:
text = ‘31’ * 10
cipher_text = MyRSACrypto.cryptor( text )
print(cipher_text)
plain_text = MyRSACrypto.decryptor( cipher_text )
print( plain_text )
谢谢大神 解出来了 !!!


