密钥生成 Java、加密 php、解密 Java

Keygeneration Java, Encryption php, Decryption Java

我正在开发一个带有 java 客户端和 php 服务器的软件。 java 客户端生成 2 个 RSA 密钥。 public 密钥通过 post 请求发送到 php 服务器端。服务器使用 public 密钥加密响应并将其发送回 java 客户端。 但是我得到这个错误:

Exception in thread "main" org.bouncycastle.crypto.InvalidCipherTextException: unknown block type
at org.bouncycastle.crypto.encodings.PKCS1Encoding.decodeBlock(Unknown Source)
at org.bouncycastle.crypto.encodings.PKCS1Encoding.processBlock(Unknown Source)

据我通过谷歌搜索,public 和私钥不匹配。 此行出现错误:(应解密响应的位置) byte[] encodedCipher = asymmetricBlockCipher.processBlock(messageBytes, 0, messageBytes.length);

所以事实上,我认为 public 密钥的 Base64 编码或它的传输一定有问题,但我找不到。如果我 echo 服务器上的编码密钥,它与客户端上的编码相同。但是在过去的几个小时里,我没有发现任何关于 base64 加密的有用信息。 对于 java 中的 Base64,我使用这个 2 类: import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder;

我的部分 java 客户:

密钥已生成:(它们被保存为字段)

从这里开始:http://www.mysamplecode.com/2011/08/java-generate-rsa-key-pair-using-bouncy.html

private String publicKey;
private byte[] privateKey;

private void generateKeys() throws NoSuchProviderException, NoSuchAlgorithmException {
    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
    BASE64Encoder base64Encoder = new BASE64Encoder();

    SecureRandom rnd = new FixedRand();
    generator.initialize(2048, rnd);

    KeyPair keyPair = generator.generateKeyPair();
    this.publicKey = base64Encoder.encode(keyPair.getPublic().getEncoded()).replaceAll("(?:\r\n|\n\r|\n|\r)", "").trim();
    this.privateKey = keyPair.getPrivate().getEncoded();
}

Post 请求:(使用 apache http 客户端)

private String readUrl(String urlString, String publicKey) throws Exception {
    HttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost(urlString);

    List<NameValuePair> nameValuePairs = new ArrayList<>(1);
    nameValuePairs.add(new BasicNameValuePair("key", publicKey));
    post.setEntity(new UrlEncodedFormEntity(nameValuePairs));

    HttpResponse response = client.execute(post);

    BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
    String line = "";
    StringBuffer responseString = new StringBuffer();
    while ((line = rd.readLine()) != null) {
        responseString.append(line);
    }
    return responseString.toString();
}

解密部分:

private String decrypt(String crypted) throws IOException, InvalidCipherTextException {
    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

    AsymmetricBlockCipher asymmetricBlockCipher = new RSAEngine();
    asymmetricBlockCipher = new org.bouncycastle.crypto.encodings.PKCS1Encoding(asymmetricBlockCipher);
    BASE64Decoder base64Decoder = new BASE64Decoder();
    crypted = new String(base64Decoder.decodeBuffer(crypted));
    AsymmetricKeyParameter asymmetricKeyParameter = PrivateKeyFactory.createKey(this.javaKeyToBouncycastle(privateKey));
    asymmetricBlockCipher.init(false, asymmetricKeyParameter);

    byte[] messageBytes = crypted.getBytes();
    byte[] encodedCipher = asymmetricBlockCipher.processBlock(messageBytes, 0, messageBytes.length);

    return new String(encodedCipher);
}

private PrivateKeyInfo javaKeyToBouncycastle(byte[] key) throws IOException {
    ASN1InputStream pkstream = new ASN1InputStream(key);
    return PrivateKeyInfo.getInstance(pkstream.readObject());
}

我的 php 服务器的一部分:(使用 phpseclib)

$key = trim(base64_decode($_POST['key'], true));
$rsa = new Crypt_RSA();
$rsa->loadKey($key);
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$crypt = $rsa->encrypt("Hello World");
echo base64_encode($crypt);

谢谢 :-) 不幸的是,我不太了解加密 atm 以及我在 google 中找到并自定义它们的大部分代码部分,但我正在研究它。 (仅限私人项目)

您不应将 base 64 编码的结果包装到字符串中。

crypted = new String(base64Decoder.decodeBuffer(crypted));
...
byte[] messageBytes = crypted.getBytes();

即使您在此之前执行 base 64 解码,字符串也无法保存随机数据,因为并非所有数据都代表有效的编码字符串。而只是将字节数组分配给一个新变量,例如

byte[] ciphertext = base64Decoder.decodeBuffer(crypted);

并将其用作 asymmetricBlockCipher 的输入。