无法从 CMSSigned 数据中获取 SignerCertificate

Unable to get SignerCertificate from CMSSigned data

尝试从 CMS 签名数据中提取 SignerCertificate (X509) 时,我的代码出现错误,未找到证书。为此,我正在使用 bouncycastle 库。

我想我无法签名properly.The附上代码片段,请看一下并纠正我哪里错了。

这是我的签名代码

        byte[] tokenBytes = TokenUtils.encode( token );
        CMSProcessableByteArray cmsBytes = new CMSProcessableByteArray( tokenBytes ); 

        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        List certList = new ArrayList();

        certList.add(certificate);
        Security.addProvider(new BouncyCastleProvider());
        ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(privateKey);
        gen.addSignerInfoGenerator(
                new JcaSignerInfoGeneratorBuilder(
                     new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
                     .build(sha1Signer, certificate));

       signedData = gen.generate(cmsBytes, true);

这是我验证签名的方式

public boolean verifySignature( X509Certificate certificate ) throws TokenException {
     Iterator i = signedData.getSignerInfos().getSigners().iterator();
    while ( i.hasNext() ) {

        SignerInformation s = (SignerInformation) i.next();


        try {
            if ( s.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(certificate)))
                return true;
        } catch ( Exception e ) {
            logger.error( "Error verifying signature.", e );
            throw new TokenException( "Error verifying token signature.", e );
        }
    }
    return false;
}

以及获取签名者证书的方法

 public X509Certificate getSignerCertificate() throws TokenException    {        
    if ( signedData == null )
        throw new TokenException( "No one has signed this token yet!" );

    try {
        //CertStore certStore = signedData.getCertificatesAndCRLs( "Collection", "SUN" );
        CertStore certStore = signedData.getCertificatesAndCRLs( "Collection", "SUN" );

        SignerInformationStore sis = signedData.getSignerInfos();
        Collection c = sis.getSigners();

        if ( c.size() != 1 )
            throw new TokenException( "Expected one signature, found " + c.size() );

        Iterator i = c.iterator();
        SignerInformation s = (SignerInformation) i.next();
        Collection certs = certStore.getCertificates( s.getSID() );
        if ( certs.size() != 1 )
            throw new TokenException( "Expected one certificate, found " + certs.size() );
        return (X509Certificate) certs.iterator().next();

    } catch ( CMSException cmse ) {
        throw new TokenException( "Error extracting CertStore from token.", cmse );
    } catch ( GeneralSecurityException gse ) {
        throw new TokenException( "Provider error extracting certs.", gse );
    } 
}

您没有将证书添加到签名数据结构中,这可能就是您获得 signerInformation 但未使用 Collection certs = certStore.getCertificates( s.getSID() ); 获得证书的原因。要解决此问题,请使用 addCertificates() method:

将证书添加到您的 CMSSignedData
gen.addSignerInfoGenerator(
            new JcaSignerInfoGeneratorBuilder(
                 new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
                 .build(sha1Signer, certificate));

// use this to add the certificates to your signature
gen.addCertificates(certs);

signedData = gen.generate(cmsBytes, true);

希望这对您有所帮助,