如何从签名的 jar 文件中创建或提取证书

How do I create or extract the certificate from a signed jar file

我正在努力从 jar 文件中提取元数据。元数据组件之一是证书。我有一个已签名的 jar 文件,其中生成了 *.DSA 和 *.SC 文件。有没有办法以编程方式从 java 中的这些文件创建证书文件?

一个signed jar should have(对于每个签名,如果超过一个)

  • 一个signer.SF(不是.SC)条目,它和清单一样,有一些全局属性加上每个jar条目的摘要(class,资源, 等) 被签名覆盖并且

  • 一个 signer.{RSA,DSA,EC} 条目,它是一个 PKCS7(又名 CMS)'detached' 签名。这样的 PKCS7/CMS 签名可以并且通常(至少从 jarsigner 开始)确实包含签名者的证书 chain —— 或者更准确地说是构成该链的证书,因为证书链通常是有序的(当然它们在 Java 密钥库中)但是 PKCS7/CMS SignedData 中的证书在 ASN.1 中定义为不保留顺序的 SET。

'Plain' Java 不会公开 classes 来处理 PKCS7(尽管它们在内部存在),但是如果您可以使用(添加)来自 https://www.bouncycastle.org 的 bcprov它确实如此,您可以使用这样的代码将证书编写为 DER 或 PEM 文件:

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) );
        }
    }

当然可以不写文件,而是在循环中做其他的存储或者处理。