2012-05-03 79 views
5

我想使用bouncycastle生成簡單的CMS簽名。 此代碼有效!使用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(); 

但是,如何添加簽名屬性?
我想刪除默認的簽名屬性並添加簽名策略標識符。

文章非常受歡迎。

回答

7

首先,您似乎正在使用在最新版本的Bouncy Castle中棄用的構造。添加認證/簽名的attributes你必須將它們打包成一個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))(更新:它與DERUTCTime一起使用)。一點偏移:我仍然無法理解簽名和認證屬性之間的差異,Bouncy Castle已經獲得了與簽署者完美協作的DefaultAuthenticatedAttributeTableGenerator,DefaultSignedAttributeTableGenerator類。這兩者在簽名時間方面似乎存在一些細微差異,如果不存在,SignedAttributes默認添加簽名時間。 RFC提到了兩種屬性類型,但我找不到任何明確的內容。

+0

如何添加屬性'簽名策略標識符'? –

+0

可能手動,繼承CMSAttribute並使用它。使用轉儲工具查找策略標識符的ASN1代碼。 – soulseekah

+0

這是代碼片段我用於添加簽名策略的標識符:屬性策略=新屬性( \t \t \t \t PKCSObjectIdentifiers.id_aa_ets_sigPolicyId,新DERSet( \t \t \t \t \t \t sigPolicy)); –

相關問題