View details of a certificate in Android - java

How to display details of the subject in a certificate (DER format ie .cer file) in java ? eg: email, country, Name or seperate OIDs etc.
Reading a certificate could be done from the above code. Will work in Android as well. Thank you GreyBeardedGeek. But to more elaborate on it (As curious requested), if you display the subject details by using methods getSubjectDN() or cert.getSubjectX500Principal().getname() it will display the whole details. Some may be encoded. I believe it ASN1.(not sure). What I need is to extract only the information I need. For an example please refer the output of the code for a sample certificate I had created. using method - cert.getSubjectX500Principal().getname() Subject Name 2.5.4.5=#130d4e2d61626c652f49542f303130,2.5.4.72=#1308456e67696e656572,2.5.4.41=#13104e7577616e20446520416c6d65696461,1.2.840.113549.1.9.1=#16106e7577616e406e2d61626c652e62697a,OU=Information Technology,O=N-able Pvt Ltd\ ,ST=Western,C=LK
2.5.4.5 is an OID (Object Identifier) which is encoded.
Using method - getSubjectDN()
OID.2.5.4.5=N-able/IT/010, OID.2.5.4.72=Engineer, OID.2.5.4.41=Nuwan De Almeida, OID.1.2.840.113549.1.9.1=#16106E7577616E406E2D61626C652E62697A, OU=Information Technology, O="N-able Pvt Ltd ", ST=Western, C=LK
Here also some information is encoded eg: email address.
So coming back to my question , how can we extract information(not encoded) separately based on the OID. Further if you install the certificate in windows OS you could view the subject information correctly.What I need is a code to get the OID value information passing the OID in java, to extract subject details separately.
Thank you again in advance.

Look into the Bouncy Castle ASN.1 parsing libraries and especially X500Name. It can parse a distinguished name (DN) into its parts (CN, O, etc.).
http://www.bouncycastle.org/docs/docs1.5on/index.html

The following code (no error handling included) will produce an instance of X509Certificate from the .cer file. You can then use that object's methods to inspect the properties of the certificate. The code is generic java, but should work in Android.
X509Certificate cert = null;
FileInputStream fis = null;
ByteArrayInputStream bais = null;
String source = "certificate.cer";
String certType = "X.509"
fis = new FileInputStream(source);
byte[] value = new byte[fis.available()];
fis.read(value);
bais = new ByteArrayInputStream(value);
java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance(certType);
cert = (X509Certificate)cf.generateCertificate(bais);

Related

Is there any way to get the plain text from signed data using private key?

The plain text is signed using java.security.Signature. Below is the code used to sign the plain text
public String getSignature(String plainText) throws Exception
{
KeyStore keyStore = loadKeyStore(); // A local method to read the keystore file from file system.
PrivateKey privateKey = (PrivateKey) keyStore.getKey(KEY_ALIAS_IN_KEYSTORE, KEYSTORE_PASSWORD.toCharArray());
Signature privateSignature = Signature.getInstance(SIGNATUREALGO);
privateSignature.initSign(privateKey);
privateSignature.update(plainText.getBytes("UTF-8"));
byte[] signature = privateSignature.sign();
return String.valueOf(signature);
// KEY_ALIAS_IN_KEYSTORE, KEYSTORE_PASSWORD and SIGNATUREALGO are all constant Strings
}
Note 1: I found online a way to verify the signature using the public key Java Code Examples for java.security.Signature#verify(). But this is not what I require.
Note 2: I also found a ways to encrypt and decrypt as mentioned here RSA Signing and Encryption in Java. But the use case I have in hand is to get the original plain text from a signed data. Is that possible?
No, you can't retrieve the original content from just the signature.
The signature alone does not contain enough information to restore the original clear text, no matter what keys you have access to.
The basic idea of a signature is to send it together with the clear text. That means the clear text will be visible, but the signature can be used to verify that the message was written (or at least signed) by who claims to have done so and has not been tampered with since then.
Signing something is different from encrypting it. The two often uses the same or related technologies and both fall under cryptography.

Java, Exporting public key (X.509, Base64 .cer) from certificate

I'm working on project which collect data from some government portal.
To obtain valid data I had to make request containing some exact xml data.
The xml data had also to contain public key of my certificate. The the portal then encrypts
the returned data. Having private key of the certificate I am then able to decrypt returned data. So far so good, it's working.
But how am I getting the public key of my certificate for the xml? So far manually.
I found the certificate among other personal ones in Chrome browser.
Exported it into file, without private key, X.509, coding Base-64 (CER).
Then opened the exported file in the text editor, removed '-----BEGIN CERTIFICATE-----'
and '----END CERTIFICATE-----''and the rest put into XML
This all I need to repeat by java code (BouncyCastle library ?). I think it will be easy,
but the examples are scarce.
Thanks.
I finally googled the solution, the class JcaPEMWriter (BouncyCastle library) did the trick. Now the output is the same as exported manually.
public static String convertCertificateToPEM(X509Certificate signedCertificate) throws IOException {
StringWriter signedCertificatePEMDataStringWriter = new StringWriter();
JcaPEMWriter pemWriter = new JcaPEMWriter(signedCertificatePEMDataStringWriter);
pemWriter.writeObject(signedCertificate);
pemWriter.close();
return signedCertificatePEMDataStringWriter.toString();
}

Is there a way to decrypt S/MIME public key data?

