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.NoSuchProviderException;
23 import java.security.Provider;
24 import java.util.List;
25
26 import javax.xml.crypto.XMLStructure;
27 import javax.xml.crypto.dom.DOMStructure;
28 import javax.xml.crypto.dsig.CanonicalizationMethod;
29 import javax.xml.crypto.dsig.SignatureMethod;
30 import javax.xml.crypto.dsig.SignedInfo;
31 import javax.xml.crypto.dsig.XMLSignContext;
32 import javax.xml.crypto.dsig.XMLSignature;
33 import javax.xml.crypto.dsig.XMLSignatureFactory;
34 import javax.xml.crypto.dsig.dom.DOMSignContext;
35 import javax.xml.crypto.dsig.keyinfo.KeyInfo;
36 import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
37 import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
38 import javax.xml.crypto.dsig.spec.ExcC14NParameterSpec;
39
40 import org.w3c.dom.Document;
41 import org.w3c.dom.Element;
42
43 import org.apache.wss4j.common.WSEncryptionPart;
44 import org.apache.wss4j.common.derivedKey.ConversationConstants;
45 import org.apache.wss4j.common.ext.WSSecurityException;
46 import org.apache.wss4j.common.token.Reference;
47 import org.apache.wss4j.common.token.SecurityTokenReference;
48 import org.apache.wss4j.common.util.KeyUtils;
49 import org.apache.wss4j.common.util.XMLUtils;
50 import org.apache.wss4j.dom.WSConstants;
51 import org.apache.wss4j.dom.WSDocInfo;
52 import org.apache.wss4j.dom.transform.STRTransform;
53 import org.apache.wss4j.dom.util.WSSecurityUtil;
54
55
56
57
58 public class WSSecDKSign extends WSSecDerivedKeyBase {
59
60 private static final org.slf4j.Logger LOG =
61 org.slf4j.LoggerFactory.getLogger(WSSecDKSign.class);
62
63 private String sigAlgo = WSConstants.HMAC_SHA1;
64 private String digestAlgo = WSConstants.SHA1;
65 private String canonAlgo = WSConstants.C14N_EXCL_OMIT_COMMENTS;
66 private byte[] signatureValue;
67
68 private String keyInfoUri;
69 private SecurityTokenReference secRef;
70 private String strUri;
71 private WSDocInfo wsDocInfo;
72
73 private XMLSignatureFactory signatureFactory;
74 private XMLSignature sig;
75 private KeyInfo keyInfo;
76 private CanonicalizationMethod c14nMethod;
77 private int derivedKeyLength = -1;
78 private boolean addInclusivePrefixes = true;
79
80 public WSSecDKSign(WSSecHeader securityHeader) {
81 super(securityHeader);
82 init(null);
83 }
84
85 public WSSecDKSign(Document doc) {
86 this(doc, null);
87 }
88
89 public WSSecDKSign(Document doc, Provider provider) {
90 super(doc);
91 init(provider);
92 }
93
94 private void init(Provider provider) {
95 if (provider == null) {
96
97
98 try {
99 signatureFactory = XMLSignatureFactory.getInstance("DOM", "ApacheXMLDSig");
100 } catch (NoSuchProviderException ex) {
101 signatureFactory = XMLSignatureFactory.getInstance("DOM");
102 }
103 } else {
104 signatureFactory = XMLSignatureFactory.getInstance("DOM", provider);
105 }
106 }
107
108 public Document build(byte[] ephemeralKey) throws WSSecurityException {
109
110 prepare(ephemeralKey);
111 if (getParts().isEmpty()) {
112 getParts().add(WSSecurityUtil.getDefaultEncryptionPart(getDocument()));
113 } else {
114 for (WSEncryptionPart part : getParts()) {
115 if ("STRTransform".equals(part.getName()) && part.getId() == null) {
116 part.setId(strUri);
117 }
118 }
119 }
120
121 List<javax.xml.crypto.dsig.Reference> referenceList = addReferencesToSign(getParts());
122 computeSignature(referenceList);
123
124
125
126
127 prependDKElementToHeader();
128
129 return getDocument();
130 }
131
132 public void prepare(byte[] ephemeralKey) throws WSSecurityException {
133 super.prepare(ephemeralKey);
134 wsDocInfo = new WSDocInfo(getDocument());
135 sig = null;
136
137 try {
138 C14NMethodParameterSpec c14nSpec = null;
139 if (addInclusivePrefixes && canonAlgo.equals(WSConstants.C14N_EXCL_OMIT_COMMENTS)) {
140 Element securityHeaderElement = getSecurityHeader().getSecurityHeaderElement();
141 List<String> prefixes =
142 getInclusivePrefixes(securityHeaderElement, false);
143 c14nSpec = new ExcC14NParameterSpec(prefixes);
144 }
145
146 c14nMethod = signatureFactory.newCanonicalizationMethod(canonAlgo, c14nSpec);
147 } catch (Exception ex) {
148 LOG.error("", ex);
149 throw new WSSecurityException(
150 WSSecurityException.ErrorCode.FAILED_SIGNATURE, ex, "noXMLSig"
151 );
152 }
153
154 keyInfoUri = getIdAllocator().createSecureId("KI-", keyInfo);
155
156 secRef = new SecurityTokenReference(getDocument());
157 strUri = getIdAllocator().createSecureId("STR-", secRef);
158 secRef.setID(strUri);
159 if (addWSUNamespace) {
160 secRef.addWSUNamespace();
161 }
162
163 Reference ref = new Reference(getDocument());
164 ref.setURI("#" + getId());
165 String ns =
166 ConversationConstants.getWSCNs(getWscVersion())
167 + ConversationConstants.TOKEN_TYPE_DERIVED_KEY_TOKEN;
168 ref.setValueType(ns);
169 secRef.setReference(ref);
170
171 XMLStructure structure = new DOMStructure(secRef.getElement());
172 wsDocInfo.addTokenElement(secRef.getElement(), false);
173 KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();
174 keyInfo =
175 keyInfoFactory.newKeyInfo(
176 java.util.Collections.singletonList(structure), keyInfoUri
177 );
178
179 }
180
181
182
183
184
185
186 public Element getSignatureElement() {
187 Element securityHeaderElement = getSecurityHeader().getSecurityHeaderElement();
188 return
189 XMLUtils.getDirectChildElement(
190 securityHeaderElement, WSConstants.SIG_LN, WSConstants.SIG_NS
191 );
192 }
193
194
195
196
197
198
199
200 public List<javax.xml.crypto.dsig.Reference> addReferencesToSign(
201 List<WSEncryptionPart> references
202 ) throws WSSecurityException {
203 return
204 addReferencesToSign(
205 getDocument(),
206 references,
207 wsDocInfo,
208 signatureFactory,
209 addInclusivePrefixes,
210 digestAlgo
211 );
212 }
213
214
215
216
217
218
219
220
221
222
223 public void computeSignature(
224 List<javax.xml.crypto.dsig.Reference> referenceList
225 ) throws WSSecurityException {
226 computeSignature(referenceList, true, null);
227 }
228
229
230
231
232
233
234
235
236
237
238 public void computeSignature(
239 List<javax.xml.crypto.dsig.Reference> referenceList,
240 boolean prepend,
241 Element siblingElement
242 ) throws WSSecurityException {
243 try {
244 java.security.Key key = getDerivedKey(sigAlgo);
245 SignatureMethod signatureMethod =
246 signatureFactory.newSignatureMethod(sigAlgo, null);
247 SignedInfo signedInfo =
248 signatureFactory.newSignedInfo(c14nMethod, signatureMethod, referenceList);
249
250 sig = signatureFactory.newXMLSignature(
251 signedInfo,
252 keyInfo,
253 null,
254 getIdAllocator().createId("SIG-", null),
255 null);
256
257
258
259
260 XMLSignContext signContext = null;
261 Element securityHeaderElement = getSecurityHeader().getSecurityHeaderElement();
262 if (prepend) {
263 if (siblingElement == null) {
264 siblingElement = (Element)securityHeaderElement.getFirstChild();
265 }
266 if (siblingElement == null) {
267 signContext = new DOMSignContext(key, securityHeaderElement);
268 } else {
269 signContext = new DOMSignContext(key, securityHeaderElement, siblingElement);
270 }
271 } else {
272 signContext = new DOMSignContext(key, securityHeaderElement);
273 }
274
275 signContext.putNamespacePrefix(WSConstants.SIG_NS, WSConstants.SIG_PREFIX);
276 if (WSConstants.C14N_EXCL_OMIT_COMMENTS.equals(canonAlgo)) {
277 signContext.putNamespacePrefix(
278 WSConstants.C14N_EXCL_OMIT_COMMENTS,
279 WSConstants.C14N_EXCL_OMIT_COMMENTS_PREFIX
280 );
281 }
282 signContext.setProperty(STRTransform.TRANSFORM_WS_DOC_INFO, wsDocInfo);
283 wsDocInfo.setCallbackLookup(callbackLookup);
284
285
286 wsDocInfo.setTokensOnContext((DOMSignContext)signContext);
287
288 sig.sign(signContext);
289
290 signatureValue = sig.getSignatureValue().getValue();
291 } catch (Exception ex) {
292 LOG.error(ex.getMessage(), ex);
293 throw new WSSecurityException(
294 WSSecurityException.ErrorCode.FAILED_SIGNATURE, ex
295 );
296 }
297 }
298
299 protected int getDerivedKeyLength() throws WSSecurityException {
300 return derivedKeyLength > 0 ? derivedKeyLength : KeyUtils.getKeyLength(sigAlgo);
301 }
302
303 public void setDerivedKeyLength(int keyLength) {
304 derivedKeyLength = keyLength;
305 }
306
307
308
309
310
311 public void setSignatureAlgorithm(String algorithm) {
312 sigAlgo = algorithm;
313 }
314
315
316
317
318 public String getSignatureAlgorithm() {
319 return sigAlgo;
320 }
321
322
323
324
325
326
327 public String getSignatureId() {
328 if (sig == null) {
329 return null;
330 }
331 return sig.getId();
332 }
333
334
335
336
337
338 public void setDigestAlgorithm(String algorithm) {
339 digestAlgo = algorithm;
340 }
341
342
343
344
345 public String getDigestAlgorithm() {
346 return digestAlgo;
347 }
348
349
350
351
352 public byte[] getSignatureValue() {
353 return signatureValue;
354 }
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369 public void setSigCanonicalization(String algo) {
370 canonAlgo = algo;
371 }
372
373
374
375
376
377
378
379
380
381 public String getSigCanonicalization() {
382 return canonAlgo;
383 }
384
385 public boolean isAddInclusivePrefixes() {
386 return addInclusivePrefixes;
387 }
388
389 public void setAddInclusivePrefixes(boolean addInclusivePrefixes) {
390 this.addInclusivePrefixes = addInclusivePrefixes;
391 }
392 }