2012-05-03 16 views
5

Chcę wygenerować prosty podpis CMS za pomocą bouncycastle. Ten kod działa!Dodaj podpisane/uwierzytelnione atrybuty do podpisu CMS za pomocą 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(); 

Ale jak dodać atrybuty podpisane?
Chcę usunąć domyślne atrybuty podpisane i dodać identyfikator strategii podpisu.

Artykuły są bardzo mile widziane.

Odpowiedz

7

Po pierwsze wydaje się, że używasz konstruktów, które są przestarzałe w najnowszych wersjach Bouncy Castle. Aby dodać uwierzytelnione/podpisana attributes trzeba je pakietu w AttributeTable Podpisano atrybutami są dodawane do podpisującego tak:

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

następnie używać go w jednej z metod addSigner. Jak już wspomniałem na początku, ta metoda jest przestarzała i zachęcamy do korzystania z Generatorów i Generatorów Generatorów. Oto krótki przykład:

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

To dość nieporęczne i chyba jeszcze nie działa (jestem w trakcie pisania i natknęliśmy się na swoje pytanie podczas badania kilka rzeczy), w szczególności część signingDate, to prawdopodobnie musi być new DERSet(new Time(new Date)) (aktualizacja: działa z DERUTCTime).

Trochę offtopic: wciąż nie mogę zrozumieć różnicy między atrybutami Signed i Authenticated, Bouncy Castle ma klasy DefaultAuthenticatedAttributeTableGenerator, DefaultSignedAttributeTableGenerator, które doskonale działają z Signers. Wydaje się, że pomiędzy tymi dwoma elementami występują niewielkie różnice pod względem czasu logowania, opcja Podpisane atrybuty domyślnie dodaje wartość czasu do podpisu, jeśli nie jest obecna. W dokumentach RFC wymieniono oba typy atrybutów, ale nie mogłem znaleźć niczego konkretnego.

+0

A jak dodać atrybut "identyfikator polityki podpisu"? –

+0

Prawdopodobnie ręcznie, dziedziczy CMSAttribute i używa go. Znajdź kod ASN1 dla identyfikatora polityki za pomocą narzędzi dump. – soulseekah

+0

Jest to fragment kodu użyłem, aby dodać podpis-policy-identyfikator: Attribute polityki = nowy atrybut ( \t \t \t \t PKCSObjectIdentifiers.id_aa_ets_sigPolicyId, nowy DERSet ( \t \t \t \t \t \t sigPolicy)); –

Powiązane problemy