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.SOAPConstants;
23  import org.apache.ws.security.WSEncryptionPart;
24  import org.apache.ws.security.WSConstants;
25  import org.apache.ws.security.WSSConfig;
26  import org.apache.ws.security.util.WSSecurityUtil;
27  import org.apache.ws.security.WSSecurityEngine;
28  import org.apache.ws.security.common.SOAPUtil;
29  import org.apache.ws.security.components.crypto.Crypto;
30  import org.apache.ws.security.components.crypto.CryptoFactory;
31  import org.w3c.dom.Document;
32  
33  import java.util.List;
34  import java.util.ArrayList;
35  
36  /**
37   * WS-Security Test Case for signature creation/validation using the
38   * SecurityTokenReference transform.
39   * 
40   * @author Davanum Srinivas (dims@yahoo.com)
41   */
42  public class STRSignatureTest extends org.junit.Assert {
43      private static final org.apache.commons.logging.Log LOG = 
44          org.apache.commons.logging.LogFactory.getLog(STRSignatureTest.class);
45      private WSSecurityEngine secEngine = new WSSecurityEngine();
46      private Crypto crypto = null;
47      
48      public STRSignatureTest() throws Exception {
49          WSSConfig.init();
50          crypto = CryptoFactory.getInstance("wss40.properties");
51      }
52  
53      /**
54       * Test that signs and verifies a WS-Security envelope.
55       * This test uses the direct reference key identifier (certificate included
56       * as a BinarySecurityToken (BST) in the message). The test signs the message
57       * body (SOAP Body) and uses the STRTransform to sign the embedded certificate
58       * <p/>
59       * 
60       * @throws java.lang.Exception Thrown when there is any problem in signing or verification
61       */
62      @org.junit.Test
63      public void testX509SignatureDirectSTR() throws Exception {
64          WSSecSignature builder = new WSSecSignature();
65          builder.setUserInfo("wss40", "security");
66          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
67          SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc.getDocumentElement());
68          List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
69          
70          //
71          // Set up to sign body and use STRTransform to sign
72          // the signature token (e.g. X.509 certificate)
73          //
74          WSEncryptionPart encP =
75              new WSEncryptionPart(
76                  soapConstants.getBodyQName().getLocalPart(),
77                  soapConstants.getEnvelopeURI(),
78                  "Content");
79          parts.add(encP);
80          encP =
81              new WSEncryptionPart(
82                  "STRTransform",
83                  soapConstants.getEnvelopeURI(),
84                  "Content");
85          parts.add(encP);
86  
87          builder.setParts(parts);
88          builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
89  
90          LOG.info("Before Signing STR DirectReference....");
91  
92          WSSecHeader secHeader = new WSSecHeader();
93          secHeader.insertSecurityHeader(doc);
94  
95          Document signedDoc = builder.build(doc, crypto, secHeader);
96  
97          if (LOG.isDebugEnabled()) {
98              LOG.debug("Signed message with STR DirectReference key identifier:");
99              String outputString = 
100                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
101             LOG.debug(outputString);
102         }
103         LOG.info("After Signing STR DirectReference....");
104         verify(signedDoc);
105     }
106     
107     /**
108      * This is a test for WSS-96:
109      * "Error when making a signature when containing a WSSecTimestamp"
110      * A timestamp is added to the document and signed.
111      */
112     @org.junit.Test
113     public void testWSS96() throws Exception {
114         WSSecSignature builder = new WSSecSignature();
115         builder.setUserInfo("wss40", "security");
116         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
117         SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc.getDocumentElement());
118         List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
119         
120         WSSecHeader secHeader = new WSSecHeader();
121         secHeader.insertSecurityHeader(doc);
122         
123         //
124         // Set up to sign body and use STRTransform to sign
125         // the signature token (e.g. X.509 certificate)
126         //
127         WSEncryptionPart encP =
128             new WSEncryptionPart(
129                 soapConstants.getBodyQName().getLocalPart(),
130                 soapConstants.getEnvelopeURI(),
131                 "Content");
132         parts.add(encP);
133         encP =
134             new WSEncryptionPart(
135                 "STRTransform",
136                 soapConstants.getEnvelopeURI(),
137                 "Content");
138         parts.add(encP);
139         
140         WSSecTimestamp timestamp = new WSSecTimestamp();
141         timestamp.setTimeToLive(600);
142         timestamp.build(doc, secHeader);
143         parts.add(new WSEncryptionPart(timestamp.getId()));
144 
145         builder.setParts(parts);
146         builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
147 
148         LOG.info("Before Signing STR DirectReference....");
149         Document signedDoc = builder.build(doc, crypto, secHeader);
150 
151         if (LOG.isDebugEnabled()) {
152             LOG.debug("Signed message with STR DirectReference key identifier:");
153             String outputString = 
154                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
155             LOG.debug(outputString);
156         }
157         LOG.info("After Signing STR DirectReference....");
158         verify(signedDoc);
159     }
160 
161 
162     /**
163      * Test that signs and verifies a WS-Security envelope.
164      * This test uses the IssuerSerial reference key identifier (certificate not included
165      * in the message)and reads the certificate from a keystore using IssuerSerialNumber
166      * to identify it.
167      * <p/>
168      * 
169      * @throws java.lang.Exception Thrown when there is any problem in signing or verification
170      */
171     @org.junit.Test
172     public void testX509SignatureISSTR() throws Exception {
173         WSSecSignature builder = new WSSecSignature();
174         builder.setUserInfo("wss40", "security");
175         
176         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
177         SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc.getDocumentElement());
178         List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
179         
180         //
181         // Set up to sign body and use STRTransform to sign
182         // the signature token (e.g. X.509 certificate)
183         //
184         WSEncryptionPart encP =
185             new WSEncryptionPart(
186                 soapConstants.getBodyQName().getLocalPart(),    // define the body
187                 soapConstants.getEnvelopeURI(),
188                 "Content");
189         parts.add(encP);
190         encP =
191             new WSEncryptionPart(
192                 "STRTransform",                // reserved word to use STRTransform
193                 soapConstants.getEnvelopeURI(),
194                 "Content");
195         parts.add(encP);
196 
197         builder.setParts(parts);
198         builder.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
199 
200         LOG.info("Before Signing STR IS....");
201         
202         WSSecHeader secHeader = new WSSecHeader();
203         secHeader.insertSecurityHeader(doc);
204 
205         Document signedDoc = builder.build(doc, crypto, secHeader);
206 
207         if (LOG.isDebugEnabled()) {
208             LOG.debug("Signed message with STR IssuerSerial key identifier:");
209             String outputString = 
210                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
211             LOG.debug(outputString);
212         }
213         LOG.info("After Signing STR IS....");
214         verify(signedDoc);
215     }
216     
217     /**
218      * Test that signs and verifies a WS-Security envelope.
219      * This test uses the SubjectKeyIdentifier key identifier (certificate not included
220      * in the message) and reads the certificate from a keystore using SKI
221      * to identify it.
222      * <p/>
223      * 
224      * @throws java.lang.Exception Thrown when there is any problem in signing or verification
225      */
226     @org.junit.Test
227     public void testX509SignatureSKISTR() throws Exception {
228         WSSecSignature builder = new WSSecSignature();
229         builder.setUserInfo("wss40", "security");
230         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
231         SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc.getDocumentElement());
232         List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
233         
234         //
235         // Set up to sign body and use STRTransform to sign
236         // the signature token (e.g. X.509 certificate)
237         //
238         WSEncryptionPart encP =
239             new WSEncryptionPart(
240                 soapConstants.getBodyQName().getLocalPart(),    // define the body
241                 soapConstants.getEnvelopeURI(),
242                 "Content");
243         parts.add(encP);
244         encP =
245             new WSEncryptionPart(
246                 "STRTransform",                // reserved word to use STRTransform
247                 soapConstants.getEnvelopeURI(),
248                 "Content");
249         parts.add(encP);
250 
251         builder.setParts(parts);
252         builder.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER);
253 
254         LOG.info("Before Signing STR SKI....");
255         
256         WSSecHeader secHeader = new WSSecHeader();
257         secHeader.insertSecurityHeader(doc);
258 
259         Document signedDoc = builder.build(doc, crypto, secHeader);
260 
261         if (LOG.isDebugEnabled()) {
262             LOG.debug("Signed message with STR SKI key identifier:");
263             String outputString = 
264                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
265             LOG.debug(outputString);
266         }
267         LOG.info("After Signing STR SKI....");
268         verify(signedDoc);
269     }
270 
271 
272     /**
273      * Verifies the soap envelope
274      * 
275      * @param env soap envelope
276      * @throws java.lang.Exception Thrown when there is a problem in verification
277      */
278     private void verify(Document doc) throws Exception {
279         secEngine.processSecurityHeader(doc, null, null, crypto);
280     }
281 }