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.message;
21
22 import java.io.IOException;
23 import java.util.Collections;
24
25 import javax.crypto.KeyGenerator;
26 import javax.crypto.SecretKey;
27 import javax.security.auth.callback.Callback;
28 import javax.security.auth.callback.CallbackHandler;
29 import javax.security.auth.callback.UnsupportedCallbackException;
30 import javax.xml.crypto.dsig.SignatureMethod;
31
32 import org.apache.wss4j.common.util.SOAPUtil;
33 import org.apache.wss4j.dom.WSConstants;
34 import org.apache.wss4j.dom.common.CustomHandler;
35 import org.apache.wss4j.dom.common.KeystoreCallbackHandler;
36 import org.apache.wss4j.dom.common.SecretKeyCallbackHandler;
37
38 import org.apache.wss4j.dom.engine.WSSConfig;
39 import org.apache.wss4j.dom.engine.WSSecurityEngine;
40 import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
41 import org.apache.wss4j.common.crypto.Crypto;
42 import org.apache.wss4j.common.crypto.CryptoFactory;
43 import org.apache.wss4j.common.ext.WSPasswordCallback;
44 import org.apache.wss4j.common.util.KeyUtils;
45 import org.apache.wss4j.common.util.XMLUtils;
46 import org.apache.wss4j.dom.handler.HandlerAction;
47 import org.apache.wss4j.dom.handler.RequestData;
48 import org.apache.wss4j.dom.handler.WSHandlerConstants;
49 import org.apache.wss4j.dom.handler.WSHandlerResult;
50
51 import org.junit.jupiter.api.BeforeEach;
52 import org.junit.jupiter.api.Test;
53 import org.w3c.dom.Document;
54
55 import static org.junit.jupiter.api.Assertions.assertFalse;
56 import static org.junit.jupiter.api.Assertions.assertNotNull;
57 import static org.junit.jupiter.api.Assertions.assertNull;
58
59
60
61
62
63
64
65 public class SymmetricSignatureTest implements CallbackHandler {
66 private static final org.slf4j.Logger LOG =
67 org.slf4j.LoggerFactory.getLogger(SymmetricSignatureTest.class);
68 private WSSecurityEngine secEngine = new WSSecurityEngine();
69 private CallbackHandler callbackHandler = new KeystoreCallbackHandler();
70 private SecretKeyCallbackHandler secretKeyCallbackHandler = new SecretKeyCallbackHandler();
71 private byte[] keyData;
72 private Crypto crypto;
73
74 public SymmetricSignatureTest() throws Exception {
75 WSSConfig.init();
76 crypto = CryptoFactory.getInstance("wss40.properties");
77 }
78
79
80
81
82
83
84
85 @BeforeEach
86 public void setUp() throws Exception {
87 KeyGenerator keyGen = KeyGenerator.getInstance("AES");
88 keyGen.init(128);
89 SecretKey key = keyGen.generateKey();
90 keyData = key.getEncoded();
91 }
92
93
94
95
96 @Test
97 public void testSymmetricSignatureSHA1() throws Exception {
98 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
99
100 WSSecHeader secHeader = new WSSecHeader(doc);
101 secHeader.insertSecurityHeader();
102
103 WSSecSignature sign = new WSSecSignature(secHeader);
104 sign.setKeyIdentifierType(WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER);
105 sign.setSecretKey(keyData);
106 sign.setSignatureAlgorithm(SignatureMethod.HMAC_SHA1);
107
108 Document signedDoc = sign.build(crypto);
109
110 byte[] encodedBytes = KeyUtils.generateDigest(keyData);
111 String identifier = org.apache.xml.security.utils.XMLUtils.encodeToString(encodedBytes);
112 secretKeyCallbackHandler.addSecretKey(identifier, keyData);
113
114 if (LOG.isDebugEnabled()) {
115 LOG.debug("Signed symmetric message SHA1:");
116 String outputString =
117 XMLUtils.prettyDocumentToString(signedDoc);
118 LOG.debug(outputString);
119 }
120
121 secEngine.processSecurityHeader(doc, null, secretKeyCallbackHandler, null, crypto);
122 }
123
124
125
126
127
128
129 @Test
130 public void testSymmetricSignatureDR() throws Exception {
131 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
132
133 WSSecHeader secHeader = new WSSecHeader(doc);
134 secHeader.insertSecurityHeader();
135
136 WSSecEncryptedKey encrKey = new WSSecEncryptedKey(secHeader);
137 encrKey.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
138 encrKey.setUserInfo("wss40", "security");
139
140 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_192);
141 SecretKey symmetricKey = keyGen.generateKey();
142 encrKey.prepare(crypto, symmetricKey);
143
144 WSSecSignature sign = new WSSecSignature(secHeader);
145 sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
146 sign.setCustomTokenId(encrKey.getId());
147 sign.setSecretKey(symmetricKey.getEncoded());
148 sign.setSignatureAlgorithm(SignatureMethod.HMAC_SHA1);
149 sign.setCustomTokenValueType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
150
151 Document signedDoc = sign.build(crypto);
152 encrKey.prependToHeader();
153
154 if (LOG.isDebugEnabled()) {
155 LOG.debug("Signed symmetric message DR:");
156 String outputString =
157 XMLUtils.prettyDocumentToString(signedDoc);
158 LOG.debug(outputString);
159 }
160
161 verify(signedDoc);
162 }
163
164
165
166
167
168
169
170
171 @Test
172 public void testEncryptedKeySignature() throws Exception {
173 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
174 LOG.info("Before Sign/Encryption....");
175
176 WSSecHeader secHeader = new WSSecHeader(doc);
177 secHeader.insertSecurityHeader();
178
179 WSSecEncryptedKey encrKey = new WSSecEncryptedKey(secHeader);
180 encrKey.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
181 encrKey.setUserInfo("wss40", "security");
182
183 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_192);
184 SecretKey symmetricKey = keyGen.generateKey();
185 encrKey.prepare(crypto, symmetricKey);
186
187 WSSecEncrypt encrypt = new WSSecEncrypt(secHeader);
188 encrypt.setEncKeyId(encrKey.getId());
189 encrypt.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
190 encrypt.setEncryptSymmKey(false);
191 encrypt.setEncryptedKeyElement(encrKey.getEncryptedKeyElement());
192
193 WSSecSignature sign = new WSSecSignature(secHeader);
194 sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
195 sign.setCustomTokenId(encrKey.getId());
196 sign.setCustomTokenValueType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
197 sign.setSecretKey(symmetricKey.getEncoded());
198 sign.setSignatureAlgorithm(SignatureMethod.HMAC_SHA1);
199
200 sign.build(crypto);
201 Document encryptedSignedDoc = encrypt.build(crypto, symmetricKey);
202
203 if (LOG.isDebugEnabled()) {
204 LOG.debug("Signed and encrypted message with IssuerSerial key identifier (both), 3DES:");
205 String outputString =
206 XMLUtils.prettyDocumentToString(encryptedSignedDoc);
207 LOG.debug(outputString);
208 }
209
210 LOG.info("After Sign/Encryption....");
211 verify(encryptedSignedDoc);
212 }
213
214
215
216
217
218 @Test
219 public void testSymmetricSignatureSHA1Handler() throws Exception {
220 final WSSConfig cfg = WSSConfig.getNewInstance();
221 RequestData reqData = new RequestData();
222 reqData.setWssConfig(cfg);
223 java.util.Map<String, Object> messageContext = new java.util.TreeMap<>();
224 messageContext.put(WSHandlerConstants.SIG_KEY_ID, "EncryptedKeySHA1");
225 messageContext.put(WSHandlerConstants.SIG_ALGO, SignatureMethod.HMAC_SHA1);
226 messageContext.put(WSHandlerConstants.PW_CALLBACK_REF, this);
227 reqData.setMsgContext(messageContext);
228 reqData.setUsername("");
229
230 final Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
231 CustomHandler handler = new CustomHandler();
232 HandlerAction action = new HandlerAction(WSConstants.SIGN);
233 handler.send(
234 doc,
235 reqData,
236 Collections.singletonList(action),
237 true
238 );
239
240 String outputString =
241 XMLUtils.prettyDocumentToString(doc);
242 if (LOG.isDebugEnabled()) {
243 LOG.debug(outputString);
244 }
245
246 reqData = new RequestData();
247 reqData.setWssConfig(WSSConfig.getNewInstance());
248 messageContext = new java.util.TreeMap<>();
249 messageContext.put(WSHandlerConstants.PW_CALLBACK_REF, this);
250 reqData.setMsgContext(messageContext);
251 reqData.setUsername("");
252
253 handler.receive(Collections.singletonList(WSConstants.SIGN), reqData);
254
255 secEngine.processSecurityHeader(doc, null, this, null, crypto);
256 }
257
258
259
260
261
262
263
264
265
266
267 @Test
268 public void testSymmetricSignatureIsNotReportedAsValidated() throws Exception {
269 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
270
271 WSSecHeader secHeader = new WSSecHeader(doc);
272 secHeader.insertSecurityHeader();
273
274 WSSecEncryptedKey encrKey = new WSSecEncryptedKey(secHeader);
275 encrKey.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
276 encrKey.setUserInfo("wss40", "security");
277
278 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_192);
279 SecretKey symmetricKey = keyGen.generateKey();
280 encrKey.prepare(crypto, symmetricKey);
281
282 WSSecSignature sign = new WSSecSignature(secHeader);
283 sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
284 sign.setCustomTokenId(encrKey.getId());
285 sign.setSecretKey(symmetricKey.getEncoded());
286 sign.setSignatureAlgorithm(SignatureMethod.HMAC_SHA1);
287 sign.setCustomTokenValueType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
288
289 Document signedDoc = sign.build(crypto);
290 encrKey.prependToHeader();
291
292 WSHandlerResult results = verify(signedDoc);
293
294 WSSecurityEngineResult actionResult =
295 results.getActionResults().get(WSConstants.SIGN).get(0);
296 assertNotNull(actionResult);
297
298
299 assertNotNull(actionResult.get(WSSecurityEngineResult.TAG_SECRET));
300 assertNull(actionResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES));
301 assertNull(actionResult.get(WSSecurityEngineResult.TAG_PUBLIC_KEY));
302
303 assertFalse((Boolean)actionResult.get(WSSecurityEngineResult.TAG_VALIDATED_TOKEN),
304 "A signature keyed by an EncryptedKey secret must not be reported as a "
305 + "validated token: no trust decision was taken on the key");
306 }
307
308
309
310
311
312
313
314
315 private WSHandlerResult verify(Document doc) throws Exception {
316 WSHandlerResult results =
317 secEngine.processSecurityHeader(doc, null, callbackHandler, null, crypto);
318 if (LOG.isDebugEnabled()) {
319 LOG.debug("Verfied and decrypted message:");
320 String outputString =
321 XMLUtils.prettyDocumentToString(doc);
322 LOG.debug(outputString);
323 }
324 return results;
325 }
326
327 public void handle(Callback[] callbacks)
328 throws IOException, UnsupportedCallbackException {
329 for (Callback callback : callbacks) {
330 if (callback instanceof WSPasswordCallback) {
331 WSPasswordCallback pc = (WSPasswordCallback) callback;
332
333
334
335
336
337
338 pc.setPassword("security");
339 pc.setKey(keyData);
340 } else {
341 throw new UnsupportedCallbackException(callback, "Unrecognized Callback");
342 }
343 }
344 }
345
346
347 }