View Javadoc
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.wss4j.dom.message;
21  
22  import java.util.Collections;
23  
24  import org.apache.wss4j.common.principal.PublicKeyPrincipal;
25  import org.apache.wss4j.common.util.SOAPUtil;
26  import org.w3c.dom.Document;
27  import org.apache.wss4j.common.bsp.BSPRule;
28  import org.apache.wss4j.common.crypto.Crypto;
29  import org.apache.wss4j.common.crypto.CryptoFactory;
30  import org.apache.wss4j.common.ext.WSSecurityException;
31  import org.apache.wss4j.common.util.XMLUtils;
32  import org.apache.wss4j.dom.WSConstants;
33  
34  import org.apache.wss4j.dom.engine.WSSConfig;
35  import org.apache.wss4j.dom.engine.WSSecurityEngine;
36  import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
37  import org.apache.wss4j.dom.handler.RequestData;
38  import org.apache.wss4j.dom.handler.WSHandlerResult;
39  
40  import org.junit.jupiter.api.Test;
41  
42  import static org.junit.jupiter.api.Assertions.assertNotNull;
43  import static org.junit.jupiter.api.Assertions.assertTrue;
44  import static org.junit.jupiter.api.Assertions.fail;
45  
46  /**
47   * This class tests signing where the the public key is transmitted in the message via
48   * a ds:KeyInfo/ds:KeyValue element. Although this isn't strictly recommended for use in
49   * WS-Security, it's necessary to support it for WCF interop.
50   */
51  public class SignatureKeyValueTest {
52      private static final org.slf4j.Logger LOG =
53          org.slf4j.LoggerFactory.getLogger(SignatureKeyValueTest.class);
54      private Crypto crypto;
55  
56      public SignatureKeyValueTest() throws Exception {
57          WSSConfig.init();
58          crypto = CryptoFactory.getInstance("wss40.properties");
59      }
60  
61      /**
62       * Successful RSAKeyValue test.
63       */
64      @Test
65      public void testRSAKeyValue() throws Exception {
66          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
67          WSSecHeader secHeader = new WSSecHeader(doc);
68          secHeader.insertSecurityHeader();
69  
70          WSSecSignature builder = new WSSecSignature(secHeader);
71          builder.setUserInfo("wss40", "security");
72          builder.setKeyIdentifierType(WSConstants.KEY_VALUE);
73          Document signedDoc = builder.build(crypto);
74  
75          String outputString =
76              XMLUtils.prettyDocumentToString(signedDoc);
77          if (LOG.isDebugEnabled()) {
78              LOG.debug(outputString);
79          }
80          assertTrue(outputString.contains("RSAKeyValue"));
81  
82          WSSecurityEngine secEngine = new WSSecurityEngine();
83          RequestData data = new RequestData();
84          data.setSigVerCrypto(crypto);
85          data.setIgnoredBSPRules(Collections.singletonList(BSPRule.R5417));
86          final WSHandlerResult results =
87              secEngine.processSecurityHeader(signedDoc, data);
88  
89          WSSecurityEngineResult actionResult =
90              results.getActionResults().get(WSConstants.SIGN).get(0);
91          assertNotNull(actionResult);
92  
93          java.security.Principal principal =
94              (java.security.Principal)actionResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
95          assertTrue(principal instanceof PublicKeyPrincipal);
96          java.security.PublicKey publicKey =
97              ((PublicKeyPrincipal)principal).getPublicKey();
98          assertTrue(publicKey instanceof java.security.interfaces.RSAPublicKey);
99  
100     }
101 
102 
103     /**
104      * Failed RSAKeyValue test, where a message is signed using a key-pair which doesn't
105      * correspond to the public key in the "trust"-store.
106      */
107     @Test
108     public void testBadRSAKeyValue() throws Exception {
109         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
110         WSSecHeader secHeader = new WSSecHeader(doc);
111         secHeader.insertSecurityHeader();
112 
113         WSSecSignature builder = new WSSecSignature(secHeader);
114         builder.setUserInfo("wss86", "security");
115         builder.setKeyIdentifierType(WSConstants.KEY_VALUE);
116         Document signedDoc =
117             builder.build(CryptoFactory.getInstance("wss86.properties"));
118 
119         String outputString =
120             XMLUtils.prettyDocumentToString(signedDoc);
121         if (LOG.isDebugEnabled()) {
122             LOG.debug(outputString);
123         }
124         assertTrue(outputString.contains("RSAKeyValue"));
125 
126         try {
127             WSSecurityEngine secEngine = new WSSecurityEngine();
128             RequestData data = new RequestData();
129             data.setSigVerCrypto(crypto);
130             data.setIgnoredBSPRules(Collections.singletonList(BSPRule.R5417));
131             secEngine.processSecurityHeader(signedDoc, data);
132             fail("Failure expected on bad public key");
133         } catch (WSSecurityException ex) {
134             assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
135         }
136 
137     }
138 
139 
140     /**
141      * Successful DSAKeyValue test.
142      */
143     @Test
144     public void testDSAKeyValue() throws Exception {
145         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
146         WSSecHeader secHeader = new WSSecHeader(doc);
147         secHeader.insertSecurityHeader();
148 
149         WSSecSignature builder = new WSSecSignature(secHeader);
150         builder.setUserInfo("wss40DSA", "security");
151         builder.setKeyIdentifierType(WSConstants.KEY_VALUE);
152         Document signedDoc = builder.build(crypto);
153 
154         String outputString =
155             XMLUtils.prettyDocumentToString(signedDoc);
156         if (LOG.isDebugEnabled()) {
157             LOG.debug(outputString);
158         }
159         assertTrue(outputString.contains("DSAKeyValue"));
160 
161         WSSecurityEngine secEngine = new WSSecurityEngine();
162         RequestData data = new RequestData();
163         data.setSigVerCrypto(crypto);
164         data.setIgnoredBSPRules(Collections.singletonList(BSPRule.R5417));
165         final WSHandlerResult results =
166             secEngine.processSecurityHeader(signedDoc, data);
167 
168         WSSecurityEngineResult actionResult =
169             results.getActionResults().get(WSConstants.SIGN).get(0);
170         assertNotNull(actionResult);
171 
172         java.security.Principal principal =
173             (java.security.Principal)actionResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
174         assertTrue(principal instanceof PublicKeyPrincipal);
175         java.security.PublicKey publicKey =
176             ((PublicKeyPrincipal)principal).getPublicKey();
177         assertTrue(publicKey instanceof java.security.interfaces.DSAPublicKey);
178     }
179     
180     /**
181      * Successful ECKeyValue test.
182      */
183     @Test
184     public void testECKeyValue() throws Exception {
185         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
186         WSSecHeader secHeader = new WSSecHeader(doc);
187         secHeader.insertSecurityHeader();
188 
189         WSSecSignature builder = new WSSecSignature(secHeader);
190         builder.setUserInfo("wss40ec", "security");
191         builder.setKeyIdentifierType(WSConstants.KEY_VALUE);
192         Document signedDoc = builder.build(crypto);
193 
194         String outputString =
195             XMLUtils.prettyDocumentToString(signedDoc);
196         LOG.debug(outputString);
197         assertTrue(outputString.contains("ECKeyValue"));
198 
199         WSSecurityEngine secEngine = new WSSecurityEngine();
200         RequestData data = new RequestData();
201         data.setSigVerCrypto(crypto);
202         data.setIgnoredBSPRules(Collections.singletonList(BSPRule.R5417));
203         final WSHandlerResult results =
204             secEngine.processSecurityHeader(signedDoc, data);
205 
206         WSSecurityEngineResult actionResult =
207             results.getActionResults().get(WSConstants.SIGN).get(0);
208         assertNotNull(actionResult);
209 
210         java.security.Principal principal =
211             (java.security.Principal)actionResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
212         assertTrue(principal instanceof PublicKeyPrincipal);
213         java.security.PublicKey publicKey =
214             ((PublicKeyPrincipal)principal).getPublicKey();
215         assertTrue(publicKey instanceof java.security.interfaces.ECPublicKey);
216     }
217 
218 }