NullPointerException in BouncyCastleProvider while creating X509Certificate - java

I'm creating X509Certificate from bytes, but that is throwing NullPointerException, In my application I'm doing two way(Step one getting Signature data in Bytes stored into DB, later i fetched from DB), both are consolidate in one shot, Getting exception in last line(System.out.println)
public static void main(String[] args) throws Exception {
File file = new File("C://connect.cer");
InputStream input = new FileInputStream(file);
Security.addProvider(new BouncyCastleProvider());
CertificateFactory certFactory = CertificateFactory.getInstance("X.509", "BC");
X509Certificate cert = (X509Certificate) certFactory.generateCertificate(input);
byte[] certBytes = cert.getSignature();
System.out.println("IssuerDN Name>>>>>>>>>>>>>>"+cert.getIssuerDN().getName()+">>>>>>>>>>>>>>");
InputStream input2 = new ByteArrayInputStream(certBytes);
CertificateFactory certFactory2 = CertificateFactory.getInstance("X.509", "BC");
X509Certificate cert2 = (X509Certificate) certFactory2.generateCertificate(input2);
System.out.println("IssuerDN Name>>>>>>>>>>>>>>"+cert2.getIssuerDN().getName()+">>>>>>>>>>>>>>");
}

Instead of cert.getSignature() i used cert.getEncoded(), It is forking fine.

Related

create PKCS7 with presigned data using bouncy castle

I would like to create a detached signature in a PDF file using a PKCS7 container. The data (hash) is being signed beforehand on a different device with the private key. I want to create a PKCS7 containing the signed data along with the certificate with the public key. I can't seem to create the PKCS7 with bouncy castle without supplying the private key and having the library signing the data. This doesn't seem to work:
InputStream inStream = new FileInputStream("1_public.pem");
BufferedInputStream bis = new BufferedInputStream( inStream );
CertificateFactory cf = CertificateFactory.getInstance("X.509");
List<Certificate> certList = new ArrayList<Certificate>();
Certificate certificate = cf.generateCertificate(bis);
certList.add(certificate);
Store certs = new JcaCertStore(certList);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
gen.addCertificates( certs );
CMSProcessableInputStream msg = new CMSProcessableInputStream( new ByteArrayInputStream( "signedhash".getBytes() ) );
CMSSignedData signedData = gen.generate(msg, false);
byte[] pkcs7 = signedData.getEncoded() ) );
I managed to do this by providing a ContentSigner that doesn't sign, actually quite simple:
InputStream inStream = new FileInputStream("1_public.pem");
BufferedInputStream bis = new BufferedInputStream( inStream );
CertificateFactory cf = CertificateFactory.getInstance("X.509");
List<Certificate> certList = new ArrayList<Certificate>();
Certificate certificate = cf.generateCertificate(bis);
certList.add(certificate);
Store certs = new JcaCertStore(certList);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
gen.addCertificates( certs );
final byte[] signedHash = "signedhash".getBytes();
ContentSigner nonSigner = new ContentSigner() {
#Override
public byte[] getSignature() {
return signedHash;
}
#Override
public OutputStream getOutputStream() {
return new ByteArrayOutputStream();
}
#Override
public AlgorithmIdentifier getAlgorithmIdentifier() {
return new DefaultSignatureAlgorithmIdentifierFinder().find( "SHA256WithRSA" );
}
};
org.bouncycastle.asn1.x509.Certificate cert = org.bouncycastle.asn1.x509.Certificate.getInstance(ASN1Primitive.fromByteArray(certificate.getEncoded()));
JcaSignerInfoGeneratorBuilder sigb = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build());
sigb.setDirectSignature( true );
gen.addSignerInfoGenerator(sigb.build(nonSigner, new X509CertificateHolder(cert)));
CMSProcessableInputStream msg = new CMSProcessableInputStream( new ByteArrayInputStream( "not used".getBytes() ) );
CMSSignedData signedData = gen.generate(msg, false);
byte[] pkcs7 = signedData.getEncoded();
In case the "external signature" is performed by a hardware device it is possible that it also contains "signed attributes". In this case the code must also contain:
AttributeTable signedAttributes = signer.getSignedAttributes();
signerInfoBuilder.setSignedAttributeGenerator(new SimpleAttributeTableGenerator(signedAttributes));
signatureGenerator.addSignerInfoGenerator(signerInfoBuilder.build(nonSigner, signCertificate));
you should also remove the
signatureGenerator.setDirectSignature(true)
a complete example can be found here https://www.len.ro/work/attach-payload-into-detached-pkcs7-signature/. Since I spend a lot of time searching for a solution and this post provided a vital clue I thought I should complete with the information I still missed in an article. Thanks.

Reading certificate error

