无法解密 Java 服务器在 python 客户端中发送的 blob

Cannot decrypt blob send by Java server in python client

我有以下工作流程。

  1. 使用openssl生成rsa密钥对
  2. Post public java 服务器的密钥
  3. 服务器在内存中构造public键
  4. 服务器使用 public 密钥加密文本并发回 blob
  5. Python 用私钥解密 blob

生成 public/private 密钥对:

openssl genrsa -out privkey.pem 1024 # generate private key

openssl rsa -in privkey.pem -pubout > pubkey.pem # derive public key

openssl pkcs8 -topk8 -in privkey.pem -outform PEM -inform PEM -nocrypt -out   privkey.pkcs8 # convert private key to PKCS8 format

Python代码

import requests
import base64
from Crypto.PublicKey import RSA

privkey_content = open('./keys/privkey.pkcs8', 'rb')
pubkey_content = open('./keys/pubkey.pem', 'rb')
priv_key = RSA.importKey(privkey_content.read())
pub_key = RSA.importKey(pubkey_content.read())
pubkey_der_content = pub_key.exportKey(format='DER')
data = {'key' : base64.b64encode(pubkey_der_content)}
resp = requests.post('http://localhost:9000/crypt/', data=data)
decoded = priv_key.decrypt(base64.b64decode(resp.text))
with open('/tmp/decoded.txt', 'wb') as f:
    f.write(decoded)

Java 服务器代码:

package com.hs.works;

import org.apache.commons.codec.binary.Base64;
import org.eclipse.jetty.http.HttpStatus;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.security.KeyFactory;

import javax.crypto.Cipher;

public class CryptServlet extends HttpServlet {

    byte[] encrypt(byte[] pubKey, String text) {
        try {
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            RSAPublicKey k = (RSAPublicKey) keyFactory.generatePublic(keySpec);
            final Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, k);
            return cipher.doFinal(text.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String key = req.getParameter("key");
        byte[] decoded_bytes = Base64.decodeBase64(key.getBytes());
        byte[] encoded = encrypt(decoded_bytes, "SECRET_TEXT");
        resp.setStatus(HttpStatus.OK_200);
        resp.getWriter().write(new String(Base64.encodeBase64(encoded)));
    }
}

输出:

>>>f = open('/tmp/decoded.txt', 'rb')
>>>c = f.read()
>>> c
'\x02bt\x1bq\xb1\x9bc\xef\xe30Q,o)<\xe8!z3B\xb7\xcf\xecWfN\x0f\x92~q\xb2\xcb\xa7\x15?%\xd1\xbf0$A,\x1ap?bZ$\xca6\xeet \xfc\x8d\x11\xee\n\x1b \xd3\xba\xaf\t\xf4&\x01\xa3\xb9H~\xd5o\x0c\xb3c\xa8\xdd\x9f4*\x86\x92\xe0\xcb\xb4\x1d\xcb\x9889\x856\xf9\xff\x9cGf\xf9\xa4\xc7\xadR\xb5\xcaU\xfc\xd355\xae\x87\x80\x1e\x00SECRET_TEXT'
>>>
>>> c[len(c) - 11:]
'SECRET_TEXT'

在 python 端打印输出时,我在输出中看到 SECRET_TEXT,但也有很多乱码。

我不确定它是否与填充或其他问题有关。

我没有指定正确的密码。

在服务器代码中进行了以下更改:

final Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");

并在 python 客户端代码中进行以下更改:

from Crypto.Cipher import PKCS1_OAEP
rsa_key = RSA.generate(2048)
cipher = PKCS1_OAEP.new(rsa_key)
pubkey = rsa_key.publickey()
data = {'key' : base64.b64encode(pubkey.exportKey(format='DER'))}
resp = requests.post('http://localhost:9000/crypt/', data=data)
decoded = cipher.decrypt(base64.b64decode(resp.text))