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