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.PublicKeyPrincipal;
23  import org.apache.ws.security.WSConstants;
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.common.SOAPUtil;
28  import org.apache.ws.security.components.crypto.Crypto;
29  import org.apache.ws.security.components.crypto.CryptoFactory;
30  import org.apache.ws.security.util.WSSecurityUtil;
31  import org.w3c.dom.Document;
32  
33  import java.util.List;
34  
35  /**
36   * This class tests signing where the the public key is transmitted in the message via
37   * a ds:KeyInfo/ds:KeyValue element. Although this isn't strictly recommended for use in
38   * WS-Security, it's necessary to support it for WCF interop.
39   */
40  public class SignatureKeyValueTest extends org.junit.Assert {
41      private static final org.apache.commons.logging.Log LOG = 
42          org.apache.commons.logging.LogFactory.getLog(SignatureKeyValueTest.class);
43      private Crypto crypto = null;
44      
45      public SignatureKeyValueTest() throws Exception {
46          WSSConfig.init();
47          crypto = CryptoFactory.getInstance("wss40.properties");
48      }
49  
50      /**
51       * Successful RSAKeyValue test.
52       */
53      @org.junit.Test
54      public void testRSAKeyValue() throws Exception {
55          WSSecSignature builder = new WSSecSignature();
56          builder.setUserInfo("wss40", "security");
57          builder.setKeyIdentifierType(WSConstants.KEY_VALUE);
58          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
59          WSSecHeader secHeader = new WSSecHeader();
60          secHeader.insertSecurityHeader(doc);
61          Document signedDoc = builder.build(doc, crypto, secHeader);
62  
63          String outputString = 
64              org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
65          if (LOG.isDebugEnabled()) {
66              LOG.debug(outputString);
67          }
68          assertTrue(outputString.indexOf("RSAKeyValue") != -1);
69          
70          WSSecurityEngine secEngine = new WSSecurityEngine();
71          WSSConfig config = WSSConfig.getNewInstance();
72          config.setWsiBSPCompliant(false);
73          secEngine.setWssConfig(config);
74          final List<WSSecurityEngineResult> results = 
75              secEngine.processSecurityHeader(signedDoc, null, null, crypto);
76  
77          WSSecurityEngineResult actionResult = 
78              WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
79          assertTrue(actionResult != null);
80          
81          java.security.Principal principal = 
82              (java.security.Principal)actionResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
83          assertTrue(principal instanceof PublicKeyPrincipal);
84          java.security.PublicKey publicKey = 
85              ((PublicKeyPrincipal)principal).getPublicKey();
86          assertTrue(publicKey instanceof java.security.interfaces.RSAPublicKey);
87          
88      }
89      
90      
91      /**
92       * Failed RSAKeyValue test, where a message is signed using a key-pair which doesn't
93       * correspond to the public key in the "trust"-store.
94       */
95      @org.junit.Test
96      public void testBadRSAKeyValue() throws Exception {
97          WSSecSignature builder = new WSSecSignature();
98          builder.setUserInfo("wss86", "security");
99          builder.setKeyIdentifierType(WSConstants.KEY_VALUE);
100         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
101         WSSecHeader secHeader = new WSSecHeader();
102         secHeader.insertSecurityHeader(doc);
103         Document signedDoc = 
104             builder.build(doc, CryptoFactory.getInstance("wss86.properties"), secHeader);
105 
106         String outputString = 
107             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
108         if (LOG.isDebugEnabled()) {
109             LOG.debug(outputString);
110         }
111         assertTrue(outputString.indexOf("RSAKeyValue") != -1);
112         
113         try {
114             WSSecurityEngine secEngine = new WSSecurityEngine();
115             WSSConfig config = WSSConfig.getNewInstance();
116             config.setWsiBSPCompliant(false);
117             secEngine.setWssConfig(config);
118             secEngine.processSecurityHeader(signedDoc, null, null, crypto);
119             fail("Failure expected on bad public key");
120         } catch (Exception ex) {
121             // expected
122         }
123         
124     }
125     
126     
127     /**
128      * Successful DSAKeyValue test.
129      */
130     @org.junit.Test
131     public void testDSAKeyValue() throws Exception {
132         WSSecSignature builder = new WSSecSignature();
133         builder.setUserInfo("wss40DSA", "security");
134         builder.setKeyIdentifierType(WSConstants.KEY_VALUE);
135         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
136         WSSecHeader secHeader = new WSSecHeader();
137         secHeader.insertSecurityHeader(doc);
138         Document signedDoc = builder.build(doc, crypto, secHeader);
139 
140         String outputString = 
141             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
142         if (LOG.isDebugEnabled()) {
143             LOG.debug(outputString);
144         }
145         assertTrue(outputString.indexOf("DSAKeyValue") != -1);
146         
147         WSSecurityEngine secEngine = new WSSecurityEngine();
148         WSSConfig config = WSSConfig.getNewInstance();
149         config.setWsiBSPCompliant(false);
150         secEngine.setWssConfig(config);
151         final List<WSSecurityEngineResult> results = 
152             secEngine.processSecurityHeader(signedDoc, null, null, crypto);
153         
154         WSSecurityEngineResult actionResult = 
155             WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
156         assertTrue(actionResult != null);
157         
158         java.security.Principal principal = 
159             (java.security.Principal)actionResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
160         assertTrue(principal instanceof PublicKeyPrincipal);
161         java.security.PublicKey publicKey = 
162             ((PublicKeyPrincipal)principal).getPublicKey();
163         assertTrue(publicKey instanceof java.security.interfaces.DSAPublicKey);
164     }
165     
166 }