从链中删除根 ca(签名)

Remove root ca from a chain (Signature)

我需要从证书链中删除根 ca。最好的方法是什么?我找到了读取值的方法,但无法删除它们。

你没有说清楚你想要什么,但这里有一个简单的例子来删除所有显示为自签名的证书(相同的颁发者和主题名称 - 最好实际验证签名,随意添加该代码)来自用于传送证书链的特殊 CMS 结构。此代码使用 Bouncycastle PKIX 库,但可以仅使用 Bouncycastle 核心库再多几行代码来完成此操作。

import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.util.CollectionStore;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.function.Predicate;

public class PKCS7Certs {
    private static final String P7_CERT_FILENAME = "stackexchange-com-chain.p7b";
    private static final String OUT_FILENAME = "stackexchange-com-chain-no-root.p7b";

    public static void main(String[] args) throws Exception {
        Path p7In = Paths.get(P7_CERT_FILENAME);
        Path p7Out = Paths.get(OUT_FILENAME);
        removeRoot(p7In, p7Out);
    }

    private static void removeRoot(Path p7In, Path p7Out) throws Exception{
        CMSSignedData contentInfo = new CMSSignedData(Files.newInputStream(p7In));
        Collection<X509CertificateHolder> certs = contentInfo.getCertificates().getMatches(null);

        // Delete the root cert(s)

        certs.removeIf(new Predicate<X509CertificateHolder>() {
            @Override
            public boolean test(X509CertificateHolder cert) {
                return ! cert.getIssuer().equals(cert.getSubject());
            }
        });

        // create a new SignedData ContentInfo with the non-root certs

        CollectionStore newStore = new CollectionStore(certs);
        CMSSignedData newCI = CMSSignedData.replaceCertificatesAndCRLs(
                contentInfo,
                newStore,
                contentInfo.getAttributeCertificates(),
                contentInfo.getCRLs()
        );
        Files.write(p7Out, newCI.getEncoded());
    }
}

从签名中删除根 ca 的其他可能性:

private byte[] removeRoot(byte[] b) throws CMSException, IOException {
CMSSignedData signature = new CMSSignedData(b);
Store<X509CertificateHolder> cs = signature.getCertificates();
Collection<X509CertificateHolder> certificates = cs.getMatches(new Selector<>() {
  @Override
  public boolean match(final X509CertificateHolder obj) {
    return !Objects.equals(obj.getIssuer(), obj.getSubject());
  }

  @Override
  public Object clone() {
    return null;
  }
});

final CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
generator.addSigners(signature.getSignerInfos());
generator.addAttributeCertificates(signature.getAttributeCertificates());
certificates.forEach(o -> {
  try {
    generator.addCertificate(o);
  } catch (CMSException e) {
    throw new RuntimeException(e);
  }
});

CMSSignedData signedData = generator.generate(signature.getSignedContent(), true);
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (ASN1InputStream asn1 = new ASN1InputStream(signedData.getEncoded())) {
  DEROutputStream dos = new DEROutputStream(out);
  dos.writeObject(asn1.readObject());
}

return out.toByteArray();

}