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

时间:2015-10-23 22:41:31

标签: java php rsa bouncycastle phpseclib

我正在开发一个带有java客户端和php服务器的软件。 java客户端生成2个RSA密钥。公钥通过post请求发送到php服务器端。服务器使用公钥加密响应并将其发送回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)

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

事实上,我认为公钥的Base64编码或传输的问题一定存在问题,但我无法找到。如果我echo服务器上的编码密钥,则它与客户端上编码的密钥相同。但是在过去的几个小时里,我还没有发现有关base64加密的任何有用信息。 对于java中的Base64,我使用这两个类: 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和我在谷歌找到的大部分代码部分并对其进行了定制,但我正在研究它。 (仅限私人项目)

1 个答案:

答案 0 :(得分:1)

您不应将base 64编码的结果包装成String。

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

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

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

并将其用作asymmetricBlockCipher的输入。