I am getting the following exception when running my application in a different server. The code works in two different tomcat servers, but on a specific one it doesn't work.
java.lang.NoClassDefFoundError:
org/bouncycastle/asn1/pkcs/PrivateKeyInfo
org.bouncycastle.jcajce.provider.asymmetric.rsa.KeyFactorySpi.engineGeneratePrivate(Unknown
Source) java.security.KeyFactory.generatePrivate(KeyFactory.java:372)
The part of the code when I am getting the error is the following on this line
> pk = kf.generatePrivate(ks);
PrivateKey pk = null;
X509Certificate cert = null;
Security.addProvider(new BouncyCastleProvider());
try{
byte [] key = Base64.decodeBase64(llave.getBytes());
byte [] cer = Base64.decodeBase64(certificado.getBytes());
KeyFactory kf = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(key);
pk = kf.generatePrivate(ks);
pk.getEncoded();
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
InputStream in = new ByteArrayInputStream(cer);
cert = (X509Certificate)certFactory.generateCertificate(in);
DateTime fechaDesde = new DateTime(cert.getNotBefore());
DateTime fechaHasta = new DateTime(cert.getNotAfter());
Does somebody knows why this happens?
java.lang.NoClassDefFoundError This exception is thrown when JVM is unable to find a particular class at runtime which was available during compile time.
This link will help you

How to convert pkcs8 to pkcs12 in Java

I know this is possible with openssl.
But I wonder if there are PKCS converting possibilities(pkcs8 to 12) in Java using any library.
First you read PKCS#8 encoded key as a file and create PrivateKey object
public PrivateKey loadPrivateKey(String keyFile)
throws Exception {
File f = new File(keyFile);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
Then this key is being saved into PKCS#12 key store
public void createKeyStore(String keyStorePwd, String keyStoreFile,
PrivateKey privateKey, X509Certificate certificate)
throws Exception {
char[] pwd = keyStorePwd.toCharArray();
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null, pwd);
KeyStore.ProtectionParameter protParam =
new KeyStore.PasswordProtection(pwd);
Certificate[] certChain =
new Certificate[]{ certificate };
KeyStore.PrivateKeyEntry pkEntry =
new KeyStore.PrivateKeyEntry(privateKey, certChain);
ks.setEntry("keypair", pkEntry, protParam);
FileOutputStream fos = new FileOutputStream(keyStoreFile);
ks.store(fos, pwd);
fos.close();
}

Creating a Key Pair Certificate and Signing It with External CA using BouncyCastle

Here what I have so far generating a Certificate for a User
try {
Security.addProvider(new BouncyCastleProvider()); // adding provider
// to
String pathtoSave = "D://sureshtest.cer";
KeyPair keyPair = generateKeypair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
X509Certificate trustCert = createCertificate(null, "CN=CompanyName",
"CN=Owner", publicKey, privateKey);
java.security.cert.Certificate[] outChain = { trustCert, };
trustCert.checkValidity();
KeyStore outStore = KeyStore.getInstance("PKCS12");
outStore.load(null, null);
outStore.setKeyEntry("my own certificate", privateKey,
"admin123".toCharArray(), outChain);
OutputStream outputStream = new FileOutputStream(pathtoSave);
outStore.store(outputStream, "admin123".toCharArray());
outputStream.flush();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
The above code generate a certificate with a private and public key.
Now I want to sign that certificate with a signing certificate I've been issued by a certificate authority (CA). After that I'll grant that certificate to user.
I got some input from here and it seems that is not the required answer with my case.
No need for a full implementation, just a valid procedure or some hints will greatly help.
You need to generate a CSR so you can invoke the code from Sign CSR using Bouncy Castle which is using the BC API. Add this to your code above:
final PKCS10 request = new PKCS10(publicKey);
final String sigAlgName = "SHA1WithRSA"; // change this to SHA1WithDSA if it's a DSA key
final Signature signature = Signature.getInstance(sigAlgName);
signature.initSign(privateKey);
final X500Name subject = new X500Name(trustCert.getSubjectDN().toString());
final X500Signer signer = new X500Signer(signature, subject);
// Sign the request and base-64 encode it
request.encodeAndSign(signer);
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final PrintStream writer = new PrintStream(baos);
request.print(writer);
// Remove -----BEGIN NEW CERTIFICATE REQUEST----- and -----END NEW CERTIFICATE REQUEST-----
final String requestBase64 = new String(baos.toByteArray());
String withoutTags = requestBase64.substring(41);
withoutTags = withoutTags.substring(0, withoutTags.length() - 39);
// org.bouncycastle.pkcs.PKCS10CertificationRequestHolder
final PKCS10CertificationRequest holder = new PKCS10CertificationRequest(Base64.decode(withoutTags));
// Feed this into https://stackoverflow.com/questions/7230330/sign-csr-using-bouncy-castle

How to access certificate from eToken in java

I want to read certificate from eToken when it plugged-in, when I store that certificate on local machine I can read it through my java application but, I don't know how to read it from eToken.
RSAPublicKey pub;
String fileName = "C:\\myCert.cer";
InputStream inStream = new FileInputStream(fileName);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert =
(X509Certificate)cf.generateCertificate(inStream);
inStream.close();
pub = (RSAPublicKey) cert.getPublicKey();
System.out.println(cert.getIssuerDN());
System.out.println(cert.getSubjectDN());
System.out.println(cert.getSubjectAlternativeNames());
byte [] tempPub = pub.getEncoded();
String sPub = new String( tempPub );
One way to do this is by using the PKCS#11 provider. It comes with examples, too.

Categories

Resources