V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
334862132
V2EX  ›  Python

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

  •  
  •   334862132 · 2018-09-29 09:39:10 +08:00 · 2774 次点击
    这是一个创建于 2249 天前的主题,其中的信息可能已经有所发展或是发生改变。
    最近对接第三方接口,有一个地方需要用 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
    5 条回复    2018-09-30 09:40:40 +08:00
    nongmei
        1
    nongmei  
       2018-09-29 10:05:27 +08:00   ❤️ 1
    感觉你俩的明文补全方式不一样,php 是手动补的"\0",python 是 pkcs1 padding
    334862132
        2
    334862132  
    OP
       2018-09-29 10:21:20 +08:00
    这个是我的初始加密方式 我用\0 在加密对象左侧填充到 245 长度加密出来的结果第三方也解密不了 加密到 256 位的话 RSA 长度不行 至于 RSA 切割加密感觉更不行了, 长度估计都跟对面给出来的长度不一样,RSA 公钥加密最恶心的是每次加密出来的结果都不一样, 除了私钥根本没法验证 更恶心的是我还没有私钥
    FanWall
        3
    FanWall  
       2018-09-29 10:32:29 +08:00   ❤️ 1
    搜索: python rsa no padding

    还有, no padding 每次的结果应当是一样的
    334862132
        4
    334862132  
    OP
       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
        5
    334862132  
    OP
       2018-09-30 09:40:40 +08:00
    @FanWall 谢谢大神 解出来了 !!!!!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3123 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 13:50 · PVG 21:50 · LAX 05:50 · JFK 08:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.