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 org.apache.ws.security.WSConstants;
23 import org.apache.ws.security.WSEncryptionPart;
24 import org.apache.ws.security.WSSConfig;
25 import org.apache.ws.security.WSSecurityException;
26 import org.apache.ws.security.conversation.ConversationException;
27 import org.apache.ws.security.message.token.Reference;
28 import org.apache.ws.security.message.token.SecurityTokenReference;
29 import org.apache.ws.security.util.WSSecurityUtil;
30 import org.apache.xml.security.keys.KeyInfo;
31 import org.w3c.dom.Document;
32 import org.w3c.dom.Element;
33 import org.w3c.dom.Node;
34
35 import javax.crypto.SecretKey;
36
37 import java.util.ArrayList;
38 import java.util.List;
39
40 /**
41 * Encrypts and signs parts of a message with derived keys derived from a
42 * symmetric key. This symmetric key will be included as an EncryptedKey
43 *
44 * @author Ruchith Fernando (ruchith.fernando@gmail.com)
45 */
46 public class WSSecDKEncrypt extends WSSecDerivedKeyBase {
47
48 protected String symEncAlgo = WSConstants.AES_128;
49
50 public WSSecDKEncrypt() {
51 super();
52 }
53 public WSSecDKEncrypt(WSSConfig config) {
54 super(config);
55 }
56
57 public Document build(Document doc, WSSecHeader secHeader)
58 throws WSSecurityException, ConversationException {
59
60 //
61 // Setup the encrypted key
62 //
63 prepare(doc);
64 envelope = doc.getDocumentElement();
65 //
66 // prepend elements in the right order to the security header
67 //
68 prependDKElementToHeader(secHeader);
69
70 String soapNamespace = WSSecurityUtil.getSOAPNamespace(envelope);
71 if (parts == null) {
72 parts = new ArrayList<WSEncryptionPart>(1);
73 WSEncryptionPart encP =
74 new WSEncryptionPart(
75 WSConstants.ELEM_BODY,
76 soapNamespace,
77 "Content"
78 );
79 parts.add(encP);
80 }
81 Element externRefList = encryptForExternalRef(null, parts);
82 addExternalRefElement(externRefList, secHeader);
83
84 return doc;
85 }
86
87 /**
88 * Encrypt one or more parts or elements of the message (external).
89 *
90 * This method takes a vector of <code>WSEncryptionPart</code> object that
91 * contain information about the elements to encrypt. The method call the
92 * encryption method, takes the reference information generated during
93 * encryption and add this to the <code>xenc:Reference</code> element.
94 * This method can be called after <code>prepare()</code> and can be
95 * called multiple times to encrypt a number of parts or elements.
96 *
97 * The method generates a <code>xenc:Reference</code> element that <i>must</i>
98 * be added to the SecurityHeader. See <code>addExternalRefElement()</code>.
99 *
100 * If the <code>dataRef</code> parameter is <code>null</code> the method
101 * creates and initializes a new Reference element.
102 *
103 * @param dataRef A <code>xenc:Reference</code> element or <code>null</code>
104 * @param references A list containing WSEncryptionPart objects
105 * @return Returns the updated <code>xenc:Reference</code> element
106 * @throws WSSecurityException
107 */
108 public Element encryptForExternalRef(Element dataRef, List<WSEncryptionPart> references)
109 throws WSSecurityException {
110
111 KeyInfo keyInfo = createKeyInfo();
112 SecretKey key = WSSecurityUtil.prepareSecretKey(symEncAlgo, derivedKeyBytes);
113
114 List<String> encDataRefs =
115 WSSecEncrypt.doEncryption(
116 document, getWsConfig(), keyInfo, key, symEncAlgo, references, callbackLookup
117 );
118 if (dataRef == null) {
119 dataRef =
120 document.createElementNS(
121 WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":ReferenceList"
122 );
123 }
124 return WSSecEncrypt.createDataRefList(document, dataRef, encDataRefs);
125 }
126
127 /**
128 * Create a KeyInfo object
129 */
130 private KeyInfo createKeyInfo() throws WSSecurityException {
131 KeyInfo keyInfo = new KeyInfo(document);
132 SecurityTokenReference secToken = new SecurityTokenReference(document);
133 secToken.addWSSENamespace();
134 Reference ref = new Reference(document);
135 ref.setURI("#" + dktId);
136 secToken.setReference(ref);
137
138 keyInfo.addUnknownElement(secToken.getElement());
139 Element keyInfoElement = keyInfo.getElement();
140 keyInfoElement.setAttributeNS(
141 WSConstants.XMLNS_NS, "xmlns:" + WSConstants.SIG_PREFIX, WSConstants.SIG_NS
142 );
143
144 return keyInfo;
145 }
146
147 /**
148 * Adds (prepends) the external Reference element to the Security header.
149 *
150 * The reference element <i>must</i> be created by the
151 * <code>encryptForExternalRef() </code> method. The method adds the
152 * reference element in the SecurityHeader.
153 *
154 * @param referenceList The external <code>enc:Reference</code> element
155 * @param secHeader The security header.
156 */
157 public void addExternalRefElement(Element referenceList, WSSecHeader secHeader) {
158 Node node = dkt.getElement().getNextSibling();
159 if (node != null && Node.ELEMENT_NODE == node.getNodeType()) {
160 secHeader.getSecurityHeader().insertBefore(referenceList, node);
161 } else {
162 // If (at this moment) DerivedKeyToken is the LAST element of
163 // the security header
164 secHeader.getSecurityHeader().appendChild(referenceList);
165 }
166 }
167
168
169 /**
170 * Set the symmetric encryption algorithm URI to use
171 * @param algo the symmetric encryption algorithm URI to use
172 */
173 public void setSymmetricEncAlgorithm(String algo) {
174 symEncAlgo = algo;
175 }
176
177 /**
178 * @see org.apache.ws.security.message.WSSecDerivedKeyBase#getDerivedKeyLength()
179 */
180 protected int getDerivedKeyLength() throws WSSecurityException{
181 return (derivedKeyLength > 0) ? derivedKeyLength :
182 WSSecurityUtil.getKeyLength(symEncAlgo);
183 }
184
185 }