Hi Sean,

I guess I'm confused. I thought the whole point of the enveloping technique was 
that the signature would become part of the original document?  Really what I 
want to do is sign the soap body (id=Body) and then put the resulting signature 
into the soap header.

Am I better off trying to do a detached signature instead?  Then create a new 
blank document, add the body from the original, add a new node for the soap 
header, and put the detached signature content on that?

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 5:08 PM
To: security-dev@xml.apache.org
Subject: Re: problem enveloping a soap body

I believe it is because of this line:

// Create a DOMSignContext, specifying the PrivateKey and the document
 >              // location of the XMLSignature
 >              DOMSignContext domSignContext = new DOMSignContext(privateKey, 
doc.getDocumentElement());


I think this is because you are trying to create an enveloping signature over 
the Document that you parsed, but then also trying to insert the Signature 
element as a child element of the root element of the same document. You really 
should create a brand new Document object to insert the Signature in and then 
pass the root Element of that document to the DOMSignContext above.

--Sean

Richard Sand wrote:
> 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