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.components.crypto;
21  
22  import org.apache.ws.security.WSSecurityEngine;
23  import org.apache.ws.security.WSConstants;
24  import org.apache.ws.security.common.KeystoreCallbackHandler;
25  import org.apache.ws.security.common.SOAPUtil;
26  import org.apache.ws.security.message.WSSecEncrypt;
27  import org.apache.ws.security.message.WSSecHeader;
28  import org.apache.ws.security.message.WSSecSignature;
29  import org.w3c.dom.Document;
30  
31  import javax.security.auth.callback.CallbackHandler;
32  import java.security.cert.CertificateFactory;
33  import java.security.cert.X509Certificate;
34  
35  /**
36   * This is a test for WSS-86 - "CryptoBase.splitAndTrim does not take into account the format of a 
37   * DN constructed by different providers":
38   * http://issues.apache.org/jira/browse/WSS-86
39   * 
40   * Keystore: keys\wss86.keystore
41   * Password: security
42   * Generated by:
43   * 
44   * keytool -genkey -validity 3650 -alias wss86 -keyalg RSA -keystore wss86.keystore 
45   * -dname "1.2.840.113549.1.9.1=#16125765726e6572406578616d706c652e636f6d,CN=Werner,
46   * OU=WSS4J,O=Apache,L=Munich,ST=Bayern,C=DE"
47   */
48  public class CryptoProviderTest extends org.junit.Assert {
49      private static final org.apache.commons.logging.Log LOG = 
50          org.apache.commons.logging.LogFactory.getLog(CryptoProviderTest.class);
51      private WSSecurityEngine secEngine = new WSSecurityEngine();
52      private CallbackHandler callbackHandler = new KeystoreCallbackHandler();
53      private Crypto crypto;
54  
55      public CryptoProviderTest() throws Exception {
56          secEngine.getWssConfig(); //make sure BC gets registered
57          crypto = CryptoFactory.getInstance("wss86.properties");
58      }
59  
60      /**
61       * Test signing a SOAP message using a cert with an OID
62       */
63      @org.junit.Test
64      public void testSignatureOID() throws Exception {
65          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
66          WSSecSignature sign = new WSSecSignature();
67          sign.setUserInfo("wss86", "security");
68          sign.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
69  
70          WSSecHeader secHeader = new WSSecHeader();
71          secHeader.insertSecurityHeader(doc);
72          Document signedDoc = sign.build(doc, crypto, secHeader);
73          
74          if (LOG.isDebugEnabled()) {
75              String outputString = 
76                  org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
77              LOG.debug(outputString);
78          }
79          verify(signedDoc);
80      }
81      
82      /**
83       * Test loading a certificate using BouncyCastle, and using it to encrypt a message, but
84       * decrypt the message using the Java Keystore provider
85       */
86      @org.junit.Test
87      public void testInterop() throws Exception {
88          // 
89          // This cert corresponds to the cert in wss86.keystore
90          // Extracted with:
91          // keytool -export -rfc -keystore wss86.keystore -alias wss86 -file wss86.cer
92          //
93          byte[] certBytes = 
94              org.apache.ws.security.util.Base64.decode(
95                  "MIICfDCCAeUCBEnHoGMwDQYJKoZIhvcNAQEEBQAwgYQxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIEwZC"
96                  + "YXllcm4xDzANBgNVBAcTBk11bmljaDEPMA0GA1UEChMGQXBhY2hlMQ4wDAYDVQQLEwVXU1M0SjEP"
97                  + "MA0GA1UEAxMGV2VybmVyMSEwHwYJKoZIhvcNAQkBFhJXZXJuZXJAZXhhbXBsZS5jb20wHhcNMDkw"
98                  + "MzIzMTQ0NDUxWhcNMTkwMzIxMTQ0NDUxWjCBhDELMAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVy"
99                  + "bjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNVBAsTBVdTUzRKMQ8wDQYD"
100                 + "VQQDEwZXZXJuZXIxITAfBgkqhkiG9w0BCQEWEldlcm5lckBleGFtcGxlLmNvbTCBnzANBgkqhkiG"
101                 + "9w0BAQEFAAOBjQAwgYkCgYEA3uRplw7q8y/sIR541uCrlbIMzJHXCRU3nQreGNr6dM49/LxHYffQ"
102                 + "Ex99chQh+wR6fwArFlziDRNnqslOy8zKMfGbaBaR41ZZrxvkSsIwzOhD6yAPgKVQL2vTmJAbdZ35"
103                 + "GwcOW8oe7l+NV9qmv7yrr5OhqDhFh36WhgjVLiwmP/cCAwEAATANBgkqhkiG9w0BAQQFAAOBgQBP"
104                 + "PnR2BYn7DKn/SkU8XTgf9g2NoYcMyvQOB+Uo25/QzDdMk6HKmHl0+7mh7RAtXcBz2YqC3WbQW5U3"
105                 + "KmOH6fVxB8hw6xalBjs2YpnBx4gaHAws35KlAfkGVVe5wqnrI7ER7RBYO/7Gr7uCUq11QrGyEG8/"
106                 + "yIXktaFLxgD2R4hpfA=="
107             );
108         CertificateFactory factory = 
109             CertificateFactory.getInstance("X.509", "BC");
110         X509Certificate cert = 
111             (X509Certificate)factory.generateCertificate(
112                 new java.io.ByteArrayInputStream(certBytes)
113             );
114 
115         WSSecEncrypt encrypt = new WSSecEncrypt();
116         encrypt.setUseThisCert(cert);
117         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
118         WSSecHeader secHeader = new WSSecHeader();
119         secHeader.insertSecurityHeader(doc);
120         Document encryptedDoc = encrypt.build(doc, crypto, secHeader);
121         
122         if (LOG.isDebugEnabled()) {
123             String outputString = 
124                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
125             LOG.debug(outputString);
126         }
127         verify(encryptedDoc);
128         
129     }
130     
131     
132     /**
133      * Test loading a certificate using BouncyCastle, and using it to encrypt a message, but
134      * decrypt the message using the Java Keystore provider. In this case though the cert doesn't
135      * correspond with the cert in wss86.keystore.
136      */
137     @org.junit.Test
138     public void testBadInterop() throws Exception {
139         byte[] certBytes = 
140             org.apache.ws.security.util.Base64.decode(
141                 "MIIDNDCCAp2gAwIBAgIBEDANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEPMA0GA1UECBMG"
142                 + "QmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUxFTATBgNVBAsTDEFwYWNoZSBX"
143                 + "U1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA4MDQwNDE5MzIxOFoXDTEwMDQwNDE5MzIxOFowYTEL"
144                 + "MAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZB"
145                 + "cGFjaGUxDjAMBgNVBAsTBVdTUzRKMQ8wDQYDVQQDEwZXZXJuZXIwgZ8wDQYJKoZIhvcNAQEBBQAD"
146                 + "gY0AMIGJAoGBAINlL3/k0H/zvknpBtLo8jzXwx/IJU/CGSv6MsqJZ2fyZ6kpLlXCuSBUZ/tfkdxp"
147                 + "uzhYq/Sc7A8csIk9gDf9RUbrhK0qKw0VP6DoCIJjS5IeN+NeJkx8YjmzLPmZqLYbNPXr/hy8CRrR"
148                 + "6CqLTTSkBwoEJ+cDkfZrdH2/bND0FEIZAgMBAAGjgfYwgfMwCQYDVR0TBAIwADAsBglghkgBhvhC"
149                 + "AQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFFSZXv0I5bG7XPEw"
150                 + "jylwG3lmZGdiMIGYBgNVHSMEgZAwgY2AFL/FsHHolGIMacU1TZW/88Bd2EL6oWqkaDBmMQswCQYD"
151                 + "VQQGEwJERTEPMA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx"
152                 + "FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyggkAuBIOAWJ19mwwDQYJKoZI"
153                 + "hvcNAQEEBQADgYEAUiUh/wORVcQYXxIh13h3w2Btg6Kj2g6V6YO0Utc/gEYWwT310C2OuroKAwwo"
154                 + "HapMIIWiJRclIAiA8Hnb0Sv/puuHYD4G4NWFdiVjRord90eZJe40NMGruRmlqIRIGGKCv+wv3E6U"
155                 + "x1cWW862f5H9Eyrcocke2P+3GNAGy83vghA="
156             );
157         CertificateFactory factory = 
158             CertificateFactory.getInstance("X.509", "BC");
159         X509Certificate cert = 
160             (X509Certificate)factory.generateCertificate(
161                 new java.io.ByteArrayInputStream(certBytes)
162             );
163 
164         WSSecEncrypt encrypt = new WSSecEncrypt();
165         encrypt.setUseThisCert(cert);
166         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
167         WSSecHeader secHeader = new WSSecHeader();
168         secHeader.insertSecurityHeader(doc);
169         Document encryptedDoc = encrypt.build(doc, crypto, secHeader);
170         
171         if (LOG.isDebugEnabled()) {
172             String outputString = 
173                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
174             LOG.debug(outputString);
175         }
176         try {
177             verify(encryptedDoc);
178             fail("Failure expected on encryption with a key that does not exist in the keystore");
179         } catch (Exception ex) {
180             // expected
181         }
182         
183     }
184     
185     /**
186      * Verifies the soap envelope
187      * <p/>
188      * 
189      * @param doc 
190      * @throws Exception Thrown when there is a problem in verification
191      */
192     private void verify(Document doc) throws Exception {
193         secEngine.processSecurityHeader(doc, null, callbackHandler, crypto);
194         if (LOG.isDebugEnabled()) {
195             LOG.debug("Verfied and decrypted message:");
196             String outputString = 
197                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
198             LOG.debug(outputString);
199         }
200     }
201 
202 }