I am working on extracting the metadata from jar file. One of the metadata component is the certificate. I have a signed jar file that has *.DSA and *.SC files generated. Is there a way to programmatically create a certificate file from these files in java?
A signed jar should have (for each signature, if more than one)
a signer.SF
(not .SC
) entry which, like the manifest, has some global attributes plus a digest of each jar entry (class, resource, etc) covered by the signature and
a signer.{RSA,DSA,EC}
entry which is a PKCS7 (aka CMS) 'detached' signature. Such a PKCS7/CMS signature can and usually (at least from jarsigner
) does contain the signer's cert chain -- or more exactly the certs making up that chain, since cert chains are normally ordered (certainly they are in a Java keystore) but the certs in a PKCS7/CMS SignedData are defined in ASN.1 as a SET which doesn't preserve order.
'Plain' Java does not expose classes for dealing with PKCS7 (although they exist internally), but if you can use (add) bcprov from https://www.bouncycastle.org it does and you can use code like this to write the certs as DER or PEM files:
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;
...
byte[] sig = // contents of the signer.RSA/DSA/EC entry e.g. using ZipFile
int n = 0; boolean DER = // true or false as desired
for( X509CertificateHolder cert : new CMSSignedData(sig).getCertificates().getMatches(null) ){
byte[] der = cert.getEncoded(); String filename = "cert"+(++n);
if( DER ) Files.write(Paths.get(filename), der);
else try( PemWriter w = new PemWriter(new FileWriter(filename)) ){
w.writeObject( new PemObject("CERTIFICATE",der) );
}
}
Of course instead of writing files, you can do other storage or processing in the loop.