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
chenqh
V2EX  ›  Python

今天碰到一个对接 Java rsa pkcs1 用公钥解密,

  •  
  •   chenqh · 351 天前 · 2099 次点击
    这是一个创建于 351 天前的主题,其中的信息可能已经有所发展或是发生改变。

    python 我搜了好久,都是用私钥解密的, 论坛里的大佬有给个资料的吗?

    我实在搜不到了

    第 1 条附言  ·  349 天前
    私钥加密卡死了

    私钥加密的东西, 用公钥解密不出来

    把私钥就加密的 base64, 放网上也解密不出来

    代码::

    ```


    def util_rsa_encrypt_by_privatekey(private_key_str, raw_message, block_size=117):
    """
    Args:
    private_key_str: 没有'---'的密钥, 可以是多行
    raw_message: 应该是 byte
    Returns:
    (str): base64 之后的结果
    """
    assert isinstance(raw_message, bytes)
    private_key_str = "".join(private_key_str.splitlines())
    private_key_str = handle_pri_key(private_key_str)
    priv_key = rsa.PrivateKey._load_pkcs1_pem(private_key_str)
    keylength = common.byte_size(priv_key.n)

    block_list = []
    raw_message_len = len(raw_message)
    for i in range(0, raw_message_len, block_size):
    message = raw_message[i:i + block_size]
    padded = _pad_for_encryption(message, keylength)

    payload = transform.bytes2int(padded)
    encrypted = core.encrypt_int(payload, priv_key.d, priv_key.n)
    block = transform.int2bytes(encrypted, keylength)
    block_list.append(block)
    byte_str = b''.join(block_list)
    b64_str = base64.b64encode(byte_str).decode("utf-8")
    return b64_str
    ```

    求指点
    21 条回复    2021-06-15 20:33:11 +08:00
    zvcs
        1
    zvcs  
       351 天前 via iPhone   ❤️ 1
    公钥不也是私钥吗?
    GM
        2
    GM  
       351 天前   ❤️ 1
    对于一对公钥、私钥:
    公钥加密了,可以用对应的私钥解密。
    私钥加密了,可以用对应的公钥解密。
    ye4tar
        3
    ye4tar  
       351 天前   ❤️ 1
    记住口诀,公加私解,私加公验
    yuanmomo
        4
    yuanmomo  
       351 天前 via iPhone   ❤️ 1
    公钥那个不叫解密,叫验证。从知乎看来的~

    加密的时候,肯定不希望别人能看到解密过后的内容,所以就只能用私钥解密,对应就是公钥加密。

    反过来,当有个东西我希望别人能验证就是属于我这个私钥,而不是别人的私钥那就是私钥签名,公钥验证
    godblessumilk
        5
    godblessumilk  
       351 天前 via Android   ❤️ 1
    理论上无论公钥加密还是私钥加密都是可以的,只是用私钥加密,能作简单的身份认证(用私钥加密明文,生成数字签名)
    chenqh
        6
    chenqh  
    OP
       351 天前
    @yuanmomo 但是我用 python 搞不了呀, 因为我对接的 java, 他用私钥加密的, 所以我用公钥解密, 但是试了好久都不行呀,
    求指点
    zonghow
        7
    zonghow  
       351 天前 via iPhone
    M2Crypto 可以 关键 api:public_decrypt
    liuidetmks
        8
    liuidetmks  
       350 天前 via iPhone
    rsa 的话,公钥解密叫签名验证。

    别人用私钥加密,你用公钥能解开 就能证明是他发的内容了。
    xiangyuecn
        9
    xiangyuecn  
       350 天前
    本质上是没毛病的😂 N E D 三个数,NE 、ND 随便哪个做公钥,另外一个就是私钥

    不过有一个问题,比较标准的密钥生成工具,指定了 N 后,E 一般给的就是 AQAB=65537,据说是因为这个数加密更快。然后,这样的固定的 E 只能是做公钥😂

    附我几年前写的从 pem 中提取 N 、E 、D 的代码(纯字节码解析):

    C#: https://github.com/xiangyuecn/RSA-csharp

    Java: https://github.com/xiangyuecn/RSA-java

    Python: - 🤷‍♂️
    chenqh
        10
    chenqh  
    OP
       350 天前
    @zonghow 我试试 m2crypto
    chenqh
        11
    chenqh  
    OP
       350 天前
    @zonghow 但是我 centos7 怎么装 `M2Crypto` 呀
    chenqh
        12
    chenqh  
    OP
       350 天前
    @zonghow 关键我还是用的 pyenv 装的 python3, 早知道用 ubuntu 了
    chenqh
        13
    chenqh  
    OP
       350 天前
    大佬们给个 python 私钥加密, 公钥解密的例子把, 我也不想私钥加密,公钥解密的呀, 但是对接就是这个样子呀, 大佬们, 帮帮忙把
    openmm
        14
    openmm  
       350 天前
    哈哈哈哈 专业点叫私钥签名 公钥验签 虽然原理上也是加解密 但用途上目的不是为了加密 而是为了验证
    chenqh
        15
    chenqh  
    OP
       350 天前
    @openmm 不, 就是公钥解密, 他平台自己保留私钥, 他给我的内容是私钥加密的, 所以我这边需要公钥解密
    ye4tar
        16
    ye4tar  
       350 天前
    把密文和公钥发来,大伙给你验证下
    chenqh
        17
    chenqh  
    OP
       350 天前
    我左搜右搜,终于找到解密, 现在要搞私钥加密了
    among
        18
    among  
       347 天前
    class MyRsa():
    def __init__(self, pri_key_file, pub_key_file):
    with open(pri_key_file, mode='rb') as privatefile:
    private_keydata = privatefile.read()
    self.privkey = rsa.PrivateKey.load_pkcs1(private_keydata)
    with open(pub_key_file, mode='rb') as publicfile:
    public_keydata = publicfile.read()
    self.pubkey = rsa.PublicKey.load_pkcs1(public_keydata)

    def encrypt_b64(self, msg):
    crypto_text = rsa.sign(msg.encode('utf8'), self.privkey, 'SHA-1')
    res = base64.b64encode(crypto_text)
    res = res.decode()
    logz.info(msg)
    # logz.info(self.privkey)
    logz.info(res)
    return res



    rsa1 = MyRsa(pri_key_file=pri_key_file, pub_key_file=pub_key_file)
    signature = rsa1.encrypt_b64(sign_str)
    print(signature)


    试试,拷贝了一段。
    chenqh
        19
    chenqh  
    OP
       347 天前
    @among 我用 M2Crypto 实现了, 就是我的 python 需要重装
    among
        20
    among  
       347 天前
    @chenqh

    问题解决了,是不是也需要贴个 代码出来。。
    chenqh
        21
    chenqh  
    OP
       347 天前
    @among


    ```
    import M2Crypto
    from tornado import escape
    import base64
    """
    sudo yum install -y python3-devel openssl-devel swig
    pip install M2Crypto
    """

    def handle_key_inner(key, start, end):
    result = ''
    # 分割 key,每 64 位长度换一行
    divide = int(len(key) / 64)
    divide = divide if (divide > 0) else divide + 1
    line = divide if (len(key) % 64 == 0) else divide + 1
    for i in range(line):
    result += key[i * 64:(i + 1) * 64] + '\n'
    result = start + result + end
    return result


    def handle_pub_key(key):
    """
    处理公钥
    公钥格式 pem,处理成以-----BEGIN PUBLIC KEY-----开头,-----END PUBLIC KEY-----结尾的格式
    :param key:pem 格式的公钥,无-----BEGIN PUBLIC KEY-----开头,-----END PUBLIC KEY-----结尾
    :return:
    """
    start = '-----BEGIN PUBLIC KEY-----\n'
    end = '-----END PUBLIC KEY-----'
    return handle_key_inner(key, start, end)


    def handle_pri_key(key):
    start = '-----BEGIN PRIVATE KEY-----\n'
    end = '-----END PRIVATE KEY-----'
    return handle_key_inner(key, start, end)


    def util_rsa_encrypt_with_private_key_str(msg: bytes, private_key_str: str, blocksize=117):
    private_key_str = "".join([e.strip() for e in private_key_str.splitlines()])
    private_key_str = handle_pri_key(private_key_str)
    bio = M2Crypto.BIO.MemoryBuffer(private_key_str.encode("utf-8"))
    rsa_pri = M2Crypto.RSA.load_key_bio(bio)
    out_li = []
    len_msg = len(msg)
    for i in range(0, len_msg, blocksize):
    piece = msg[i:i + blocksize]
    ctxt_pri = rsa_pri.private_encrypt(piece, M2Crypto.RSA.pkcs1_padding) # 这里的方法选择加密填充方式,所以在解密的时候 要对应。
    out_li.append(ctxt_pri)
    raw_msg = b''.join(out_li)
    return base64.b64encode(raw_msg)


    def pub_decrypt_with_pubkeyfile(msg, file_name):
    rsa_pub = M2Crypto.RSA.load_pub_key(file_name)
    pub_decrypt(msg, rsa_pub)


    def util_rsa_decrypt_with_public_key_str(msg, pub_key: str):
    """
    Args:
    msg: base64 string
    """
    pub_key = "".join([e.strip() for e in pub_key.splitlines()])
    pub_key = handle_pub_key(pub_key)
    msg = escape.utf8(msg)
    bio = M2Crypto.BIO.MemoryBuffer(pub_key.encode("utf-8"))
    rsa_pub = M2Crypto.RSA.load_pub_key_bio(bio)
    return pub_decrypt(msg, rsa_pub)


    def pub_decrypt(msg, rsa_pub, block_size=128):

    ctxt_pri = base64.b64decode(msg) # 先将 str 转成 base64
    # maxlength = 128
    li = []
    len_ctxt = len(ctxt_pri)
    for i in range(0, len_ctxt, block_size):
    input = ctxt_pri[i:i + block_size]
    out = rsa_pub.public_decrypt(input, M2Crypto.RSA.pkcs1_padding) # 解密
    li.append(out)
    return b''.join(li)

    ```
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1087 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 22:55 · PVG 06:55 · LAX 15:55 · JFK 18:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.