I am trying to use BouncyCastle classes to encrypt and decrypt a password. I have written a test program and generated a test key/cert in PEM format as well as DER format. I can read the key/cert into my program and get the public key and encrypt a value. When I try to setup to decrypt the value I am getting the error "org.bouncycastle.asn1.DLSequence cannot be cast to org.bouncycastle.asn1.ASN1Integer" when creating the AsymmetricKeyParameter. It seems that when I am trying to pull in the data from the cert by doing the cert.getEncoded() it pulls in the header values as well. I tried just reading the file and removing the BEGIN and END CERTIFCATE lines, along with the dashes and that netted me the same error. I have tried used the java.security.cert.Certificate as well as the X509Certificate the code below is using. Any help would be greatly appreciated.
I can upload the key file is that would be helpful to you as it is a test key that I generated on my local machine and will be thrown away once I have this working.
package com.cds.test;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.engines.RSAEngine;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
public class RSAEncryptDecrypt {
public X509Certificate cert = null;
//
public void readCertificate() throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
CertificateFactory factory = CertificateFactory.getInstance("X.509", new BouncyCastleProvider());
InputStream fis = new FileInputStream("/opt/temp/keys/openssl_crt.pem");
X509Certificate x509Cert = (X509Certificate) factory.generateCertificate(fis);
this.cert = x509Cert;
System.out.println("issuer: " + x509Cert.getIssuerX500Principal());
}
//
public String encrypt(String inputData) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
//
System.out.println("public key: " + new String(Base64.encode(cert.getPublicKey().getEncoded())));
AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(cert.getPublicKey().getEncoded());
AsymmetricBlockCipher cipher = new RSAEngine();
cipher = new org.bouncycastle.crypto.encodings.PKCS1Encoding(cipher);
cipher.init(true, publicKey);
//
byte[] messageBytes = inputData.getBytes();
byte[] hexEncodedCipher = cipher.processBlock(messageBytes, 0, messageBytes.length);
//
return new String(Base64.encode(hexEncodedCipher));
}
//
private String decrypt (String encryptedData) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
//
byte[] certData = cert.getEncoded();
//certData = Base64.decode(certData);
AsymmetricKeyParameter privateKey = PrivateKeyFactory.createKey(cert.getEncoded());
AsymmetricBlockCipher cipher = new RSAEngine();
cipher = new org.bouncycastle.crypto.encodings.PKCS1Encoding(cipher);
cipher.init(false, privateKey);
//
byte[] decoded = Base64.decode(encryptedData.getBytes());
byte[] result = cipher.processBlock(decoded, 0, decoded.length);
//
return new String(result);
}
//
public static void main(String[] args) throws Exception {
String inputData = "This is the message I am trying to encrypt.";
String encrypted = null;
String decrypted = null;
//
RSAEncryptDecrypt rsa = new RSAEncryptDecrypt();
//
rsa.readCertificate();
System.out.println(" input: " + inputData);
encrypted = rsa.encrypt(inputData);
System.out.println("encrypted: " + encrypted);
decrypted = rsa.decrypt(encrypted);
System.out.println("decrypted: " + decrypted);
}
}
A certificate only contains the public key, not a private key. Of course the public key has a private key associated to it, but that is not kept in the certificate. The certificate is what you distribute to other parties.
It could be that you have been working with Microsoft code too much. I'm mentioning Microsoft as in .NET code the certificate class can internally contain the associated private key, making for a rather oversimplified API.
So to decrypt you will have to read the private key separately of your certificate (using PKCS8EncodedKeySpec
and an "RSA"
KeyFactory
).
Another option is to put both in a PKCS#12 key store and read it into Java using KeyStore.load
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With