1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.dom.components.crypto;
21
22 import org.apache.wss4j.common.util.SOAPUtil;
23 import org.apache.wss4j.dom.WSConstants;
24 import org.apache.wss4j.dom.common.KeystoreCallbackHandler;
25
26 import org.apache.wss4j.dom.engine.WSSecurityEngine;
27 import org.apache.wss4j.common.crypto.Crypto;
28 import org.apache.wss4j.common.crypto.CryptoFactory;
29 import org.apache.wss4j.common.ext.WSSecurityException;
30 import org.apache.wss4j.common.util.KeyUtils;
31 import org.apache.wss4j.common.util.XMLUtils;
32 import org.apache.wss4j.dom.message.WSSecEncrypt;
33 import org.apache.wss4j.dom.message.WSSecHeader;
34 import org.apache.wss4j.dom.message.WSSecSignature;
35 import org.bouncycastle.jce.provider.BouncyCastleProvider;
36
37 import org.junit.jupiter.api.Test;
38 import org.w3c.dom.Document;
39
40 import javax.crypto.KeyGenerator;
41 import javax.crypto.SecretKey;
42 import javax.security.auth.callback.CallbackHandler;
43 import javax.xml.parsers.DocumentBuilderFactory;
44
45 import java.io.ByteArrayInputStream;
46 import java.io.InputStream;
47 import java.security.Security;
48 import java.security.cert.CertificateFactory;
49 import java.security.cert.X509Certificate;
50
51 import static org.junit.jupiter.api.Assertions.assertTrue;
52 import static org.junit.jupiter.api.Assertions.fail;
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 public class CryptoProviderTest {
68 private static final org.slf4j.Logger LOG =
69 org.slf4j.LoggerFactory.getLogger(CryptoProviderTest.class);
70 private WSSecurityEngine secEngine = new WSSecurityEngine();
71 private CallbackHandler callbackHandler = new KeystoreCallbackHandler();
72 private Crypto crypto;
73
74 public CryptoProviderTest() throws Exception {
75 secEngine.getWssConfig();
76 crypto = CryptoFactory.getInstance("wss86.properties");
77 }
78
79
80
81
82 @Test
83 public void testSignatureOID() throws Exception {
84 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
85 WSSecHeader secHeader = new WSSecHeader(doc);
86 secHeader.insertSecurityHeader();
87
88 WSSecSignature sign = new WSSecSignature(secHeader);
89 sign.setUserInfo("wss86", "security");
90 sign.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
91
92 Document signedDoc = sign.build(crypto);
93
94 if (LOG.isDebugEnabled()) {
95 String outputString =
96 XMLUtils.prettyDocumentToString(signedDoc);
97 LOG.debug(outputString);
98 }
99 verify(signedDoc);
100 }
101
102
103
104
105
106 @Test
107 public void testSignatureEmailAddress() throws Exception {
108 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
109 WSSecHeader secHeader = new WSSecHeader(doc);
110 secHeader.insertSecurityHeader();
111
112 WSSecSignature sign = new WSSecSignature(secHeader);
113 sign.setUserInfo("wss86", "security");
114 sign.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
115
116 Document signedDoc = sign.build(crypto);
117
118 String outputString = XMLUtils.prettyDocumentToString(signedDoc);
119 outputString =
120 outputString.replace("1.2.840.113549.1.9.1=#16125765726e6572406578616d706c652e636f6d",
121 "EMAILADDRESS=Werner@example.com");
122
123 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
124 dbf.setNamespaceAware(true);
125 InputStream is = new ByteArrayInputStream(outputString.getBytes());
126 Document parsedDoc = dbf.newDocumentBuilder().parse(is);
127 verify(parsedDoc);
128 }
129
130
131
132
133
134 @Test
135 public void testSignatureOtherEmailAddress() throws Exception {
136 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
137 WSSecHeader secHeader = new WSSecHeader(doc);
138 secHeader.insertSecurityHeader();
139
140 WSSecSignature sign = new WSSecSignature(secHeader);
141 sign.setUserInfo("wss86", "security");
142 sign.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
143
144 Document signedDoc = sign.build(crypto);
145
146 String outputString = XMLUtils.prettyDocumentToString(signedDoc);
147 outputString =
148 outputString.replace("1.2.840.113549.1.9.1=#16125765726e6572406578616d706c652e636f6d",
149 "E=Werner@example.com");
150
151 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
152 dbf.setNamespaceAware(true);
153 InputStream is = new ByteArrayInputStream(outputString.getBytes());
154 Document parsedDoc = dbf.newDocumentBuilder().parse(is);
155 verify(parsedDoc);
156 }
157
158
159
160
161
162 @Test
163 public void testInterop() throws Exception {
164
165
166
167
168
169 byte[] certBytes =
170 org.apache.xml.security.utils.XMLUtils.decode(
171 "MIIDrjCCApagAwIBAgIJAI24r1w1fl4NMA0GCSqGSIb3DQEBCwUAMIGEMQswCQYD"
172 + "VQQGEwJERTEPMA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDzANBgNV"
173 + "BAoTBkFwYWNoZTEOMAwGA1UECxMFV1NTNEoxDzANBgNVBAMTBldlcm5lcjEhMB8G"
174 + "CSqGSIb3DQEJARYSV2VybmVyQGV4YW1wbGUuY29tMB4XDTI1MTAyMTE1NDIxMloX"
175 + "DTM1MTAxOTE1NDIxMlowgYQxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIEwZCYXllcm4x"
176 + "DzANBgNVBAcTBk11bmljaDEPMA0GA1UEChMGQXBhY2hlMQ4wDAYDVQQLEwVXU1M0"
177 + "SjEPMA0GA1UEAxMGV2VybmVyMSEwHwYJKoZIhvcNAQkBFhJXZXJuZXJAZXhhbXBs"
178 + "ZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDF1KvvhxPjBiwd"
179 + "VhN4xwpG4p9jApIaH5w301+loJzqrwI8LfXyx0c3TQE0XYj9lFbeGfkia/mKSaSZ"
180 + "ZJC51+AMyK1l77Q/XlSuOzQRzYekUnOYlsg6Mcjn1Vb/+FWnMpjbm5W8cAHJFnKv"
181 + "pa9eOQvHSh+yZr23Q9kgUCUR2O9i89aNLeu2WbAkR1V+roI8LRgvODMET0eUZoir"
182 + "kgwfJNFsJjNr4R2TTVS4l2oHC1surIrUVq6HMEqKyg+eMaQuec/gzRHUqEWFNr4y"
183 + "Nt22qCXLwwUH3TGhpNMMbaS216g73k+/B922Jv4vqzPHCd/FwdNzMwTr0dyImO6/"
184 + "YUUsdQNhAgMBAAGjITAfMB0GA1UdDgQWBBRq1468SE5Zz9f7R5xZBpNdJ7nk8TAN"
185 + "BgkqhkiG9w0BAQsFAAOCAQEAKzu9gO9f6qALkdHSEc1oKjBF/YZaPde4eu/0W21K"
186 + "RfLnz62YKrccBaO1fWTJuWOzRr1bVat+accqr1TePFf48Qgbi76/3n4VPvOpxtbJ"
187 + "+o3bboG+I8mA3tPeIWo73QgzEm2lrmKX8fO4PoZV6TkIshKjADmbntVmolqQ2Z4Z"
188 + "i+cz0Ho95I9SuvA9jZJPDU4bIRTT1wY9e5I3mYGRO9xHCqN6ajCpdi2MG4ArI3fs"
189 + "7fr2a5F5R8AaT8AMPBwMsEXEGj7EUl6JZP8y0BMTW5yvvEfkIM1/DIapyirfaWSS"
190 + "ynZemU0RvqAPch3ESCo6BhxAt9TzOIQ9wvTqQhYa0SzOHg=="
191 );
192
193 try {
194 Security.addProvider(new BouncyCastleProvider());
195 CertificateFactory factory =
196 CertificateFactory.getInstance("X.509", "BC");
197 X509Certificate cert =
198 (X509Certificate)factory.generateCertificate(
199 new ByteArrayInputStream(certBytes)
200 );
201
202 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
203 WSSecHeader secHeader = new WSSecHeader(doc);
204 secHeader.insertSecurityHeader();
205
206 WSSecEncrypt encrypt = new WSSecEncrypt(secHeader);
207 encrypt.setUseThisCert(cert);
208
209 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_128);
210 SecretKey symmetricKey = keyGen.generateKey();
211 Document encryptedDoc = encrypt.build(crypto, symmetricKey);
212
213 if (LOG.isDebugEnabled()) {
214 String outputString =
215 XMLUtils.prettyDocumentToString(encryptedDoc);
216 LOG.debug(outputString);
217 }
218 verify(encryptedDoc);
219 } finally {
220 Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
221 }
222
223 }
224
225
226
227
228
229
230
231 @Test
232 public void testBadInterop() throws Exception {
233 byte[] certBytes =
234 org.apache.xml.security.utils.XMLUtils.decode(
235 "MIIDNDCCAp2gAwIBAgIBEDANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEPMA0GA1UECBMG"
236 + "QmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUxFTATBgNVBAsTDEFwYWNoZSBX"
237 + "U1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA4MDQwNDE5MzIxOFoXDTEwMDQwNDE5MzIxOFowYTEL"
238 + "MAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZB"
239 + "cGFjaGUxDjAMBgNVBAsTBVdTUzRKMQ8wDQYDVQQDEwZXZXJuZXIwgZ8wDQYJKoZIhvcNAQEBBQAD"
240 + "gY0AMIGJAoGBAINlL3/k0H/zvknpBtLo8jzXwx/IJU/CGSv6MsqJZ2fyZ6kpLlXCuSBUZ/tfkdxp"
241 + "uzhYq/Sc7A8csIk9gDf9RUbrhK0qKw0VP6DoCIJjS5IeN+NeJkx8YjmzLPmZqLYbNPXr/hy8CRrR"
242 + "6CqLTTSkBwoEJ+cDkfZrdH2/bND0FEIZAgMBAAGjgfYwgfMwCQYDVR0TBAIwADAsBglghkgBhvhC"
243 + "AQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFFSZXv0I5bG7XPEw"
244 + "jylwG3lmZGdiMIGYBgNVHSMEgZAwgY2AFL/FsHHolGIMacU1TZW/88Bd2EL6oWqkaDBmMQswCQYD"
245 + "VQQGEwJERTEPMA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx"
246 + "FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyggkAuBIOAWJ19mwwDQYJKoZI"
247 + "hvcNAQEEBQADgYEAUiUh/wORVcQYXxIh13h3w2Btg6Kj2g6V6YO0Utc/gEYWwT310C2OuroKAwwo"
248 + "HapMIIWiJRclIAiA8Hnb0Sv/puuHYD4G4NWFdiVjRord90eZJe40NMGruRmlqIRIGGKCv+wv3E6U"
249 + "x1cWW862f5H9Eyrcocke2P+3GNAGy83vghA="
250 );
251
252 try {
253 Security.addProvider(new BouncyCastleProvider());
254 CertificateFactory factory =
255 CertificateFactory.getInstance("X.509", "BC");
256 X509Certificate cert =
257 (X509Certificate)factory.generateCertificate(
258 new ByteArrayInputStream(certBytes)
259 );
260
261 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
262 WSSecHeader secHeader = new WSSecHeader(doc);
263 secHeader.insertSecurityHeader();
264
265 WSSecEncrypt encrypt = new WSSecEncrypt(secHeader);
266 encrypt.setUseThisCert(cert);
267
268 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_128);
269 SecretKey symmetricKey = keyGen.generateKey();
270 Document encryptedDoc = encrypt.build(crypto, symmetricKey);
271
272 if (LOG.isDebugEnabled()) {
273 String outputString =
274 XMLUtils.prettyDocumentToString(encryptedDoc);
275 LOG.debug(outputString);
276 }
277 try {
278 verify(encryptedDoc);
279 fail("Failure expected on encryption with a key that does not exist in the keystore");
280 } catch (WSSecurityException ex) {
281 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILURE);
282 }
283 } finally {
284 Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
285 }
286 }
287
288
289
290
291
292
293
294
295 private void verify(Document doc) throws Exception {
296 secEngine.processSecurityHeader(doc, null, callbackHandler, crypto);
297 if (LOG.isDebugEnabled()) {
298 LOG.debug("Verfied and decrypted message:");
299 String outputString =
300 XMLUtils.prettyDocumentToString(doc);
301 LOG.debug(outputString);
302 }
303 }
304
305 }