1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.ws.security.message;
21  
22  import org.apache.ws.security.WSConstants;
23  import org.apache.ws.security.WSEncryptionPart;
24  import org.apache.ws.security.WSSConfig;
25  import org.apache.ws.security.WSSecurityEngine;
26  import org.apache.ws.security.WSSecurityEngineResult;
27  import org.apache.ws.security.WSSecurityException;
28  import org.apache.ws.security.common.KeystoreCallbackHandler;
29  import org.apache.ws.security.common.SAML1CallbackHandler;
30  import org.apache.ws.security.common.SOAPUtil;
31  import org.apache.ws.security.components.crypto.Crypto;
32  import org.apache.ws.security.components.crypto.CryptoFactory;
33  import org.apache.ws.security.saml.WSSecSignatureSAML;
34  import org.apache.ws.security.saml.ext.AssertionWrapper;
35  import org.apache.ws.security.saml.ext.SAMLParms;
36  import org.apache.ws.security.saml.ext.builder.SAML1Constants;
37  import org.apache.ws.security.util.WSSecurityUtil;
38  import org.apache.ws.security.util.XmlSchemaDateFormat;
39  import org.w3c.dom.Document;
40  import org.w3c.dom.Element;
41  import org.w3c.dom.Node;
42  
43  import java.text.DateFormat;
44  import java.util.Date;
45  import java.util.List;
46  import java.util.ArrayList;
47  
48  import javax.security.auth.callback.CallbackHandler;
49  
50  /**
51   * This class tests the modification of requests.
52   */
53  public class ModifiedRequestTest extends org.junit.Assert {
54      private static final org.apache.commons.logging.Log LOG = 
55          org.apache.commons.logging.LogFactory.getLog(ModifiedRequestTest.class);
56      private static final String SOAPMSG = 
57          "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 
58          + "<SOAP-ENV:Envelope "
59          +   "xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" "
60          +   "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
61          +   "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" 
62          +   "<SOAP-ENV:Body>" 
63          +       "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">" 
64          +           "<value xmlns=\"http://blah.com\">15</value>" 
65          +       "</add>" 
66          +   "</SOAP-ENV:Body>" 
67          + "</SOAP-ENV:Envelope>";
68      
69      private WSSecurityEngine secEngine = new WSSecurityEngine();
70      private CallbackHandler callbackHandler = new KeystoreCallbackHandler();
71      private Crypto crypto = null;
72      
73      public ModifiedRequestTest() throws Exception {
74          WSSConfig.init();
75          crypto = CryptoFactory.getInstance();
76      }
77  
78      /**
79       * Test that signs a SOAP body element "value". The SOAP request is then modified
80       * so that the signed "value" element is put in the header, and the value of the
81       * original element is changed. This test will fail as the request will contain
82       * multiple elements with the same wsu:Id.
83       */
84      @org.junit.Test
85      public void testMovedElement() throws Exception {
86          WSSecSignature builder = new WSSecSignature();
87          builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
88          LOG.info("Before Signing....");
89          Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
90          WSSecHeader secHeader = new WSSecHeader();
91          secHeader.insertSecurityHeader(doc);
92          
93          List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
94          WSEncryptionPart encP =
95              new WSEncryptionPart(
96                  "value",
97                  "http://blah.com",
98                  "");
99          parts.add(encP);
100         builder.setParts(parts);
101         
102         Document signedDoc = builder.build(doc, crypto, secHeader);
103         
104         //
105         // Replace the signed element with a modified element, and move the original
106         // signed element into the SOAP header
107         //
108         org.w3c.dom.Element secHeaderElement = secHeader.getSecurityHeader();
109         org.w3c.dom.Element envelopeElement = signedDoc.getDocumentElement();
110         org.w3c.dom.Node valueNode = 
111             envelopeElement.getElementsByTagNameNS("http://blah.com", "value").item(0);
112         org.w3c.dom.Node clonedValueNode = valueNode.cloneNode(true);
113         secHeaderElement.appendChild(clonedValueNode);
114         valueNode.getFirstChild().setNodeValue("250");
115         
116         if (LOG.isDebugEnabled()) {
117             LOG.debug("After Signing....");
118             String outputString = 
119                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
120             LOG.debug(outputString);
121         }
122         
123         try {
124             verify(signedDoc);
125             fail("Failure expected on multiple elements with the same wsu:Id");
126         } catch (WSSecurityException ex) {
127             assertTrue(ex.getErrorCode() == 6);
128             assertTrue(ex.getMessage().startsWith("The signature or decryption was invalid"));
129         }
130     }
131     
132     
133     /**
134      * Test that signs a SOAP body element "value". The SOAP request is then modified
135      * so that the signed "value" element is put in the header, and the value of the
136      * original element is changed. The wsu:Id value of the original element is also
137      * changed. Signature verification will pass, so we need to check the wsu:Id's.
138      */
139     @org.junit.Test
140     public void testMovedElementChangedId() throws Exception {
141         WSSecSignature builder = new WSSecSignature();
142         builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
143         LOG.info("Before Signing....");
144         Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
145         WSSecHeader secHeader = new WSSecHeader();
146         secHeader.insertSecurityHeader(doc);
147         
148         List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
149         WSEncryptionPart encP =
150             new WSEncryptionPart(
151                 "value",
152                 "http://blah.com",
153                 "");
154         parts.add(encP);
155         builder.setParts(parts);
156         
157         Document signedDoc = builder.build(doc, crypto, secHeader);
158         
159         //
160         // Replace the signed element with a modified element, and move the original
161         // signed element into the SOAP header
162         //
163         org.w3c.dom.Element secHeaderElement = secHeader.getSecurityHeader();
164         org.w3c.dom.Element envelopeElement = signedDoc.getDocumentElement();
165         org.w3c.dom.Node valueNode = 
166             envelopeElement.getElementsByTagNameNS("http://blah.com", "value").item(0);
167         org.w3c.dom.Node clonedValueNode = valueNode.cloneNode(true);
168         secHeaderElement.appendChild(clonedValueNode);
169         valueNode.getFirstChild().setNodeValue("250");
170         String savedId = 
171             ((org.w3c.dom.Element)valueNode).getAttributeNS(WSConstants.WSU_NS, "Id");
172         ((org.w3c.dom.Element)valueNode).setAttributeNS(
173              WSConstants.WSU_NS, "wsu:Id", "id-250"
174         );
175         
176         if (LOG.isDebugEnabled()) {
177             LOG.debug("After Signing....");
178             String outputString = 
179                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
180             LOG.debug(outputString);
181         }
182         
183         //
184         // Now we check that the wsu:Id of the element we want signed corresponds to the
185         // wsu:Id that was actually signed...again, this should pass
186         //
187         List<WSSecurityEngineResult> results = verify(signedDoc);
188         
189         WSSecurityEngineResult actionResult = 
190             WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
191         WSSecurityUtil.checkSignsAllElements(actionResult, new String[]{savedId});
192         
193         //
194         // Finally we need to check that the wsu:Id of the element we want signed in the
195         // SOAP request is the same as the wsu:Id that was actually signed
196         //
197         envelopeElement = signedDoc.getDocumentElement();
198         org.w3c.dom.Node bodyNode = 
199             envelopeElement.getElementsByTagNameNS(
200                 WSConstants.URI_SOAP11_ENV, "Body"
201             ).item(0);
202         valueNode = 
203             ((org.w3c.dom.Element)bodyNode).getElementsByTagNameNS(
204                 "http://blah.com", "value"
205             ).item(0);
206         String actualId = 
207             ((org.w3c.dom.Element)valueNode).getAttributeNS(WSConstants.WSU_NS, "Id");
208         try {
209             WSSecurityUtil.checkSignsAllElements(actionResult, new String[]{actualId});
210             fail("Failure expected on bad wsu:Id");
211         } catch (WSSecurityException ex) {
212             assertTrue(ex.getErrorCode() == 6);
213             assertTrue(ex.getMessage().startsWith("The signature or decryption was invalid"));
214         }
215     }
216     
217     /**
218      * Test a duplicated signed SAML Assertion.
219      */
220     @org.junit.Test
221     public void testDuplicatedSignedSAMLAssertion() throws Exception {
222         SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
223         callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
224         callbackHandler.setConfirmationMethod(SAML1Constants.CONF_SENDER_VOUCHES);
225         callbackHandler.setIssuer("www.example.com");
226         
227         SAMLParms samlParms = new SAMLParms();
228         samlParms.setCallbackHandler(callbackHandler);
229         AssertionWrapper assertion = new AssertionWrapper(samlParms);
230         
231         WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
232         wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
233         
234         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
235         WSSecHeader secHeader = new WSSecHeader();
236         secHeader.insertSecurityHeader(doc);
237         
238         Document signedDoc = 
239             wsSign.build(
240                 doc, null, assertion, crypto, "16c73ab6-b892-458f-abf5-2f875f74882e", 
241                 "security", secHeader
242             );
243         Element assertionElement = (Element)assertion.getElement().cloneNode(true);
244         assertionElement.removeChild(assertionElement.getFirstChild());
245         secHeader.getSecurityHeader().appendChild(assertionElement);
246 
247         if (LOG.isDebugEnabled()) {
248             LOG.debug("SAML 1.1 Authn Assertion (sender vouches):");
249             String outputString = 
250                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
251             LOG.debug(outputString);
252         }
253         
254         try {
255             verify(signedDoc);
256             fail("Failure expected on duplicate tokens");
257         } catch (WSSecurityException ex) {
258             assertTrue(ex.getMessage().contains(
259                 "Multiple security tokens with the same Id have been detected"
260             ));
261         }
262     }
263     
264     /**
265      * Test a duplicated signed UsernameToken
266      */
267     @org.junit.Test
268     public void testDuplicatedSignedUsernameToken() throws Exception {
269         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
270         WSSecHeader secHeader = new WSSecHeader();
271         secHeader.insertSecurityHeader(doc);
272         
273         WSSecUsernameToken usernameToken = new WSSecUsernameToken();
274         usernameToken.setUserInfo("wss86", "security");
275         Document createdDoc = usernameToken.build(doc, secHeader);
276         
277         List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
278         WSEncryptionPart encP =
279             new WSEncryptionPart(
280                 "UsernameToken",
281                 WSConstants.WSSE_NS,
282                 "");
283         parts.add(encP);
284         
285         WSSecSignature builder = new WSSecSignature();
286         builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
287         builder.setParts(parts);
288         
289         builder.prepare(createdDoc, crypto, secHeader);
290         
291         List<javax.xml.crypto.dsig.Reference> referenceList = 
292             builder.addReferencesToSign(parts, secHeader);
293 
294         builder.computeSignature(referenceList, false, null);
295         
296         secHeader.getSecurityHeader().appendChild(
297             usernameToken.getUsernameTokenElement().cloneNode(true)
298         );
299         
300         if (LOG.isDebugEnabled()) {
301             LOG.debug("Signed Timestamp");
302             String outputString = 
303                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
304             LOG.debug(outputString);
305         }
306         
307         try {
308             verify(doc);
309             fail("Failure expected on duplicate tokens");
310         } catch (WSSecurityException ex) {
311             assertTrue(ex.getMessage().contains(
312                 "Multiple security tokens with the same Id have been detected"
313             ));
314         }
315     }
316     
317     /**
318      * Test for when an EncryptedData structure is modified
319      */
320     @org.junit.Test
321     public void testModifiedEncryptedDataStructure() throws Exception {
322         WSSecEncrypt builder = new WSSecEncrypt();
323         builder.setUserInfo("wss40");
324         builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
325         builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
326         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
327         WSSecHeader secHeader = new WSSecHeader();
328         secHeader.insertSecurityHeader(doc);
329         Crypto wssCrypto = CryptoFactory.getInstance("wss40.properties");
330         Document encryptedDoc = builder.build(doc, wssCrypto, secHeader);
331 
332         Element body = WSSecurityUtil.findBodyElement(doc);
333         Element encryptionMethod = 
334             WSSecurityUtil.findElement(body, "EncryptionMethod", WSConstants.ENC_NS);
335         encryptionMethod.setAttribute("Algorithm", "http://new-algorithm");
336         
337         String outputString = 
338             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
339         if (LOG.isDebugEnabled()) {
340             LOG.debug(outputString);
341         }
342         
343         WSSecurityEngine newEngine = new WSSecurityEngine();
344         try {
345             newEngine.processSecurityHeader(doc, null, new KeystoreCallbackHandler(), wssCrypto);
346             fail("Failure expected on a modified EncryptedData structure");
347         } catch (WSSecurityException ex) {
348             // expected
349         }
350     }
351     
352     /**
353      * Test for when some EncryptedData CipherValue data is modified.
354      */
355     @org.junit.Test
356     public void testModifiedEncryptedDataCipherValue() throws Exception {
357         WSSecEncrypt builder = new WSSecEncrypt();
358         builder.setUserInfo("wss40");
359         builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
360         builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
361         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
362         WSSecHeader secHeader = new WSSecHeader();
363         secHeader.insertSecurityHeader(doc);
364         Crypto wssCrypto = CryptoFactory.getInstance("wss40.properties");
365         Document encryptedDoc = builder.build(doc, wssCrypto, secHeader);
366 
367         Element body = WSSecurityUtil.findBodyElement(doc);
368         Element cipherValue = 
369             WSSecurityUtil.findElement(body, "CipherValue", WSConstants.ENC_NS);
370         String cipherText = cipherValue.getTextContent();
371         
372         StringBuilder stringBuilder = new StringBuilder(cipherText);
373         int index = stringBuilder.length() / 2;
374         char ch = stringBuilder.charAt(index);
375         if (ch != 'A') {
376             ch = 'A';
377         } else {
378             ch = 'B';
379         }
380         stringBuilder.setCharAt(index, ch);
381         cipherValue.setTextContent(stringBuilder.toString());
382         
383         String outputString = 
384             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
385         if (LOG.isDebugEnabled()) {
386             LOG.debug(outputString);
387         }
388         
389         WSSecurityEngine newEngine = new WSSecurityEngine();
390         try {
391             newEngine.processSecurityHeader(doc, null, new KeystoreCallbackHandler(), wssCrypto);
392             fail("Failure expected on a modified EncryptedData CipherValue");
393         } catch (WSSecurityException ex) {
394             assertTrue(ex.getErrorCode() == 6);
395             assertTrue(ex.getMessage().startsWith("The signature or decryption was invalid"));
396         }
397     }
398     
399     /**
400      * Test for when some EncryptedKey CipherValue data is modified.
401      */
402     @org.junit.Test
403     public void testModifiedEncryptedKeyCipherValue() throws Exception {
404         WSSecEncrypt builder = new WSSecEncrypt();
405         builder.setUserInfo("wss40");
406         builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
407         builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
408         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
409         WSSecHeader secHeader = new WSSecHeader();
410         secHeader.insertSecurityHeader(doc);
411         Crypto wssCrypto = CryptoFactory.getInstance("wss40.properties");
412         Document encryptedDoc = builder.build(doc, wssCrypto, secHeader);
413 
414         Element encryptedKey = 
415                 WSSecurityUtil.findElement(doc.getDocumentElement(), "EncryptedKey", WSConstants.ENC_NS);
416         Element cipherValue = 
417             WSSecurityUtil.findElement(encryptedKey, "CipherValue", WSConstants.ENC_NS);
418         String cipherText = cipherValue.getTextContent();
419         
420         StringBuilder stringBuilder = new StringBuilder(cipherText);
421         int index = stringBuilder.length() / 2;
422         char ch = stringBuilder.charAt(index);
423         if (ch != 'A') {
424             ch = 'A';
425         } else {
426             ch = 'B';
427         }
428         stringBuilder.setCharAt(index, ch);
429         cipherValue.setTextContent(stringBuilder.toString());
430         
431         String outputString = 
432             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
433         if (LOG.isDebugEnabled()) {
434             LOG.debug(outputString);
435         }
436         
437         WSSecurityEngine newEngine = new WSSecurityEngine();
438         try {
439             newEngine.processSecurityHeader(doc, null, new KeystoreCallbackHandler(), wssCrypto);
440             fail("Failure expected on a modified EncryptedData CipherValue");
441         } catch (WSSecurityException ex) {
442             assertTrue(ex.getErrorCode() == 6);
443             assertTrue(ex.getMessage().startsWith("The signature or decryption was invalid"));
444         }
445     }
446 
447 
448     
449     /**
450      * Test for when an element that a Signature Reference points to is modified
451      */
452     @org.junit.Test
453     public void testModifiedSignatureReference() throws Exception {
454         WSSecSignature builder = new WSSecSignature();
455         builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
456         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
457         WSSecHeader secHeader = new WSSecHeader();
458         secHeader.insertSecurityHeader(doc);
459         
460         WSSecTimestamp timestamp = new WSSecTimestamp();
461         timestamp.setTimeToLive(300);
462         Document createdDoc = timestamp.build(doc, secHeader);
463         
464         List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
465         WSEncryptionPart encP =
466             new WSEncryptionPart(
467                 "Timestamp",
468                 WSConstants.WSU_NS,
469                 "");
470         parts.add(encP);
471         builder.setParts(parts);
472         
473         Document signedDoc = builder.build(createdDoc, crypto, secHeader);
474         
475         // Modify the Created text of the Timestamp element
476         Element timestampElement = timestamp.getElement();
477         Element createdValue = 
478             WSSecurityUtil.findElement(timestampElement, "Created", WSConstants.WSU_NS);
479         DateFormat zulu = new XmlSchemaDateFormat();
480         createdValue.setTextContent(zulu.format(new Date()));
481         
482         if (LOG.isDebugEnabled()) {
483             String outputString = 
484                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
485             LOG.debug(outputString);
486         }
487         
488         try {
489             verify(signedDoc);
490             fail("Failure expected on a modified Signature Reference");
491         } catch (WSSecurityException ex) {
492             assertTrue(ex.getErrorCode() == 6);
493             assertTrue(ex.getMessage().startsWith("The signature or decryption was invalid"));
494         }
495     }
496     
497     /**
498      * Test for when a Signature is received with a certificate that is not trusted
499      */
500     @org.junit.Test
501     public void testUntrustedSignature() throws Exception {
502         WSSecSignature builder = new WSSecSignature();
503         builder.setUserInfo("wss40", "security");
504         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
505         WSSecHeader secHeader = new WSSecHeader();
506         secHeader.insertSecurityHeader(doc);
507         
508         Crypto wss40Crypto = CryptoFactory.getInstance("wss40.properties");
509         Document signedDoc = builder.build(doc, wss40Crypto, secHeader);
510         
511         if (LOG.isDebugEnabled()) {
512             String outputString = 
513                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
514             LOG.debug(outputString);
515         }
516         
517         try {
518             verify(signedDoc);
519             fail("Failure expected on an untrusted Certificate");
520         } catch (WSSecurityException ex) {
521             assertTrue(ex.getErrorCode() == 6);
522             assertTrue(ex.getMessage().startsWith("The signature or decryption was invalid"));
523         }
524     }
525     
526     /**
527      * Test for when the Signature element is modified
528      */
529     @org.junit.Test
530     public void testModifiedSignature() throws Exception {
531         WSSecSignature builder = new WSSecSignature();
532         builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
533         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
534         WSSecHeader secHeader = new WSSecHeader();
535         secHeader.insertSecurityHeader(doc);
536         
537         Document signedDoc = builder.build(doc, crypto, secHeader);
538         
539         // Modify the Signature element
540         Element signatureElement = builder.getSignatureElement();
541         Node firstChild = signatureElement.getFirstChild();
542         while (!(firstChild instanceof Element) && firstChild != null) {
543             firstChild = signatureElement.getNextSibling();
544         }
545         ((Element)firstChild).setAttributeNS(null, "Id", "xyz");
546         
547         if (LOG.isDebugEnabled()) {
548             String outputString = 
549                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
550             LOG.debug(outputString);
551         }
552         
553         try {
554             verify(signedDoc);
555             fail("Failure expected on a modified Signature element");
556         } catch (WSSecurityException ex) {
557             assertTrue(ex.getErrorCode() == 6);
558             assertTrue(ex.getMessage().startsWith("The signature or decryption was invalid"));
559         }
560     }
561 
562     /**
563      * Verifies the soap envelope
564      * <p/>
565      * 
566      * @param env soap envelope
567      * @throws java.lang.Exception Thrown when there is a problem in verification
568      */
569     private List<WSSecurityEngineResult>  verify(Document doc) throws Exception {
570         return secEngine.processSecurityHeader(doc, null, callbackHandler, crypto);
571     }
572 
573 }