How to convert generated x509certificate to Hex in Java - java

I generate a x509certificate with Java, but I need to convert this x509certificate to Hex.
X509Certificate generateX509Certificate() throws Exception
{
X509CertificateStructure x509CertificateStructure = generateX509CertificateHolder().toASN1Structure();
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
InputStream is1 = new ByteArrayInputStream(x509CertificateStructure.getEncoded());
X509Certificate x509Certificate = (X509Certificate)certificateFactory.generateCertificate(is1);
return x509Certificate;
other alternative is the byte[] but I don't know how to convert it to hex.
Thank you for your answers

I found the solution
byte[] hex = x509Certificate.getEncoded();
System.out.println("--------------------------------------");
String hexText = DatatypeConverter.printHexBinary(hex);
System.out.println(hexText);

Related

Java get subject key identifier from certificate X509Certificate

I have p7b-file with some certificate inside, I open it in Java and get Subject with this code:
try (InputStream inputStream = new FileInputStream("D:\\test.p7b")) {
final CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
certificateFactory.generateCertificates(inputStream).forEach(certificate -> {
final X509Certificate x509Certificate = (X509Certificate) certificate;
System.out.println("subjectDN: " + x509Certificate.getSubjectDN().getName());
System.out.println("__" + x509Certificate.getExtensionValue("2.5.29.14").hashCode() );
System.out.println("*************************");
});
}
It's work fine, but I need to get Subject Key Identifier like this:
and it must be only on free Java without bouncycastle or any other framework. Please help, how to do it? Thanks!

Got java.security.InvalidKeyException: IOException: ObjectIdentifier() -- data isn't an object ID (tag = -96)

Note: String cert is sent over REST API as a HashMap, Not sure what is wrong here.
HashMap<String, Object> extraParams = //API brings this HashMap here.
String cert = (String) extraParams.get("certificate");
cert = cert.replaceAll("-----BEGIN CERTIFICATE-----", "").
replaceAll("-----END CERTIFICATE-----", "").replaceAll("\r", "").replaceAll("\n", "");
byte[] decodedBytes = Base64.decodeBase64(cert.getBytes("UTF-8"));
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(decodedBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pk = kf.generatePublic(publicKeySpec);
My Certificate String from originated Server and what I received over API is same but still getting this error not sure why?
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: ObjectIdentifier() -- data isn't an object ID (tag = -96)
As I mentioned in the question itself that my String Cert have traveled over REST HTTP, I was suspecting that UTF-8 encoding might be an issue. That's what I was missing. Below code worked like charm for me. partially copied from https://stackoverflow.com/a/34549537/1665592
String cert = "...";
byte[] encodedCert = cert.getBytes("UTF-8");
byte[] decodedCert = Base64.decodeBase64(encodedCert);
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
InputStream in = new ByteArrayInputStream(decodedCert);
X509Certificate certificate = (X509Certificate)certFactory.generateCertificate(in);
PublicKey publicKey = ((RSAPublicKey)certificate.getPublicKey());

Nested PKCS7 in BouncyCastle

I would like to encapsulate SignedData in EnvelopedData.
I am using BouncyCastle.
After looking in an example, I wrote something like this:
CMSSignedData signedData = gen.generate(new CMSProcessableByteArray(out.toByteArray()), true);
FileInputStream inputStream = new FileInputStream(args[3]);
CertificateFactory factory = CertificateFactory.getInstance("X.509", "BC");
X509Certificate certificate = (X509Certificate) factory.generateCertificate(inputStream);
CMSEnvelopedDataGenerator engen = new CMSEnvelopedDataGenerator();
engen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(certificate).setProvider("BC"));
CMSEnvelopedData envelopedData =engen.generate( new CMSProcessableByteArray(signedData.getEncoded()),
new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES256_CBC).setProvider("BC").build());
But I think this is wrong. Where can I specify the ContentType of ContentInfo? I need to specify the content type of EnvelopedData as SignedData, but it's not possible with the CMSSignedData class.

Creating a .p12 file with a KeyStore

I have an external service that creates certificate for me, out of which I recieve a buffer (String). I attempt to load this buffer into a KeyStore in Java and then use the "store" function in order to create a .p12 file. However, the store function throws an exception - "Given final block not properly padded".
No matter what I try, I cannot get this to work or find the cause of the issue.
My code is :
public void createP12Certificate(String userName, String comment) throws KeyStoreException, AdminCertificateException, CertificateException, NoSuchAlgorithmException, IOException
{
KeyStore store = KeyStore.getInstance("PKCS12");
/* Some Code that gets 'buff' etc. */
byte[] byteBuff = hexStringToByteArray(buff);
Arrays.reverse(byteBuff);
InputStream inputStream = new ByteArrayInputStream(byteBuff);
store.load(inputStream, password.toCharArray());
OutputStream outputStream = new FileOutputStream(userName+".p12");
store.store(outputStream,anotherPassword); //Throws Exception
}
Thank you very much!
The issue is at those lines
/* Some Code that gets 'buff' etc. */
byte[] byteBuff = hexStringToByteArray(buff);
Because the other posted code would work without an exception.
char[] passwordChars = "password".toCharArray();
String fileOne = "/tmp/output_1.p12";
String fileTwo = "/tmp/output_2.p12";
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(null, null);
keyStore.store(new FileOutputStream(fileOne), passwordChars);
keyStore = KeyStore.getInstance("PKCS12");
byte[] byteBuff = Files.readAllBytes(Paths.get(fileOne));
InputStream inputStream = new ByteArrayInputStream(byteBuff);
keyStore.load(inputStream, passwordChars);
keyStore.store(new FileOutputStream(fileTwo), passwordChars);

Generate X509Certificate from byte[]?

Is there a possibility to generate an java.security.cert.X509Certificate from an byte[]?
Sure.
The certificate objects can be created by an instance of CertificateFactory - in particular, one configured to create X509 certificates. This can be created like so:
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
Then you need to pass it an InputStream containing the bytes of the certificate. This can be achieved by wrapping your byte array in a ByteArrayInputStream:
InputStream in = new ByteArrayInputStream(bytes);
X509Certificate cert = (X509Certificate)certFactory.generateCertificate(in);
You can do something like:
X509Certificate certificate = signature.getKeyInfo().getX509Datas().get(0).getX509Certificates().get(0);
String lexicalXSDBase64Binary = certificate.getValue();
byte[] decoded = DatatypeConverter.parseBase64Binary(lexicalXSDBase64Binary);
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(decoded));
InputStream stream = null;
byte[] bencoded = javax.xml.bind.DatatypeConverter.parseBase64Binary(x509CertificateStr);
try {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
cert = (X509Certificate) certFactory.generateCertificate(stream);
} catch (java.security.cert.CertificateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Categories