I would like to get the email address and expire date to a S/MIME certificate based on it's public key. Is this aproach even possible? Or am I totally wrong? Can I decrypt the public key to get these kind of data via java?
I searched in google, read the wiki pages and read about an oracle s/mime project. But it doesn't seam like its possible. Are those data only availabe in the csr??
Thanks in advance
I'm amazed this isn't a dupe, but I couldn't find a good one.
Although Bouncy is fine and has many features if you want to use it, core Java can handle X.509 certificates since forever. For a cert in a file (or anything that can be accessed as a Stream) in either PEM or DER format (although the javadoc isn't clear on that) all you need is CertificateFactory:
CertificateFactory fact = CertificateFactory.getInstance("X.509");
// from a real file
InputStream is = new FileInputStream ("filename");
Certificate cert = fact.generateCertificate(is);
is.close(); // or use try-resources to do automatically
// from an alternate/custom filesystem, such as a ZIP
Path p = Paths.get("somespecification"); // or any other creation of a Path
InputStream is = Files.newInputStream(p); // add open options if needed
// same as before
// from the classpath (usually a JAR)
InputStream is = ClassLoader /*or any Class<?> object*/ .getResourceAsStream("name");
// same as before
// from a byte[] in memory
InputStream is = new ByteArrayInputStream (bytearray);
// same as before, except don't really need to close
// you get the idea
Although JCA APIs like this one are defined to allow a lot of extension, reading an X.509 cert will actually give you not just Certificate but subclass X509Certificate from which .getNotAfter() gives the expiration date-time directly. The email address if present (which isn't required by X.509 certs in general, but should always be the case in a cert used for S/MIME) will usually be an attribute in the subject name, which actually has internal structure that Java doesn't let you get at directly so you need to:
String x500name = ((X509Certificate)cert).getSubjectX500Principal()) .toString();
// simple case: no multivalue RDN, no reserved chars ,+="<>\;# or extra spaces
for( String attr : x500name.split(", ") )
if( attr.startsWith("EMAILADDRESS=") )
... use attr.substring(13) ...
// other cases require slightly more complicated parsing
Note there is no encryption at all in X.509, and thus no actual decryption, although many people use 'decrypt' to describe anything unfamiliar not an actual cipher.
File file = new File(fileName);
FileReader fileReader = new FileReader(file);
PEMParser pemParser = new PEMParser(fileReader);
X509CertificateHolder caCertificate = (X509CertificateHolder) pemParser.readObject();

Generating a PKCS10 Certificate request with extra fields in java

I need to add extra fields in the CSR, like keyusage, regestrationID etc.I am using java IBM-sdk60. I've gone through x500 name API's and could not find any solution. Help on API's would be appreciated.
Thanks in advance
The standard way to include additional information in a CSR (PKCS#10) request is by adding Attributes. According to the PKCS#10 standard:
The intention of including a set of attributes is twofold: to provide
other information about a given entity , or a "challenge password" by
which the entity may later request certificate revocation; and to
provide attributes for inclusion in X.509 certificates. A
non-exhaustive list of attributes is given in PKCS #9
An attribute is an OID and a value whose meaning depends on the OID
Actually PKCS#9 defines 3 attributes:
Challenge password
Extension request
Extended-certificate attributes (this is deprecated)
The one you are looking for is Extension request :
The extensionRequest attribute type may be used to carry information
about certificate extensions the requester wishes to be included in a
certificate.
This code template (not tested) may give you some hints on how include this attribute
CertificateExtensions exts = /* build the extensions set you want to include */
/* Wrap the extensions set into a SET OF */
OutputStream out = new ByteArrayOutputStream();
exts.encode(out);
DerValue val = new DerValue(DerValue.tag_SetOf, out.toByteArray());
PKCSAttribute extReq = new PKCSAttribute(new ObjectIdentifier("1.2.840.113549.1.9.14"), val.toByteArray());
PKCSAttributes attrs = new PKCSAttributes(new PKCSAttribute[] { extReq });
CertificationRequestInfo cri = new CertificationRequestInfo(subject, key, attrs);
CertificationRequest csr = new CertificationRequest(cri);
Please note that unless the CA explicitly announces this PKCS#10 attribute is supported it will be ignored during the certificate generation.

how to generate s3 style access/secret key using java

I am trying to generate access keys and secret keys in the same fashion as S3 using java but am having some trouble.
As a starting point I am looking at this bouncy castle example , I have this code up and running but am not sure of two things 1) how to set it up to use the same key generation as s3 which uses HMAC-SHA1 as outlined here and 2) how to get the friendly public/private key strings out for the the user.
You may have guessed I am new to java encryption and the bouncy castle libraries, however I did find JCEKeyGenerator.HMACSHA1 in the bc docs but am unable to find an example of its use. Any help would be greatly appreciated.
Thanks.
You'll need to make use of javax.crypto.KeyGenerator to create the AWSAccessKeyId and the AWSSecretAccessKey:
javax.crypto.KeyGenerator generator = javax.crypto.KeyGenerator.getInstance("HMACSHA1");
generator.init(120);
byte[] awsAccessKeyId = generator.generateKey().getEncoded();
generator.init(240);
byte[] awsSecretAccessKey = generator.generateKey().getEncoded();
Then, you'll want to base64 encode the bytes (this uses MimeUtility from mail.jar):
final ByteArrayOutputStream encoded = new ByteArrayOutputStream();
final OutputStream encoder = javax.mail.internet.MimeUtility.encode(encoded, "base64");
encoder.write(awsAccessKeyId);
encoder.flush();
encoder.close();
String accessKeyId = new String(encoded.toByteArray(), encoding).replaceAll("[\\r\\n]", "");

Categories