Hi Sean,

Thanks for the prompt reply! Actually I had tried that as well- it also fails 
but I get a different error message and stacktrace.  Maybe this sheds some 
light on what's happening?

org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert 
a node where it is not permitted. 
        at org.apache.xerces.dom.ParentNode.internalInsertBefore(Unknown Source)
        at org.apache.xerces.dom.ParentNode.insertBefore(Unknown Source)
        at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.marshal(Unknown Source)
        at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(Unknown Source)
        at TestClass2.signDocument(TestClass2.java:125)
        at TestClass2.main(TestClass2.java:75)

Best regards,

Richard A. Sand, CEO
Skyworth TTG USA, Inc.
+1 (866) 9-TRIPOD
http://www.skyworthttg.com/us


-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] 
Sent: Wednesday, October 08, 2008 9:31 AM
To: security-dev@xml.apache.org
Subject: Re: problem enveloping a soap body

You are trying to import a Document node which is illegal according to 
Document.importNode. Try changing the following line:

                XMLStructure content = new DOMStructure(doc);

to:

                XMLStructure content = new 
DOMStructure(doc.getDocumentElement());

--Sean


Richard Sand wrote:
> Hi all,
> 
> I'm sure this has been encountered before... I'm trying to use the XML 
> security API to sign a SOAP request. For various reasons I'm not using 
> WS-Security, only XML security.
> 
> I've gone through the sample code provided with the API and I can see that 
> the enveloping sample does not load the XML from an existing stream (such as 
> a file), but rather instantiates the XML document programmatically. When I 
> build my Document using any sort of stream, I get a DOMException upon 
> signing, presumably because the Document cannot be altered.
> 
> org.w3c.dom.DOMException: NOT_SUPPORTED_ERR: The implementation does not 
> support the requested type of object or operation. 
>       at org.apache.xerces.dom.CoreDocumentImpl.importNode(Unknown Source)
>       at org.apache.xerces.dom.CoreDocumentImpl.importNode(Unknown Source)
>       at org.jcp.xml.dsig.internal.dom.DOMUtils.appendChild(Unknown Source)
>       at org.jcp.xml.dsig.internal.dom.DOMXMLObject.marshal(Unknown Source)
>       at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.marshal(Unknown Source)
>       at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(Unknown Source)
>       at TestClass2.signDocument(TestClass2.java:125)
>       at TestClass2.main(TestClass2.java:75)
> 
> My apologies for the elementary question, but how should I generate the 
> Document such that DOMXMLSignature.sign() doesn't have this problem with 
> importNode?
> 
> Thanks for any help! FYI I'm using Sun JDK 1.5.0_12 and building with only 
> the libraries provided with xmlsec-1.4.2.
> 
> My source code is here for reference. FWIW I had a heck of a time loading an 
> encrypted private key, I had to scour the net for that code too, so if that’s 
> useful for anyone please help yourselves. :-)
> 
> import java.io.ByteArrayInputStream;
> import java.io.File;
> import java.io.FileInputStream;
> import java.io.IOException;
> import java.security.AlgorithmParameters;
> import java.security.InvalidAlgorithmParameterException;
> import java.security.InvalidKeyException;
> import java.security.Key;
> import java.security.KeyFactory;
> import java.security.NoSuchAlgorithmException;
> import java.security.PrivateKey;
> import java.security.Provider;
> import java.security.PublicKey;
> import java.security.cert.Certificate;
> import java.security.cert.CertificateException;
> import java.security.cert.CertificateFactory;
> import java.security.spec.InvalidKeySpecException;
> import java.security.spec.InvalidParameterSpecException;
> import java.security.spec.PKCS8EncodedKeySpec;
> import java.util.Collections;
> 
> import javax.crypto.BadPaddingException;
> import javax.crypto.Cipher;
> import javax.crypto.EncryptedPrivateKeyInfo;
> import javax.crypto.IllegalBlockSizeException;
> import javax.crypto.NoSuchPaddingException;
> import javax.crypto.SecretKeyFactory;
> import javax.crypto.spec.PBEKeySpec;
> import javax.xml.crypto.XMLStructure;
> import javax.xml.crypto.dom.DOMStructure;
> import javax.xml.crypto.dsig.CanonicalizationMethod;
> import javax.xml.crypto.dsig.DigestMethod;
> import javax.xml.crypto.dsig.Reference;
> import javax.xml.crypto.dsig.SignatureMethod;
> import javax.xml.crypto.dsig.SignedInfo;
> import javax.xml.crypto.dsig.Transform;
> import javax.xml.crypto.dsig.XMLObject;
> import javax.xml.crypto.dsig.XMLSignature;
> import javax.xml.crypto.dsig.XMLSignatureFactory;
> import javax.xml.crypto.dsig.dom.DOMSignContext;
> import javax.xml.crypto.dsig.keyinfo.KeyInfo;
> import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
> import javax.xml.crypto.dsig.keyinfo.KeyValue;
> import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
> import javax.xml.crypto.dsig.spec.TransformParameterSpec;
> import javax.xml.parsers.DocumentBuilderFactory;
> 
> import org.w3c.dom.Document;
> 
> public class TestClass2 {
> 
>       /**
>        * @param args
>        */
>       public static void main(String[] args) {
>               String xmlStr = "<?xml version=\"1.0\" 
> encoding=\"UTF-8\"?><soapenv:Envelope 
> xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\";><soapenv:Body 
> Id=\"body\"><ns2:getGoKartAll 
> xmlns:ns2=\"http://soa.examples.ttg.com\";><ns2:model>1</ns2:model><ns2:width>33</ns2:width><ns2:length>66</ns2:length><ns2:tires>6</ns2:tires><ns2:color>Dark
>  Red</ns2:color></ns2:getGoKartAll></soapenv:Body></soapenv:Envelope>";
>               // String xmlStr =
>               // 
> "<getGoKartAll><model>1</model><width>33</width><length>66</length><tires>6</tires><color>Dark
>  Red</color></getGoKartAll>";
>               // String xmlStr = "<Object>Some stuff</Object>";
>               String X509cert = "c:\\gkconfig.der";
>               String privateKey = "c:\\gkconfig_key.pk8";
>               String password = "password";
> 
>               try {
>                       // Create a builder factory
>                       ByteArrayInputStream is = new 
> ByteArrayInputStream(xmlStr.getBytes());
>                       DocumentBuilderFactory factory = 
> DocumentBuilderFactory.newInstance();
>                       factory.setNamespaceAware(true);
>                       factory.setValidating(false);
> 
>                       // Create the builder and parse the input
>                       Document doc = factory.newDocumentBuilder().parse(is);
> 
>                       // Sign and output
>                       signDocument(doc, "body", privateKey, password, 
> X509cert);
>                       String signed = doc.toString();
>                       System.out.println("Signed: " + signed);
> 
>               } catch (Exception e) {
>                       e.printStackTrace();
>               }
>       }
> 
>       public static void signDocument(Document doc, String reference, String 
> privateKeyFile, String password, String x509certFile) throws Exception {
>               String providerName = System.getProperty("jsr105Provider", 
> "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
>               XMLSignatureFactory xmlSigFactory = 
> XMLSignatureFactory.getInstance("DOM", (Provider) 
> Class.forName(providerName).newInstance());
> 
>               // Create a Reference to a same-document URI that is an Object
>               // element and specify the SHA1 digest algorithm
>               // Reference ref = xmlSigFactory.newReference(reference,
>               // xmlSigFactory.newDigestMethod(DigestMethod.SHA1, null));
> 
>               // also specify the SHA1 digest algorithm and the ENVELOPED 
> Transform.
>               Reference ref = xmlSigFactory.newReference("", 
> xmlSigFactory.newDigestMethod(DigestMethod.SHA1, null), 
> Collections.singletonList(xmlSigFactory
>                               .newTransform(Transform.ENVELOPED, 
> (TransformParameterSpec) null)), null, null);
> 
>               // Create the SignedInfo
>               SignedInfo si = 
> xmlSigFactory.newSignedInfo(xmlSigFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
>                               (C14NMethodParameterSpec) null), 
> xmlSigFactory.newSignatureMethod(SignatureMethod.DSA_SHA1, null), 
> Collections.singletonList(ref));
> 
>               // Create the XML object from the document
>               XMLStructure content = new DOMStructure(doc);
>               XMLObject xmlobj = 
> xmlSigFactory.newXMLObject(Collections.singletonList(content), "body", null, 
> null);
> 
>               // Load the public and private keys
>               Certificate certs[] = loadX509CertificateChain(x509certFile);
>               if (certs.length < 1)
>                       return;
>               PublicKey publicKey = certs[0].getPublicKey();
>               PrivateKey privateKey = loadPKCS8PrivateKey(privateKeyFile, 
> password);
> 
>               // Create a KeyInfo from the public key
>               KeyInfoFactory kif = xmlSigFactory.getKeyInfoFactory();
>               KeyValue kv = kif.newKeyValue(publicKey);
>               KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
> 
>               // Create the XMLSignature (but don't sign it yet)
>               XMLSignature signature = xmlSigFactory.newXMLSignature(si, ki, 
> Collections.singletonList(xmlobj), null, null);
> 
>               // Create a DOMSignContext, specifying the PrivateKey and the 
> document
>               // location of the XMLSignature
>               DOMSignContext domSignContext = new DOMSignContext(privateKey, 
> doc.getDocumentElement());
> 
>               // Lastly, generate the enveloping signature using the 
> PrivateKey
>               signature.sign(domSignContext);
>       }
> 
>       /**
>        * Loads the DER-encoded X509 certificate chain
>        * 
>        * @param certificateChainFileName
>        * @return
>        * @throws IOException
>        * @throws CertificateException
>        */
>       public static Certificate[] loadX509CertificateChain(String 
> certificateChainFileName) throws IOException, CertificateException {
>               FileInputStream certificateStream = new 
> FileInputStream(certificateChainFileName);
>               CertificateFactory certificateFactory = 
> CertificateFactory.getInstance("X.509");
>               java.security.cert.Certificate[] chain = {};
>               chain = 
> certificateFactory.generateCertificates(certificateStream).toArray(chain);
>               certificateStream.close();
> 
>               return chain;
>       }
> 
>       /**
>        * Loads the DER-encoded, encrypted PKCS8 private key
>        */
>       public static PrivateKey loadPKCS8PrivateKey(String privateKeyFile, 
> String password) throws InvalidKeyException, InvalidParameterSpecException,
>                       IllegalBlockSizeException, 
> InvalidAlgorithmParameterException, NoSuchPaddingException, 
> BadPaddingException, IOException, InvalidKeySpecException,
>                       NoSuchAlgorithmException {
>               File keyFile = new File(privateKeyFile);
>               byte[] encodedKey = new byte[(int) keyFile.length()];
>               FileInputStream is = new FileInputStream(keyFile);
>               is.read(encodedKey);
>               is.close();
> 
>               byte[] decryptedKey = decryptPrivateKey(encodedKey, 
> password.toCharArray());
>               KeyFactory rSAKeyFactory = KeyFactory.getInstance("RSA");
>               PrivateKey privateKey = rSAKeyFactory.generatePrivate(new 
> PKCS8EncodedKeySpec(decryptedKey));
>               return privateKey;
>       }
> 
>       /**
>        * Decrypts an encrypted RSA private key
>        *             
>        * @param instream
>        * @param password
>        * @return
>        * @throws InvalidKeyException
>        * @throws InvalidAlgorithmParameterException
>        * @throws IllegalStateException
>        * @throws IllegalBlockSizeException
>        * @throws BadPaddingException
>        * @throws NoSuchAlgorithmException
>        * @throws NoSuchPaddingException
>        * @throws InvalidKeySpecException
>        * @throws InvalidParameterSpecException
>        * @throws IOException if the key is unencrypted
>        */
>       public static byte[] decryptPrivateKey(byte[] instream, char[] 
> password) throws InvalidKeyException, InvalidAlgorithmParameterException, 
> IllegalStateException,
>                       IllegalBlockSizeException, BadPaddingException, 
> NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException,
>                       InvalidParameterSpecException, IOException {
> 
>               EncryptedPrivateKeyInfo epki = new 
> EncryptedPrivateKeyInfo(instream);
>               //System.out.println("Encrypted private key info's algorithm 
> name is '" + epki.getAlgName() + "'");
> 
>               AlgorithmParameters params = epki.getAlgParameters();
>               if (params == null)
>                       throw new IllegalStateException("The private key info's 
> algorithm parameters are (null). The algorithm is probably not supported!");
>               //PBEParameterSpec pbeParams = (PBEParameterSpec) 
> (params.getParameterSpec(PBEParameterSpec.class));
> 
>               SecretKeyFactory sf = 
> SecretKeyFactory.getInstance(epki.getAlgName());
>               PBEKeySpec keySpec = new PBEKeySpec(password);
>               Key key = sf.generateSecret(keySpec);
>               keySpec.clearPassword();
> 
>               byte[] privateKeyInfoStream = null;
>               Cipher cipher = Cipher.getInstance(epki.getAlgName());
>               cipher.init(Cipher.DECRYPT_MODE, key, params);
> 
>               privateKeyInfoStream = cipher.doFinal(epki.getEncryptedData());
>               return privateKeyInfoStream;
>       }
> }
> 
> Best regards,
> 
> Richard A. Sand, CEO
> Skyworth TTG USA, Inc.
> +1 (866) 9-TRIPOD
> http://www.skyworthttg.com/us
> 

Reply via email to