2012-05-03 13 views
5

Quiero generar una firma CMS simple usando bouncycastle. ¡Este código funciona!Agregue atributos firmados/autenticados a la firma CMS usando BouncyCastle

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

¿Pero cómo agregar atributos con signos?
Quiero eliminar los atributos firmados predeterminados y agregar signature-policy-identifier.

Los artículos son muy bienvenidos.

Respuesta

7

En primer lugar parece que está utilizando construcciones que están en desuso en las últimas versiones de Bouncy Castle. Para añadir autenticado/firmado attributes hay que empaquetarlos en un AttributeTable atributos firmados se añaden al firmante de este modo:

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

luego usarlo en uno de los métodos addSigner. Como ya mencioné al principio, este método está en desuso y se le recomienda usar generadores y generadores. He aquí un breve ejemplo:

/* 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(); 

Es bastante voluminosos y, probablemente, no funciona todavía (estoy en el proceso de escribir y topé con su pregunta mientras que la investigación de algunas cosas), especialmente la parte signingDate, probablemente tiene que ser new DERSet(new Time(new Date)) (actualización: funciona con DERUTCTime).

Un poco offtopic: Todavía no entiendo la diferencia entre los atributos Firmado y Autenticado, Bouncy Castle tiene tanto DefaultAuthenticatedAttributeTableGenerator, clases DefaultSignedAttributeTableGenerator que funcionan perfectamente bien con Signers. Parece que hay algunas diferencias menores entre los dos en cuanto a signingTime, SignedAttributes agrega el tiempo de firma de forma predeterminada si no está presente. Los RFC mencionan ambos tipos de atributos, pero no pude encontrar nada definitivo.

+0

¿Y cómo se agrega el atributo 'signature-policy-identifier'? –

+0

Probablemente de forma manual, herede un CMSAttribute y úselo. Averigüe el código ASN1 para identificador de política utilizando herramientas de volcado. – soulseekah

+0

Este es el fragmento de código I utiliza para añadir la firma-política-identificador: Atributo política = new Atributo ( \t \t \t \t PKCSObjectIdentifiers.id_aa_ets_sigPolicyId, nuevo DERSet ( \t \t \t \t \t \t sigPolicy)); –

Cuestiones relacionadas