我正在开发一个带有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和我在谷歌找到的大部分代码部分并对其进行了定制,但我正在研究它。 (仅限私人项目)
答案 0 :(得分:1)
您不应将base 64编码的结果包装成String。
crypted = new String(base64Decoder.decodeBuffer(crypted));
...
byte[] messageBytes = crypted.getBytes();
即使您之前执行base 64解码,String也无法保存随机数据,因为并非所有数据都代表有效的编码字符串。而只是将字节数组分配给一个新变量,例如
byte[] ciphertext = base64Decoder.decodeBuffer(crypted);
并将其用作asymmetricBlockCipher
的输入。