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.security.Provider;
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import javax.crypto.SecretKey;
27 import javax.crypto.spec.SecretKeySpec;
28 import javax.security.auth.DestroyFailedException;
29
30 import org.apache.wss4j.common.WSEncryptionPart;
31 import org.apache.wss4j.common.crypto.Crypto;
32 import org.apache.wss4j.common.ext.WSSecurityException;
33 import org.apache.wss4j.common.token.Reference;
34 import org.apache.wss4j.common.token.SecurityTokenReference;
35 import org.apache.wss4j.common.util.FIPSUtils;
36 import org.apache.wss4j.common.util.XMLUtils;
37 import org.apache.wss4j.dom.WSConstants;
38 import org.apache.wss4j.dom.message.token.KerberosSecurity;
39 import org.apache.wss4j.dom.util.WSSecurityUtil;
40 import org.apache.xml.security.algorithms.JCEMapper;
41 import org.apache.xml.security.encryption.Serializer;
42 import org.apache.xml.security.keys.KeyInfo;
43 import org.w3c.dom.Document;
44 import org.w3c.dom.Element;
45
46
47
48
49
50 public class WSSecEncrypt extends WSSecEncryptedKey {
51 private static final org.slf4j.Logger LOG =
52 org.slf4j.LoggerFactory.getLogger(WSSecEncrypt.class);
53
54
55
56
57 private SecurityTokenReference securityTokenReference;
58
59
60
61
62
63 private boolean encryptSymmKey = true;
64
65
66
67
68 private String customReferenceValue;
69
70
71
72
73 private boolean encKeyIdDirectId;
74
75 private boolean embedEncryptedKey;
76
77 private List<Element> attachmentEncryptedDataElements;
78
79 private Serializer encryptionSerializer;
80
81
82
83
84 private String symEncAlgo = FIPSUtils.isFIPSEnabled()
85 ? WSConstants.AES_128_GCM : WSConstants.AES_128;
86
87 public WSSecEncrypt(WSSecHeader securityHeader) {
88 super(securityHeader);
89 }
90
91 public WSSecEncrypt(Document doc) {
92 super(doc);
93 }
94
95 public WSSecEncrypt(Document doc, Provider provider) {
96 super(doc, provider);
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113 public void prepare(Crypto crypto, SecretKey symmetricKey) throws WSSecurityException {
114 attachmentEncryptedDataElements = new ArrayList<>();
115
116 if (encryptSymmKey) {
117 super.prepare(crypto, symmetricKey);
118 } else {
119 setEncryptedKeySHA1(symmetricKey.getEncoded());
120 }
121 }
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 public Document build(Crypto crypto, SecretKey symmetricKey)
137 throws WSSecurityException {
138
139 prepare(crypto, symmetricKey);
140
141 LOG.debug("Beginning Encryption...");
142
143 Element refs = encrypt(symmetricKey);
144
145 addAttachmentEncryptedDataElements();
146 if (getEncryptedKeyElement() != null) {
147 addInternalRefElement(refs);
148 prependToHeader();
149 } else {
150 addExternalRefElement(refs);
151 }
152
153 prependBSTElementToHeader();
154
155 LOG.debug("Encryption complete.");
156 return getDocument();
157 }
158
159
160
161
162
163
164
165 public Element encrypt(SecretKey symmetricKey) throws WSSecurityException {
166 if (getParts().isEmpty()) {
167 getParts().add(WSSecurityUtil.getDefaultEncryptionPart(getDocument()));
168 }
169
170 return encryptForRef(null, getParts(), symmetricKey);
171 }
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195 public Element encryptForRef(
196 Element dataRef,
197 List<WSEncryptionPart> references,
198 SecretKey symmetricKey
199 ) throws WSSecurityException {
200 KeyInfo keyInfo = createKeyInfo();
201
202
203
204 String keyAlgorithm = JCEMapper.getJCEKeyAlgorithmFromURI(getSymmetricEncAlgorithm());
205 SecretKeySpec secretKeySpec = new SecretKeySpec(symmetricKey.getEncoded(), keyAlgorithm);
206
207 Encryptor encryptor = new Encryptor();
208 encryptor.setDoc(getDocument());
209 encryptor.setSecurityHeader(getSecurityHeader());
210 encryptor.setIdAllocator(getIdAllocator());
211 encryptor.setCallbackLookup(callbackLookup);
212 encryptor.setAttachmentCallbackHandler(attachmentCallbackHandler);
213 encryptor.setStoreBytesInAttachment(storeBytesInAttachment);
214 encryptor.setEncryptionSerializer(getEncryptionSerializer());
215 encryptor.setExpandXopInclude(isExpandXopInclude());
216 encryptor.setWsDocInfo(getWsDocInfo());
217 List<String> encDataRefs =
218 encryptor.doEncryption(keyInfo, secretKeySpec, getSymmetricEncAlgorithm(), references, attachmentEncryptedDataElements);
219
220
221 try {
222 secretKeySpec.destroy();
223 } catch (DestroyFailedException e) {
224 LOG.debug("Error destroying key: {}", e.getMessage());
225 }
226
227 if (encDataRefs.isEmpty()) {
228 return null;
229 }
230
231 if (dataRef == null) {
232 dataRef =
233 getDocument().createElementNS(
234 WSConstants.ENC_NS,
235 WSConstants.ENC_PREFIX + ":ReferenceList"
236 );
237
238
239
240
241 if (!encryptSymmKey) {
242 XMLUtils.setNamespace(
243 dataRef, WSConstants.ENC_NS, WSConstants.ENC_PREFIX
244 );
245 }
246 }
247 return createDataRefList(getDocument(), dataRef, encDataRefs);
248 }
249
250
251
252
253
254
255
256
257
258
259 public void addInternalRefElement(Element dataRef) {
260 if (dataRef != null) {
261 getEncryptedKeyElement().appendChild(dataRef);
262 }
263 }
264
265
266
267
268
269
270
271
272
273
274 public void addExternalRefElement(Element dataRef) {
275 if (dataRef != null) {
276 Element secHeaderElement = getSecurityHeader().getSecurityHeaderElement();
277 WSSecurityUtil.prependChildElement(secHeaderElement, dataRef);
278 }
279 }
280
281 public void addAttachmentEncryptedDataElements() {
282 if (attachmentEncryptedDataElements != null) {
283 for (Element encryptedData : attachmentEncryptedDataElements) {
284 Element secHeaderElement = getSecurityHeader().getSecurityHeaderElement();
285 WSSecurityUtil.prependChildElement(secHeaderElement, encryptedData);
286 }
287 }
288 }
289
290
291
292
293 private KeyInfo createKeyInfo() throws WSSecurityException {
294
295 KeyInfo keyInfo = new KeyInfo(getDocument());
296 if (embedEncryptedKey) {
297 keyInfo.addUnknownElement(getEncryptedKeyElement());
298 } else if (keyIdentifierType == WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER) {
299 SecurityTokenReference secToken = new SecurityTokenReference(getDocument());
300 if (addWSUNamespace) {
301 secToken.addWSUNamespace();
302 }
303 secToken.addWSSENamespace();
304 if (customReferenceValue != null) {
305 secToken.setKeyIdentifierEncKeySHA1(customReferenceValue);
306 } else {
307 secToken.setKeyIdentifierEncKeySHA1(getEncryptedKeySHA1());
308 }
309 secToken.addTokenType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
310 keyInfo.addUnknownElement(secToken.getElement());
311 } else if (WSConstants.WSS_SAML_KI_VALUE_TYPE.equals(customReferenceValue)) {
312 SecurityTokenReference secToken = new SecurityTokenReference(getDocument());
313 if (addWSUNamespace) {
314 secToken.addWSUNamespace();
315 }
316 secToken.addWSSENamespace();
317 secToken.addTokenType(WSConstants.WSS_SAML_TOKEN_TYPE);
318 secToken.setKeyIdentifier(WSConstants.WSS_SAML_KI_VALUE_TYPE, getId());
319 keyInfo.addUnknownElement(secToken.getElement());
320 } else if (WSConstants.WSS_SAML2_KI_VALUE_TYPE.equals(customReferenceValue)) {
321 SecurityTokenReference secToken = new SecurityTokenReference(getDocument());
322 if (addWSUNamespace) {
323 secToken.addWSUNamespace();
324 }
325 secToken.addWSSENamespace();
326 secToken.addTokenType(WSConstants.WSS_SAML2_TOKEN_TYPE);
327 secToken.setKeyIdentifier(WSConstants.WSS_SAML2_KI_VALUE_TYPE, getId());
328 keyInfo.addUnknownElement(secToken.getElement());
329 } else if (WSConstants.WSS_KRB_KI_VALUE_TYPE.equals(customReferenceValue)) {
330 SecurityTokenReference secToken = new SecurityTokenReference(getDocument());
331 if (addWSUNamespace) {
332 secToken.addWSUNamespace();
333 }
334 secToken.addWSSENamespace();
335 secToken.addTokenType(WSConstants.WSS_GSS_KRB_V5_AP_REQ);
336 secToken.setKeyIdentifier(customReferenceValue, getId(), true);
337 keyInfo.addUnknownElement(secToken.getElement());
338 } else if (securityTokenReference != null) {
339 Element tmpE = securityTokenReference.getElement();
340 tmpE.setAttributeNS(
341 WSConstants.XMLNS_NS, "xmlns:" + tmpE.getPrefix(), tmpE.getNamespaceURI()
342 );
343 keyInfo.addUnknownElement(securityTokenReference.getElement());
344 } else if (getId() != null) {
345 SecurityTokenReference secToken = new SecurityTokenReference(getDocument());
346 if (addWSUNamespace) {
347 secToken.addWSUNamespace();
348 }
349 secToken.addWSSENamespace();
350 Reference ref = new Reference(getDocument());
351 if (encKeyIdDirectId) {
352 ref.setURI(getId());
353 } else {
354 ref.setURI("#" + getId());
355 }
356 if (customReferenceValue != null) {
357 ref.setValueType(customReferenceValue);
358 }
359 secToken.setReference(ref);
360 if (KerberosSecurity.isKerberosToken(customReferenceValue)) {
361 secToken.addTokenType(customReferenceValue);
362 } else if (!WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE.equals(customReferenceValue)) {
363 secToken.addTokenType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
364 }
365 keyInfo.addUnknownElement(secToken.getElement());
366 } else if (!encryptSymmKey && (keyIdentifierType == WSConstants.ISSUER_SERIAL
367 || keyIdentifierType == WSConstants.ISSUER_SERIAL_QUOTE_FORMAT)) {
368 SecurityTokenReference secToken = new SecurityTokenReference(getDocument());
369 if (addWSUNamespace) {
370 secToken.addWSUNamespace();
371 }
372 secToken.addWSSENamespace();
373 if (customReferenceValue != null) {
374 secToken.setKeyIdentifierEncKeySHA1(customReferenceValue);
375 } else {
376 secToken.setKeyIdentifierEncKeySHA1(getEncryptedKeySHA1());
377 }
378 secToken.addTokenType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
379 keyInfo.addUnknownElement(secToken.getElement());
380 }
381
382 Element keyInfoElement = keyInfo.getElement();
383 keyInfoElement.setAttributeNS(
384 WSConstants.XMLNS_NS, "xmlns:" + WSConstants.SIG_PREFIX, WSConstants.SIG_NS
385 );
386
387 return keyInfo;
388 }
389
390
391
392
393
394
395
396
397
398 public static Element createDataRefList(
399 Document doc,
400 Element referenceList,
401 List<String> encDataRefs
402 ) {
403 for (String dataReferenceUri : encDataRefs) {
404 Element dataReference =
405 doc.createElementNS(
406 WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":DataReference"
407 );
408 dataReference.setAttributeNS(null, "URI", dataReferenceUri);
409 referenceList.appendChild(dataReference);
410 }
411 return referenceList;
412 }
413
414
415
416
417 public SecurityTokenReference getSecurityTokenReference() {
418 return securityTokenReference;
419 }
420
421
422
423
424 public void setSecurityTokenReference(SecurityTokenReference reference) {
425 securityTokenReference = reference;
426 }
427
428 public boolean isEncryptSymmKey() {
429 return encryptSymmKey;
430 }
431
432 public void setEncryptSymmKey(boolean encryptSymmKey) {
433 this.encryptSymmKey = encryptSymmKey;
434 }
435
436 public void setCustomReferenceValue(String customReferenceValue) {
437 this.customReferenceValue = customReferenceValue;
438 }
439
440 public void setEncKeyIdDirectId(boolean b) {
441 encKeyIdDirectId = b;
442 }
443
444 public void setEmbedEncryptedKey(boolean embedEncryptedKey) {
445 this.embedEncryptedKey = embedEncryptedKey;
446 }
447
448 public boolean isEmbedEncryptedKey() {
449 return embedEncryptedKey;
450 }
451
452 public List<Element> getAttachmentEncryptedDataElements() {
453 return attachmentEncryptedDataElements;
454 }
455
456 public Serializer getEncryptionSerializer() {
457 return encryptionSerializer;
458 }
459
460 public void setEncryptionSerializer(Serializer encryptionSerializer) {
461 this.encryptionSerializer = encryptionSerializer;
462 }
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477 public void setSymmetricEncAlgorithm(String algo) {
478 symEncAlgo = algo;
479 }
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494 public String getSymmetricEncAlgorithm() {
495 return symEncAlgo;
496 }
497
498 }