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.util.List;
23  
24  import javax.crypto.KeyGenerator;
25  import javax.crypto.SecretKey;
26  
27  import org.apache.ws.security.WSConstants;
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.WSSecurityException;
32  import org.apache.ws.security.common.KeystoreCallbackHandler;
33  import org.apache.ws.security.common.SOAPUtil;
34  import org.apache.ws.security.common.SecretKeyCallbackHandler;
35  import org.apache.ws.security.components.crypto.AlgorithmSuite;
36  import org.apache.ws.security.components.crypto.Crypto;
37  import org.apache.ws.security.components.crypto.CryptoFactory;
38  import org.apache.ws.security.handler.RequestData;
39  import org.apache.ws.security.util.WSSecurityUtil;
40  import org.apache.ws.security.util.XMLUtils;
41  import org.apache.xml.security.utils.Base64;
42  import org.w3c.dom.Document;
43  import org.w3c.dom.Element;
44  
45  
46  /**
47   * A set of test-cases for encrypting and decrypting SOAP requests when specifying an 
48   * AlgorithmSuite policy.
49   */
50  public class EncryptionAlgorithmSuiteTest extends org.junit.Assert {
51      private static final org.apache.commons.logging.Log LOG = 
52          org.apache.commons.logging.LogFactory.getLog(EncryptionAlgorithmSuiteTest.class);
53      
54      private Crypto crypto = null;
55      
56      public EncryptionAlgorithmSuiteTest() throws Exception {
57          WSSConfig.init();
58          crypto = CryptoFactory.getInstance("wss40.properties");
59      }
60  
61      @org.junit.Test
62      public void testEncryption() throws Exception {
63          WSSecEncrypt builder = new WSSecEncrypt();
64          builder.setUserInfo("wss40");
65          builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
66          builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
67          
68          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
69          WSSecHeader secHeader = new WSSecHeader();
70          secHeader.insertSecurityHeader(doc);
71          
72          Document encryptedDoc = builder.build(doc, crypto, secHeader);
73  
74          if (LOG.isDebugEnabled()) {
75              String outputString = 
76                  XMLUtils.PrettyDocumentToString(encryptedDoc);
77              LOG.debug(outputString);
78          }
79          
80          Element securityHeader = WSSecurityUtil.getSecurityHeader(encryptedDoc, null);
81          AlgorithmSuite algorithmSuite = createAlgorithmSuite();
82          
83          verify(securityHeader, algorithmSuite, crypto);
84          
85          algorithmSuite.setMinimumAsymmetricKeyLength(1024);
86          
87          try {
88              verify(securityHeader, algorithmSuite, crypto);
89              fail("Expected failure as 512-bit keys are not allowed");
90          } catch (WSSecurityException ex) {
91              // expected
92          }
93      }
94      
95      @org.junit.Test
96      public void testEncryptionKeyTransportRSA15() throws Exception {
97          
98          Crypto wssCrypto = CryptoFactory.getInstance("wss40.properties");
99          
100         WSSecEncrypt builder = new WSSecEncrypt();
101         builder.setUserInfo("wss40");
102         builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
103         builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
104         builder.setKeyEncAlgo(WSConstants.KEYTRANSPORT_RSA15);
105         
106         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
107         WSSecHeader secHeader = new WSSecHeader();
108         secHeader.insertSecurityHeader(doc);
109         
110         Document encryptedDoc = builder.build(doc, wssCrypto, secHeader);
111 
112         if (LOG.isDebugEnabled()) {
113             String outputString = 
114                 XMLUtils.PrettyDocumentToString(encryptedDoc);
115             LOG.debug(outputString);
116         }
117         
118         Element securityHeader = WSSecurityUtil.getSecurityHeader(encryptedDoc, null);
119         AlgorithmSuite algorithmSuite = createAlgorithmSuite();
120         
121         try {
122             verify(securityHeader, algorithmSuite, wssCrypto);
123             fail("Expected failure as RSA 15 is not allowed");
124         } catch (WSSecurityException ex) {
125             // expected
126         }
127         
128         algorithmSuite.addKeyWrapAlgorithm(WSConstants.KEYTRANSPORT_RSA15);
129         verify(securityHeader, algorithmSuite, wssCrypto);
130     }
131     
132     @org.junit.Test
133     public void testEncryptionMethodAES128() throws Exception {
134         
135         Crypto wssCrypto = CryptoFactory.getInstance("wss40.properties");
136         
137         WSSecEncrypt builder = new WSSecEncrypt();
138         builder.setUserInfo("wss40");
139         builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
140         builder.setSymmetricEncAlgorithm(WSConstants.AES_128);
141         
142         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
143         WSSecHeader secHeader = new WSSecHeader();
144         secHeader.insertSecurityHeader(doc);
145         
146         Document encryptedDoc = builder.build(doc, wssCrypto, secHeader);
147 
148         if (LOG.isDebugEnabled()) {
149             String outputString = 
150                 XMLUtils.PrettyDocumentToString(encryptedDoc);
151             LOG.debug(outputString);
152         }
153         
154         Element securityHeader = WSSecurityUtil.getSecurityHeader(encryptedDoc, null);
155         AlgorithmSuite algorithmSuite = createAlgorithmSuite();
156         
157         try {
158             verify(securityHeader, algorithmSuite, wssCrypto);
159             fail("Expected failure as AES 128 is not allowed");
160         } catch (WSSecurityException ex) {
161             // expected
162         }
163         
164         algorithmSuite.addEncryptionMethod(WSConstants.AES_128);
165         verify(securityHeader, algorithmSuite, wssCrypto);
166     }
167     
168     @org.junit.Test
169     public void testSymmetricEncryption() throws Exception {
170         
171         KeyGenerator keyGen = KeyGenerator.getInstance("AES");
172         keyGen.init(128);
173         SecretKey key = keyGen.generateKey();
174         byte[] keyData = key.getEncoded();
175         
176         WSSecEncrypt builder = new WSSecEncrypt();
177         builder.setKeyIdentifierType(WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER);
178         builder.setSymmetricKey(key);
179         builder.setEncryptSymmKey(false);
180         
181         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
182         WSSecHeader secHeader = new WSSecHeader();
183         secHeader.insertSecurityHeader(doc);
184         
185         Document encryptedDoc = builder.build(doc, crypto, secHeader);
186 
187         if (LOG.isDebugEnabled()) {
188             String outputString = 
189                 XMLUtils.PrettyDocumentToString(encryptedDoc);
190             LOG.debug(outputString);
191         }
192         
193         byte[] encodedBytes = WSSecurityUtil.generateDigest(keyData);
194         String identifier = Base64.encode(encodedBytes);
195         SecretKeyCallbackHandler secretKeyCallbackHandler = new SecretKeyCallbackHandler();
196         secretKeyCallbackHandler.addSecretKey(identifier, keyData);
197         
198         Element securityHeader = WSSecurityUtil.getSecurityHeader(encryptedDoc, null);
199         AlgorithmSuite algorithmSuite = createAlgorithmSuite();
200         
201         WSSecurityEngine secEngine = new WSSecurityEngine();
202         RequestData data = new RequestData();
203         data.setDecCrypto(crypto);
204         data.setCallbackHandler(secretKeyCallbackHandler);
205         
206         data.setAlgorithmSuite(algorithmSuite);
207         
208         algorithmSuite.addEncryptionMethod(WSConstants.AES_128);
209         secEngine.processSecurityHeader(securityHeader, data);
210         
211         algorithmSuite.setMinimumSymmetricKeyLength(256);
212         try {
213             secEngine.processSecurityHeader(securityHeader, data);
214             fail("Expected failure as a 128 bit key is not allowed");
215         } catch (WSSecurityException ex) {
216             // expected
217         }
218         
219         algorithmSuite.setMinimumSymmetricKeyLength(64);
220         algorithmSuite.setMaximumSymmetricKeyLength(120);
221         try {
222             secEngine.processSecurityHeader(securityHeader, data);
223             fail("Expected failure as a 128 bit key is not allowed");
224         } catch (WSSecurityException ex) {
225             // expected
226         }
227     }
228     
229     
230     private AlgorithmSuite createAlgorithmSuite() {
231         AlgorithmSuite algorithmSuite = new AlgorithmSuite();
232         algorithmSuite.setMinimumAsymmetricKeyLength(512);
233         algorithmSuite.addKeyWrapAlgorithm(WSConstants.KEYTRANSPORT_RSAOEP);
234         algorithmSuite.addEncryptionMethod(WSConstants.TRIPLE_DES);
235         
236         return algorithmSuite;
237     }
238 
239     private List<WSSecurityEngineResult> verify(
240         Element securityHeader, AlgorithmSuite algorithmSuite, Crypto decCrypto
241     ) throws Exception {
242         WSSecurityEngine secEngine = new WSSecurityEngine();
243         RequestData data = new RequestData();
244         data.setDecCrypto(decCrypto);
245         
246         data.setAlgorithmSuite(algorithmSuite);
247         
248         data.setCallbackHandler(new KeystoreCallbackHandler());
249         
250         return secEngine.processSecurityHeader(securityHeader, data);
251     }
252 
253 }