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 · 133 天前 · 1684 次点击
    这是一个创建于 133 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    我实在搜不到了

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

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

    把私钥就加密的 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   133 天前 via iPhone   ❤️ 1
    公钥不也是私钥吗?
    GM
        2
    GM   133 天前   ❤️ 1
    对于一对公钥、私钥:
    公钥加密了,可以用对应的私钥解密。
    私钥加密了,可以用对应的公钥解密。
    ye4tar
        3
    ye4tar   133 天前   ❤️ 1
    记住口诀,公加私解,私加公验
    yuanmomo
        4
    yuanmomo   133 天前 via iPhone   ❤️ 1
    公钥那个不叫解密,叫验证。从知乎看来的~

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

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

    别人用私钥加密,你用公钥能解开 就能证明是他发的内容了。
    xiangyuecn
        9
    xiangyuecn   132 天前
    本质上是没毛病的😂 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   132 天前
    @zonghow 我试试 m2crypto
    chenqh
        11
    chenqh   132 天前
    @zonghow 但是我 centos7 怎么装 `M2Crypto` 呀
    chenqh
        12
    chenqh   132 天前
    @zonghow 关键我还是用的 pyenv 装的 python3, 早知道用 ubuntu 了
    chenqh
        13
    chenqh   132 天前
    大佬们给个 python 私钥加密, 公钥解密的例子把, 我也不想私钥加密,公钥解密的呀, 但是对接就是这个样子呀, 大佬们, 帮帮忙把
    openmm
        14
    openmm   132 天前
    哈哈哈哈 专业点叫私钥签名 公钥验签 虽然原理上也是加解密 但用途上目的不是为了加密 而是为了验证
    chenqh
        15
    chenqh   132 天前
    @openmm 不, 就是公钥解密, 他平台自己保留私钥, 他给我的内容是私钥加密的, 所以我这边需要公钥解密
    ye4tar
        16
    ye4tar   132 天前
    把密文和公钥发来,大伙给你验证下
    chenqh
        17
    chenqh   132 天前
    我左搜右搜,终于找到解密, 现在要搞私钥加密了
    among
        18
    among   129 天前
    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   129 天前
    @among 我用 M2Crypto 实现了, 就是我的 python 需要重装
    among
        20
    among   129 天前
    @chenqh

    问题解决了,是不是也需要贴个 代码出来。。
    chenqh
        21
    chenqh   129 天前
    @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)

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