求教 Python 的 RSA 加密问题有 PHP 源码

2018-09-29 09:39:10 +08:00
 334862132
最近对接第三方接口,有一个地方需要用 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
2796 次点击
所在节点    Python
5 条回复
nongmei
2018-09-29 10:05:27 +08:00
感觉你俩的明文补全方式不一样,php 是手动补的"\0",python 是 pkcs1 padding
334862132
2018-09-29 10:21:20 +08:00
这个是我的初始加密方式 我用\0 在加密对象左侧填充到 245 长度加密出来的结果第三方也解密不了 加密到 256 位的话 RSA 长度不行 至于 RSA 切割加密感觉更不行了, 长度估计都跟对面给出来的长度不一样,RSA 公钥加密最恶心的是每次加密出来的结果都不一样, 除了私钥根本没法验证 更恶心的是我还没有私钥
FanWall
2018-09-29 10:32:29 +08:00
搜索: python rsa no padding

还有, no padding 每次的结果应当是一样的
334862132
2018-09-29 18:25:11 +08:00
@FanWall 求一份 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:

@classmethod
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]


@classmethod
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 )
334862132
2018-09-30 09:40:40 +08:00
@FanWall 谢谢大神 解出来了 !!!!!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/493725

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX