2012-05-03 9 views
5

का उपयोग कर सीएमएस हस्ताक्षर में हस्ताक्षरित/प्रमाणित विशेषताओं को जोड़ें I bouncycastle का उपयोग करके एक साधारण सीएमएस हस्ताक्षर उत्पन्न करना चाहते हैं। यह कोड काम करता है!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(); 

लेकिन, हस्ताक्षरित विशेषताओं को कैसे जोड़ें?
मैं डिफ़ॉल्ट हस्ताक्षरित विशेषताओं को हटाना चाहता हूं और हस्ताक्षर-नीति-पहचानकर्ता जोड़ना चाहता हूं।

लेख बहुत स्वागत है।

उत्तर

7

सबसे पहले आप उन संरचनाओं का उपयोग करने लगते हैं जो बाउंसी कैसल के नवीनतम संस्करणों में बहिष्कृत हैं। प्रमाणीकृत जोड़ने के लिए/पर हस्ताक्षर किए 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 तरीकों में से एक में इसका इस्तेमाल करते हैं। जैसा कि मैंने शुरुआत में पहले से ही उल्लेख किया है, इस विधि को बहिष्कृत किया गया है और आपको जेनरेटर और जेनरेटर बिल्डर्स का उपयोग करने के लिए प्रोत्साहित किया जाता है। यहाँ एक छोटी उदाहरण है:

/* 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 के साथ काम करता है)।

थोड़ा ऑफ ऑफटॉप: मैं अभी भी हस्ताक्षर किए गए और प्रमाणीकृत विशेषताओं के बीच अंतर के चारों ओर अपना सिर नहीं प्राप्त कर सकता हूं, बाउंसी कैसल को डिफ़ॉल्ट प्रमाणीकृत एट्रिब्यूटटेबल जेनरेटर, डिफॉल्टसाइन एट्रिब्यूटटेबल जेनरेटर क्लास दोनों हैं जो साइनर्स के साथ पूरी तरह से काम करते हैं। साइन-टाइम के संबंध में दोनों के बीच कुछ मामूली मतभेद प्रतीत होते हैं, साइन किए गए एट्रिब्यूट्स मौजूद नहीं होने पर डिफ़ॉल्ट रूप से साइन-टाइम जोड़ता है। आरएफसी दोनों विशेषता प्रकारों का जिक्र करते हैं, लेकिन मुझे कुछ भी निश्चित नहीं मिला।

+0

और आप विशेषता 'हस्ताक्षर-नीति-पहचानकर्ता' को कैसे जोड़ते हैं? –

+0

शायद मैन्युअल रूप से, एक CMSAttribute का वारिस करें और इसका उपयोग करें। डंप टूल का उपयोग करके पॉलिसी पहचानकर्ता के लिए एएसएन 1 कोड खोजें। – soulseekah

+0

यह कोड स्निपेट मैं हस्ताक्षर-नीति-पहचानकर्ता को जोड़ने के लिए प्रयोग किया जाता है: गुण नीति = नया गुण ( \t \t \t \t PKCSObjectIdentifiers.id_aa_ets_sigPolicyId, नई DERSet ( \t \t \t \t \t \t sigPolicy)); –

संबंधित मुद्दे