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 java.security.cert.X509Certificate;
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import org.apache.ws.security.WSConstants;
27  import org.apache.ws.security.WSEncryptionPart;
28  import org.apache.ws.security.WSSConfig;
29  import org.apache.ws.security.WSSecurityEngine;
30  import org.apache.ws.security.WSSecurityEngineResult;
31  import org.apache.ws.security.common.SOAPUtil;
32  import org.apache.ws.security.components.crypto.Crypto;
33  import org.apache.ws.security.components.crypto.CryptoFactory;
34  import org.apache.ws.security.components.crypto.CryptoType;
35  import org.apache.ws.security.message.token.X509Security;
36  import org.apache.ws.security.util.WSSecurityUtil;
37  import org.w3c.dom.Document;
38  
39  /**
40   * This is a test for signing the SOAP Body as well as the BinarySecurityToken that contains the certificate
41   * used to verify the signature.
42   */
43  public class SignedBSTTest extends org.junit.Assert {
44      private static final org.apache.commons.logging.Log LOG = 
45          org.apache.commons.logging.LogFactory.getLog(SignedBSTTest.class);
46      private WSSecurityEngine secEngine = new WSSecurityEngine();
47      private Crypto crypto = null;
48      
49      public SignedBSTTest() throws Exception {
50          WSSConfig.init();
51          crypto = CryptoFactory.getInstance("wss40.properties");
52      }
53  
54      /**
55       */
56      @org.junit.Test
57      public void testSignedBST() throws Exception {
58          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
59          WSSecHeader secHeader = new WSSecHeader();
60          secHeader.insertSecurityHeader(doc);
61          
62          // Get a certificate, convert it into a BinarySecurityToken and add it to the security header
63          CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
64          cryptoType.setAlias("wss40");
65          X509Certificate[] certs = crypto.getX509Certificates(cryptoType);
66          assertNotNull(certs);
67          
68          X509Security bst = new X509Security(doc);
69          String certUri = WSSConfig.getNewInstance().getIdAllocator().createSecureId("X509-", certs[0]);
70          bst.setX509Certificate(certs[0]);
71          bst.setID(certUri);
72          WSSecurityUtil.prependChildElement(secHeader.getSecurityHeader(), bst.getElement());
73          
74          // Add the signature
75          WSSecSignature sign = new WSSecSignature();
76          sign.setUserInfo("wss40", "security");
77          sign.setSignatureAlgorithm(WSConstants.RSA);
78          sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
79          sign.setX509Certificate(certs[0]);
80  
81          List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
82          // Add SOAP Body
83          String soapNamespace = WSSecurityUtil.getSOAPNamespace(doc.getDocumentElement());
84          WSEncryptionPart encP =
85              new WSEncryptionPart(
86                  WSConstants.ELEM_BODY, soapNamespace, "Content"
87              );
88          parts.add(encP);
89          // Add BST
90          encP =
91              new WSEncryptionPart(
92                  WSConstants.BINARY_TOKEN_LN, WSConstants.WSSE_NS, "Element"
93              );
94          encP.setElement(bst.getElement());
95          parts.add(encP);
96          sign.setParts(parts);
97          
98          sign.setCustomTokenId(bst.getID());
99          sign.setCustomTokenValueType(bst.getValueType());
100         sign.prepare(doc, crypto, secHeader);
101         
102         List<javax.xml.crypto.dsig.Reference> referenceList = 
103             sign.addReferencesToSign(parts, secHeader);
104         sign.computeSignature(referenceList, false, null);
105         
106         if (LOG.isDebugEnabled()) {
107             String outputString = 
108                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
109             LOG.debug(outputString);
110         }
111         
112         verify(doc);
113     }
114     
115 
116     /**
117      * Verifies the soap envelope
118      * <p/>
119      * 
120      * @param doc 
121      * @throws Exception Thrown when there is a problem in verification
122      */
123     private List<WSSecurityEngineResult> verify(Document doc) throws Exception {
124         List<WSSecurityEngineResult> results = 
125             secEngine.processSecurityHeader(doc, null, null, crypto);
126         if (LOG.isDebugEnabled()) {
127             LOG.debug("Verfied and decrypted message:");
128             String outputString = 
129                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
130             LOG.debug(outputString);
131         }
132         return results;
133     }
134 
135 }