You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Daniel Kulp <dk...@apache.org> on 2009/12/03 20:39:19 UTC

Re: Signing an MTOM attachment only, not the entire message


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
dkulp@apache.org
http://www.dankulp.com/blog