You can PROBABLY achieve this by creating a subclass of DataHandler and 
overriding the writeTo.... method.   Something like:

final DeferredDocumentImpl signedDoc 
      = new XmlSign().createSignedDocument(new FileInputStream("a_file.xml"));
DataHandler dh = new DataHandler(signedDoc, "text/xml") {
   public void writeTo(OutputStream out) {
         TransformerFactory tf = TransformerFactory.newInstance();
         Transformer trans = tf.newTransformer();
         trans.transform(new DOMSource(signedDoc ), new StreamResult(out));
   }
}


That said, that could be made automatic, I think.  You don't say where the 
WebServiceRequest object comes from.  Is that generated from WSDL?    I think 
if you add xmime:expectedContentTypes="text/xml" to the element that defines 
the base64binary data, the code generator would then generate it as a Document 
instead of a DataHandler.    Thus, you could just set the document in and be 
done.

Dan



On Thu November 26 2009 7:39:32 am emilSverige wrote:
> Hi, I want to sign an MTOM attachment only, not the soap message. I am
>  aware that the WSS4J-interceptor doesn't sign the attachment, so I'm
>  trying to do it in plain java instead.
> 
> Please note that the soap message should be unsigned, only the attachment
> should be signed.
> 
> So far I have managed to sign an attachment and save it to disk, then read
> it and send with cxf. No problem, but I would like to get rid of the "save
> to disk" part since it seems unnecessary.
> 
> Unfortunately though, I don't know how to. I have no idea how a Datahandler
> can handle a  DeferredDocumentImpl. Any help is appreciated!
> 
> This is the code that signs, saves to disk, reads from disk and prepares
>  the request:
> 
> /**
>  * @param fileInputStream The data to sign
>  * @return A signed document
>  */
> DeferredDocumentImpl createSignedDocument(FileInputStream fileInputStream){
>               // Create a DOM XMLSignatureFactory that will be used to 
> generate 
the
>               // enveloped signature
>               XMLSignatureFactory fac = 
> XMLSignatureFactory.getInstance("DOM");
> 
>               // Create a Reference to the enveloped document (in this case 
> we are
>               // signing the whole document, so a URI of "" signifies that) 
> and
>               // also specify the SHA1 digest algorithm and the ENVELOPED 
Transform.
>               Reference ref = fac.newReference("", fac.newDigestMethod(
>                               DigestMethod.SHA1, null), 
> Collections.singletonList(fac
>                               .newTransform(Transform.ENVELOPED,
>                               (TransformParameterSpec) null)), null, null);
> 
>               // Create the SignedInfo
>               SignedInfo si = fac
>                               .newSignedInfo(fac.newCanonicalizationMethod(
>                               CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
>                               (C14NMethodParameterSpec) null), fac
>                               .newSignatureMethod(SignatureMethod.RSA_SHA1, 
> null),
>                               Collections.singletonList(ref));
> 
>               KeyStore keystore = KeyStore.getInstance("JKS");
>               keystore.load(new FileInputStream("myKeystore.jks"),
> "aPassword".toCharArray());
> 
>               PrivateKey privateKey = (PrivateKey)keystore.getKey( "MyAlias",
> "aPassword".toCharArray());
> 
>               KeyStore.PasswordProtection password = new
> KeyStore.PasswordProtection("aPassword".toCharArray());
>               KeyStore.PrivateKeyEntry thePrivKeyEntry = 
(KeyStore.PrivateKeyEntry)
> keystore.getEntry("myAlias", password);
>               X509Certificate cert = (X509Certificate)
>  thePrivKeyEntry.getCertificate();
> 
>               // Create the KeyInfo containing the X509Data.
>               KeyInfoFactory kif = fac.getKeyInfoFactory();
>               List x509Content = new ArrayList();
>               x509Content.add(cert.getSubjectX500Principal().getName());
>               x509Content.add(cert);
>               X509Data xd = kif.newX509Data(x509Content);
>               KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
> 
> 
>               // Instantiate the document to be signed
>               DocumentBuilderFactory dbf = 
> DocumentBuilderFactory.newInstance();
>               dbf.setNamespaceAware(true);
>               Document doc = dbf.newDocumentBuilder().parse(fileInputStream);
> 
>               // Create a DOMSignContext and specify the DSA PrivateKey and
>               // location of the resulting XMLSignature's parent element
>               DOMSignContext dsc = new DOMSignContext(privateKey, doc
>                               .getDocumentElement());
> 
>               // Create the XMLSignature (but don't sign it yet)
>               XMLSignature signature = fac.newXMLSignature(si, ki);
> 
>               // Marshal, generate (and sign) the enveloped signature
>               signature.sign(dsc);
> 
>               return doc;
>       }
> 
> public void sendAnAttachmentWithSignature(){
>       // Sign the dokument
>       DeferredDocumentImpl signedDoc = new XmlSign().createSignedDocument( new
> FileInputStream("a_file.xml") );
> 
>       // Save it to disk
>       OutputStream os = new FileOutputStream( "a_signed_file.xml" );
>                       TransformerFactory tf = 
> TransformerFactory.newInstance();
>                       Transformer trans = tf.newTransformer();
>                       trans.transform(new DOMSource(signedDoc ), new 
StreamResult(os));
> 
>       // Create a DataHandler to attach to the web service klient
>       DataHandler dh = new DataHandler(
>                                       new FileDataSource(
>                                       new File("a_signed_file.xml" )) );
> 
>       // Add the datahandler to the request object
>       WebServiceRequest req = new WebServiceRequest();
>       req.setData( dh );
> 
>       // Then send the request...
> 
> }
> 

-- 
Daniel Kulp
[email protected]
http://www.dankulp.com/blog

Reply via email to