当前位置: 首页 > 面试题库 >

使用BouncyCastle将已签名/已认证的属性添加到CMS签名

呼延震博
2023-03-14
问题内容

我想使用Bouncycastle生成一个简单的CMS签名。此代码有效!

  Security.addProvider(new BouncyCastleProvider());
  String password = "123456";
  KeyStore ks = KeyStore.getInstance("PKCS12");
  ks.load(new FileInputStream("c:/cert_123456.p12"), password.toCharArray());
  String alias = (String)ks.aliases().nextElement();
  PrivateKey key = (PrivateKey)ks.getKey(alias, password.toCharArray());
  Certificate[] chain = ks.getCertificateChain(alias);

  CMSSignedDataGenerator generator = new CMSSignedDataGenerator();

  generator.addSigner(key, (X509Certificate)chain[0], CMSSignedDataGenerator.DIGEST_SHA1);
  ArrayList list = new ArrayList();
  for (int i = 0; i < chain.length; i++) {
       list.add(chain[i]);
  }
  CertStore chainStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(list), "BC");
  generator.addCertificatesAndCRLs(chainStore);
  CMSProcessable content = new CMSProcessableByteArray("test".getBytes());
  CMSSignedData signedData = generator.generate(content, false, "BC");

  byte[] pk = signedData.getEncoded();

但是,如何添加签名属性?
我想删除默认的签名属性并添加signature-policy-identifier。

文章非常受欢迎。


问题答案:

首先,您似乎正在使用最新版本的Bouncy
Castle中不推荐使用的构造。要添加经过身份验证/签名的属性,您必须将它们打包到AttributeTable中,将签名的属性添加到签名者,如下所示:

ASN1EncodableVector signedAttributes = new ASN1EncodableVector();
signedAttributes.add(new Attribute(CMSAttributes.contentType, new DERSet(new ASN1ObjectIdentifier("1.2.840.113549.1.7.1"))));
signedAttributes.add(new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(digestBytes))));
signedAttributes.add(new Attribute(CMSAttributes.signingTime, new DERSet(new DERUTCTime(signingDate))));

AttributeTable signedAttributesTable = new AttributeTable(signedAttributes);

然后在addSigner方法之一中使用它。正如我在开始时已经提到的那样,不建议使用此方法,建议您使用Generators和Generator
Builders。这是一个简短的示例:

    /* Construct signed attributes */
    ASN1EncodableVector signedAttributes = new ASN1EncodableVector();
    signedAttributes.add(new Attribute(CMSAttributes.contentType, new DERSet(new ASN1ObjectIdentifier("1.2.840.113549.1.7.1"))));
    signedAttributes.add(new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(digestBytes))));
    signedAttributes.add(new Attribute(CMSAttributes.signingTime, new DERSet(new DERUTCTime(signingDate))));

    AttributeTable signedAttributesTable = new AttributeTable(signedAttributes);
    signedAttributesTable.toASN1EncodableVector();
    DefaultSignedAttributeTableGenerator signedAttributeGenerator = new DefaultSignedAttributeTableGenerator(signedAttributesTable);

    /* Build the SignerInfo generator builder, that will build the generator... that will generate the SignerInformation... */
    SignerInfoGeneratorBuilder signerInfoBuilder = new SignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build());
    signerInfoBuilder.setSignedAttributeGenerator(signedAttributeGenerator);
    CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
    JcaContentSignerBuilder contentSigner = new JcaContentSignerBuilder("SHA1withRSA");
    contentSigner.setProvider("BC");

    generator.addSignerInfoGenerator(signerInfoBuilder.build(contentSigner.build(this.signingKey), new X509CertificateHolder(this.signingCert.getEncoded())));

    ArrayList<X509CertificateHolder> signingChainHolder = new ArrayList<X509CertificateHolder>();
    Iterator i = this.signingChain.iterator();
    while (i.hasNext()) {
        X509CertificateObject cert = (X509CertificateObject)i.next();
        signingChainHolder.add(new X509CertificateHolder(cert.getEncoded()));
    }

    generator.addCertificates(new JcaCertStore(signingChainHolder));
    generator.generate(new CMSAbsentContent(), "BC").getEncoded();

它非常笨重,可能还无法正常工作(我正在编写过程中,在研究某些东西时偶然发现了您的问题),尤其是signingDate部分,它可能必须是new DERSet(new Time(new Date))(update:它可以使用DERUTCTime)。

有点离题:我仍然无法理解Signed和Authenticated属性之间的区别,Bouncy
Castle拥有DefaultAuthenticatedAttributeTableGenerator和DefaultSignedAttributeTableGenerator类,它们与Signers完美配合。两者之间在signingTime方面似乎有一些细微的差异,如果不存在,SignedAttributes默认会添加signingTime。RFC提到了两种属性类型,但是我找不到任何确定的东西。



 类似资料:
  • 我想使用BouncyCastle生成一个简单的CMS签名。这代码管用! 但是,如何添加签名属性呢? 我要删除默认签名属性并添加签名策略标识符。 文章非常欢迎。

  • 是否可以在签名的PDF中添加附加页面并在不破坏第一个签名的情况下再次签名。 我在adobe留档中读到增量更新,这可能是可能的。 然而,我不确定这是否适用于所有内容,还是仅适用于注释(注释)、表单填写和数字签名。 我试图通过在Java中使用Apache PDFBox来做到这一点,对文档进行签名,然后加载文档,将页面附加到文档中,使用saveIncremental()保存文档,然后再次签名。 但是,第

  • 我检查了这个关于正确签名数据的问题,但它没有响应我的SCEP服务器的需求。我使用的代码来自EJBCA,但似乎没有向PKCS7签名数据添加证书。 当我使用工具解析签名数据时,我看到“证书”字段是“空的”。此外,当我尝试使用,我一无所获。 以下是我如何用Bouncy Castle签署我的数据(代码很多,但足以重现问题):

  • 我应该如何更改A方法?任何想法都是好的。提前谢谢。

  • 问题内容: 我正在使用和 (Bouncycastle库) 签署,然后验证。 这是我签署的: 现在,输出将在这一过程中使用的: 一切正常,直到由于以下原因: 有人可以给我提示可能发生的事情吗? PS 。如果有人要进行上述测试,则将需要我用来复制此文件的测试文件,只需从这里开始即可: https://www.dropbox.com/s/zs4jo1a86v8qamw/certificates.p12?