1 /* |
|
2 * reserved comment block |
|
3 * DO NOT REMOVE OR ALTER! |
|
4 */ |
|
5 /** |
|
6 * Licensed to the Apache Software Foundation (ASF) under one |
|
7 * or more contributor license agreements. See the NOTICE file |
|
8 * distributed with this work for additional information |
|
9 * regarding copyright ownership. The ASF licenses this file |
|
10 * to you under the Apache License, Version 2.0 (the |
|
11 * "License"); you may not use this file except in compliance |
|
12 * with the License. You may obtain a copy of the License at |
|
13 * |
|
14 * http://www.apache.org/licenses/LICENSE-2.0 |
|
15 * |
|
16 * Unless required by applicable law or agreed to in writing, |
|
17 * software distributed under the License is distributed on an |
|
18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
|
19 * KIND, either express or implied. See the License for the |
|
20 * specific language governing permissions and limitations |
|
21 * under the License. |
|
22 */ |
|
23 package com.sun.org.apache.xml.internal.security.encryption; |
|
24 |
|
25 import java.io.ByteArrayOutputStream; |
|
26 import java.io.InputStream; |
|
27 import java.io.UnsupportedEncodingException; |
|
28 import java.net.URI; |
|
29 import java.net.URISyntaxException; |
|
30 import java.security.InvalidAlgorithmParameterException; |
|
31 import java.security.InvalidKeyException; |
|
32 import java.security.Key; |
|
33 import java.security.NoSuchAlgorithmException; |
|
34 import java.security.NoSuchProviderException; |
|
35 import java.security.SecureRandom; |
|
36 import java.security.spec.MGF1ParameterSpec; |
|
37 import java.util.ArrayList; |
|
38 import java.util.HashMap; |
|
39 import java.util.Iterator; |
|
40 import java.util.LinkedList; |
|
41 import java.util.List; |
|
42 import java.util.Map; |
|
43 |
|
44 import javax.crypto.BadPaddingException; |
|
45 import javax.crypto.Cipher; |
|
46 import javax.crypto.IllegalBlockSizeException; |
|
47 import javax.crypto.NoSuchPaddingException; |
|
48 import javax.crypto.spec.IvParameterSpec; |
|
49 import javax.crypto.spec.OAEPParameterSpec; |
|
50 import javax.crypto.spec.PSource; |
|
51 |
|
52 import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper; |
|
53 import com.sun.org.apache.xml.internal.security.algorithms.MessageDigestAlgorithm; |
|
54 import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; |
|
55 import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException; |
|
56 import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException; |
|
57 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; |
|
58 import com.sun.org.apache.xml.internal.security.keys.KeyInfo; |
|
59 import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverException; |
|
60 import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverSpi; |
|
61 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.EncryptedKeyResolver; |
|
62 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException; |
|
63 import com.sun.org.apache.xml.internal.security.transforms.InvalidTransformException; |
|
64 import com.sun.org.apache.xml.internal.security.transforms.TransformationException; |
|
65 import com.sun.org.apache.xml.internal.security.utils.Base64; |
|
66 import com.sun.org.apache.xml.internal.security.utils.Constants; |
|
67 import com.sun.org.apache.xml.internal.security.utils.ElementProxy; |
|
68 import com.sun.org.apache.xml.internal.security.utils.EncryptionConstants; |
|
69 import com.sun.org.apache.xml.internal.security.utils.XMLUtils; |
|
70 import org.w3c.dom.Attr; |
|
71 import org.w3c.dom.Document; |
|
72 import org.w3c.dom.Element; |
|
73 import org.w3c.dom.Node; |
|
74 import org.w3c.dom.NodeList; |
|
75 |
|
76 /** |
|
77 * <code>XMLCipher</code> encrypts and decrypts the contents of |
|
78 * <code>Document</code>s, <code>Element</code>s and <code>Element</code> |
|
79 * contents. It was designed to resemble <code>javax.crypto.Cipher</code> in |
|
80 * order to facilitate understanding of its functioning. |
|
81 * |
|
82 * @author Axl Mattheus (Sun Microsystems) |
|
83 * @author Christian Geuer-Pollmann |
|
84 */ |
|
85 public class XMLCipher { |
|
86 |
|
87 private static java.util.logging.Logger log = |
|
88 java.util.logging.Logger.getLogger(XMLCipher.class.getName()); |
|
89 |
|
90 /** Triple DES EDE (192 bit key) in CBC mode */ |
|
91 public static final String TRIPLEDES = |
|
92 EncryptionConstants.ALGO_ID_BLOCKCIPHER_TRIPLEDES; |
|
93 |
|
94 /** AES 128 Cipher */ |
|
95 public static final String AES_128 = |
|
96 EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128; |
|
97 |
|
98 /** AES 256 Cipher */ |
|
99 public static final String AES_256 = |
|
100 EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256; |
|
101 |
|
102 /** AES 192 Cipher */ |
|
103 public static final String AES_192 = |
|
104 EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192; |
|
105 |
|
106 /** AES 128 GCM Cipher */ |
|
107 public static final String AES_128_GCM = |
|
108 EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128_GCM; |
|
109 |
|
110 /** AES 192 GCM Cipher */ |
|
111 public static final String AES_192_GCM = |
|
112 EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192_GCM; |
|
113 |
|
114 /** AES 256 GCM Cipher */ |
|
115 public static final String AES_256_GCM = |
|
116 EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256_GCM; |
|
117 |
|
118 /** RSA 1.5 Cipher */ |
|
119 public static final String RSA_v1dot5 = |
|
120 EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15; |
|
121 |
|
122 /** RSA OAEP Cipher */ |
|
123 public static final String RSA_OAEP = |
|
124 EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP; |
|
125 |
|
126 /** RSA OAEP Cipher */ |
|
127 public static final String RSA_OAEP_11 = |
|
128 EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP_11; |
|
129 |
|
130 /** DIFFIE_HELLMAN Cipher */ |
|
131 public static final String DIFFIE_HELLMAN = |
|
132 EncryptionConstants.ALGO_ID_KEYAGREEMENT_DH; |
|
133 |
|
134 /** Triple DES EDE (192 bit key) in CBC mode KEYWRAP*/ |
|
135 public static final String TRIPLEDES_KeyWrap = |
|
136 EncryptionConstants.ALGO_ID_KEYWRAP_TRIPLEDES; |
|
137 |
|
138 /** AES 128 Cipher KeyWrap */ |
|
139 public static final String AES_128_KeyWrap = |
|
140 EncryptionConstants.ALGO_ID_KEYWRAP_AES128; |
|
141 |
|
142 /** AES 256 Cipher KeyWrap */ |
|
143 public static final String AES_256_KeyWrap = |
|
144 EncryptionConstants.ALGO_ID_KEYWRAP_AES256; |
|
145 |
|
146 /** AES 192 Cipher KeyWrap */ |
|
147 public static final String AES_192_KeyWrap = |
|
148 EncryptionConstants.ALGO_ID_KEYWRAP_AES192; |
|
149 |
|
150 /** SHA1 Cipher */ |
|
151 public static final String SHA1 = |
|
152 Constants.ALGO_ID_DIGEST_SHA1; |
|
153 |
|
154 /** SHA256 Cipher */ |
|
155 public static final String SHA256 = |
|
156 MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA256; |
|
157 |
|
158 /** SHA512 Cipher */ |
|
159 public static final String SHA512 = |
|
160 MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA512; |
|
161 |
|
162 /** RIPEMD Cipher */ |
|
163 public static final String RIPEMD_160 = |
|
164 MessageDigestAlgorithm.ALGO_ID_DIGEST_RIPEMD160; |
|
165 |
|
166 /** XML Signature NS */ |
|
167 public static final String XML_DSIG = |
|
168 Constants.SignatureSpecNS; |
|
169 |
|
170 /** N14C_XML */ |
|
171 public static final String N14C_XML = |
|
172 Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS; |
|
173 |
|
174 /** N14C_XML with comments*/ |
|
175 public static final String N14C_XML_WITH_COMMENTS = |
|
176 Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS; |
|
177 |
|
178 /** N14C_XML exclusive */ |
|
179 public static final String EXCL_XML_N14C = |
|
180 Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS; |
|
181 |
|
182 /** N14C_XML exclusive with comments*/ |
|
183 public static final String EXCL_XML_N14C_WITH_COMMENTS = |
|
184 Canonicalizer.ALGO_ID_C14N_EXCL_WITH_COMMENTS; |
|
185 |
|
186 /** N14C_PHYSICAL preserve the physical representation*/ |
|
187 public static final String PHYSICAL_XML_N14C = |
|
188 Canonicalizer.ALGO_ID_C14N_PHYSICAL; |
|
189 |
|
190 /** Base64 encoding */ |
|
191 public static final String BASE64_ENCODING = |
|
192 com.sun.org.apache.xml.internal.security.transforms.Transforms.TRANSFORM_BASE64_DECODE; |
|
193 |
|
194 /** ENCRYPT Mode */ |
|
195 public static final int ENCRYPT_MODE = Cipher.ENCRYPT_MODE; |
|
196 |
|
197 /** DECRYPT Mode */ |
|
198 public static final int DECRYPT_MODE = Cipher.DECRYPT_MODE; |
|
199 |
|
200 /** UNWRAP Mode */ |
|
201 public static final int UNWRAP_MODE = Cipher.UNWRAP_MODE; |
|
202 |
|
203 /** WRAP Mode */ |
|
204 public static final int WRAP_MODE = Cipher.WRAP_MODE; |
|
205 |
|
206 private static final String ENC_ALGORITHMS = TRIPLEDES + "\n" + |
|
207 AES_128 + "\n" + AES_256 + "\n" + AES_192 + "\n" + RSA_v1dot5 + "\n" + |
|
208 RSA_OAEP + "\n" + RSA_OAEP_11 + "\n" + TRIPLEDES_KeyWrap + "\n" + |
|
209 AES_128_KeyWrap + "\n" + AES_256_KeyWrap + "\n" + AES_192_KeyWrap + "\n" + |
|
210 AES_128_GCM + "\n" + AES_192_GCM + "\n" + AES_256_GCM + "\n"; |
|
211 |
|
212 /** Cipher created during initialisation that is used for encryption */ |
|
213 private Cipher contextCipher; |
|
214 |
|
215 /** Mode that the XMLCipher object is operating in */ |
|
216 private int cipherMode = Integer.MIN_VALUE; |
|
217 |
|
218 /** URI of algorithm that is being used for cryptographic operation */ |
|
219 private String algorithm = null; |
|
220 |
|
221 /** Cryptographic provider requested by caller */ |
|
222 private String requestedJCEProvider = null; |
|
223 |
|
224 /** Holds c14n to serialize, if initialized then _always_ use this c14n to serialize */ |
|
225 private Canonicalizer canon; |
|
226 |
|
227 /** Used for creation of DOM nodes in WRAP and ENCRYPT modes */ |
|
228 private Document contextDocument; |
|
229 |
|
230 /** Instance of factory used to create XML Encryption objects */ |
|
231 private Factory factory; |
|
232 |
|
233 /** Serializer class for going to/from UTF-8 */ |
|
234 private Serializer serializer; |
|
235 |
|
236 /** Local copy of user's key */ |
|
237 private Key key; |
|
238 |
|
239 /** Local copy of the kek (used to decrypt EncryptedKeys during a |
|
240 * DECRYPT_MODE operation */ |
|
241 private Key kek; |
|
242 |
|
243 // The EncryptedKey being built (part of a WRAP operation) or read |
|
244 // (part of an UNWRAP operation) |
|
245 private EncryptedKey ek; |
|
246 |
|
247 // The EncryptedData being built (part of a WRAP operation) or read |
|
248 // (part of an UNWRAP operation) |
|
249 private EncryptedData ed; |
|
250 |
|
251 private SecureRandom random; |
|
252 |
|
253 private boolean secureValidation; |
|
254 |
|
255 private String digestAlg; |
|
256 |
|
257 /** List of internal KeyResolvers for DECRYPT and UNWRAP modes. */ |
|
258 private List<KeyResolverSpi> internalKeyResolvers; |
|
259 |
|
260 /** |
|
261 * Set the Serializer algorithm to use |
|
262 */ |
|
263 public void setSerializer(Serializer serializer) { |
|
264 this.serializer = serializer; |
|
265 serializer.setCanonicalizer(this.canon); |
|
266 } |
|
267 |
|
268 /** |
|
269 * Get the Serializer algorithm to use |
|
270 */ |
|
271 public Serializer getSerializer() { |
|
272 return serializer; |
|
273 } |
|
274 |
|
275 /** |
|
276 * Creates a new <code>XMLCipher</code>. |
|
277 * |
|
278 * @param transformation the name of the transformation, e.g., |
|
279 * <code>XMLCipher.TRIPLEDES</code>. If null the XMLCipher can only |
|
280 * be used for decrypt or unwrap operations where the encryption method |
|
281 * is defined in the <code>EncryptionMethod</code> element. |
|
282 * @param provider the JCE provider that supplies the transformation, |
|
283 * if null use the default provider. |
|
284 * @param canon the name of the c14n algorithm, if |
|
285 * <code>null</code> use standard serializer |
|
286 * @param digestMethod An optional digestMethod to use. |
|
287 */ |
|
288 private XMLCipher( |
|
289 String transformation, |
|
290 String provider, |
|
291 String canonAlg, |
|
292 String digestMethod |
|
293 ) throws XMLEncryptionException { |
|
294 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
295 log.log(java.util.logging.Level.FINE, "Constructing XMLCipher..."); |
|
296 } |
|
297 |
|
298 factory = new Factory(); |
|
299 |
|
300 algorithm = transformation; |
|
301 requestedJCEProvider = provider; |
|
302 digestAlg = digestMethod; |
|
303 |
|
304 // Create a canonicalizer - used when serializing DOM to octets |
|
305 // prior to encryption (and for the reverse) |
|
306 |
|
307 try { |
|
308 if (canonAlg == null) { |
|
309 // The default is to preserve the physical representation. |
|
310 this.canon = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_PHYSICAL); |
|
311 } else { |
|
312 this.canon = Canonicalizer.getInstance(canonAlg); |
|
313 } |
|
314 } catch (InvalidCanonicalizerException ice) { |
|
315 throw new XMLEncryptionException("empty", ice); |
|
316 } |
|
317 |
|
318 if (serializer == null) { |
|
319 serializer = new DocumentSerializer(); |
|
320 } |
|
321 serializer.setCanonicalizer(this.canon); |
|
322 |
|
323 if (transformation != null) { |
|
324 contextCipher = constructCipher(transformation, digestMethod); |
|
325 } |
|
326 } |
|
327 |
|
328 /** |
|
329 * Checks to ensure that the supplied algorithm is valid. |
|
330 * |
|
331 * @param algorithm the algorithm to check. |
|
332 * @return true if the algorithm is valid, otherwise false. |
|
333 * @since 1.0. |
|
334 */ |
|
335 private static boolean isValidEncryptionAlgorithm(String algorithm) { |
|
336 return ( |
|
337 algorithm.equals(TRIPLEDES) || |
|
338 algorithm.equals(AES_128) || |
|
339 algorithm.equals(AES_256) || |
|
340 algorithm.equals(AES_192) || |
|
341 algorithm.equals(AES_128_GCM) || |
|
342 algorithm.equals(AES_192_GCM) || |
|
343 algorithm.equals(AES_256_GCM) || |
|
344 algorithm.equals(RSA_v1dot5) || |
|
345 algorithm.equals(RSA_OAEP) || |
|
346 algorithm.equals(RSA_OAEP_11) || |
|
347 algorithm.equals(TRIPLEDES_KeyWrap) || |
|
348 algorithm.equals(AES_128_KeyWrap) || |
|
349 algorithm.equals(AES_256_KeyWrap) || |
|
350 algorithm.equals(AES_192_KeyWrap) |
|
351 ); |
|
352 } |
|
353 |
|
354 /** |
|
355 * Validate the transformation argument of getInstance or getProviderInstance |
|
356 * |
|
357 * @param transformation the name of the transformation, e.g., |
|
358 * <code>XMLCipher.TRIPLEDES</code> which is shorthand for |
|
359 * "http://www.w3.org/2001/04/xmlenc#tripledes-cbc" |
|
360 */ |
|
361 private static void validateTransformation(String transformation) { |
|
362 if (null == transformation) { |
|
363 throw new NullPointerException("Transformation unexpectedly null..."); |
|
364 } |
|
365 if (!isValidEncryptionAlgorithm(transformation)) { |
|
366 log.log(java.util.logging.Level.WARNING, "Algorithm non-standard, expected one of " + ENC_ALGORITHMS); |
|
367 } |
|
368 } |
|
369 |
|
370 /** |
|
371 * Returns an <code>XMLCipher</code> that implements the specified |
|
372 * transformation and operates on the specified context document. |
|
373 * <p> |
|
374 * If the default provider package supplies an implementation of the |
|
375 * requested transformation, an instance of Cipher containing that |
|
376 * implementation is returned. If the transformation is not available in |
|
377 * the default provider package, other provider packages are searched. |
|
378 * <p> |
|
379 * <b>NOTE<sub>1</sub>:</b> The transformation name does not follow the same |
|
380 * pattern as that outlined in the Java Cryptography Extension Reference |
|
381 * Guide but rather that specified by the XML Encryption Syntax and |
|
382 * Processing document. The rational behind this is to make it easier for a |
|
383 * novice at writing Java Encryption software to use the library. |
|
384 * <p> |
|
385 * <b>NOTE<sub>2</sub>:</b> <code>getInstance()</code> does not follow the |
|
386 * same pattern regarding exceptional conditions as that used in |
|
387 * <code>javax.crypto.Cipher</code>. Instead, it only throws an |
|
388 * <code>XMLEncryptionException</code> which wraps an underlying exception. |
|
389 * The stack trace from the exception should be self explanatory. |
|
390 * |
|
391 * @param transformation the name of the transformation, e.g., |
|
392 * <code>XMLCipher.TRIPLEDES</code> which is shorthand for |
|
393 * "http://www.w3.org/2001/04/xmlenc#tripledes-cbc" |
|
394 * @throws XMLEncryptionException |
|
395 * @return the XMLCipher |
|
396 * @see javax.crypto.Cipher#getInstance(java.lang.String) |
|
397 */ |
|
398 public static XMLCipher getInstance(String transformation) throws XMLEncryptionException { |
|
399 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
400 log.log(java.util.logging.Level.FINE, "Getting XMLCipher with transformation"); |
|
401 } |
|
402 validateTransformation(transformation); |
|
403 return new XMLCipher(transformation, null, null, null); |
|
404 } |
|
405 |
|
406 /** |
|
407 * Returns an <code>XMLCipher</code> that implements the specified |
|
408 * transformation, operates on the specified context document and serializes |
|
409 * the document with the specified canonicalization algorithm before it |
|
410 * encrypts the document. |
|
411 * <p> |
|
412 * |
|
413 * @param transformation the name of the transformation |
|
414 * @param canon the name of the c14n algorithm, if <code>null</code> use |
|
415 * standard serializer |
|
416 * @return the XMLCipher |
|
417 * @throws XMLEncryptionException |
|
418 */ |
|
419 public static XMLCipher getInstance(String transformation, String canon) |
|
420 throws XMLEncryptionException { |
|
421 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
422 log.log(java.util.logging.Level.FINE, "Getting XMLCipher with transformation and c14n algorithm"); |
|
423 } |
|
424 validateTransformation(transformation); |
|
425 return new XMLCipher(transformation, null, canon, null); |
|
426 } |
|
427 |
|
428 /** |
|
429 * Returns an <code>XMLCipher</code> that implements the specified |
|
430 * transformation, operates on the specified context document and serializes |
|
431 * the document with the specified canonicalization algorithm before it |
|
432 * encrypts the document. |
|
433 * <p> |
|
434 * |
|
435 * @param transformation the name of the transformation |
|
436 * @param canon the name of the c14n algorithm, if <code>null</code> use |
|
437 * standard serializer |
|
438 * @param digestMethod An optional digestMethod to use |
|
439 * @return the XMLCipher |
|
440 * @throws XMLEncryptionException |
|
441 */ |
|
442 public static XMLCipher getInstance(String transformation, String canon, String digestMethod) |
|
443 throws XMLEncryptionException { |
|
444 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
445 log.log(java.util.logging.Level.FINE, "Getting XMLCipher with transformation and c14n algorithm"); |
|
446 } |
|
447 validateTransformation(transformation); |
|
448 return new XMLCipher(transformation, null, canon, digestMethod); |
|
449 } |
|
450 |
|
451 /** |
|
452 * Returns an <code>XMLCipher</code> that implements the specified |
|
453 * transformation and operates on the specified context document. |
|
454 * |
|
455 * @param transformation the name of the transformation |
|
456 * @param provider the JCE provider that supplies the transformation |
|
457 * @return the XMLCipher |
|
458 * @throws XMLEncryptionException |
|
459 */ |
|
460 public static XMLCipher getProviderInstance(String transformation, String provider) |
|
461 throws XMLEncryptionException { |
|
462 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
463 log.log(java.util.logging.Level.FINE, "Getting XMLCipher with transformation and provider"); |
|
464 } |
|
465 if (null == provider) { |
|
466 throw new NullPointerException("Provider unexpectedly null.."); |
|
467 } |
|
468 validateTransformation(transformation); |
|
469 return new XMLCipher(transformation, provider, null, null); |
|
470 } |
|
471 |
|
472 /** |
|
473 * Returns an <code>XMLCipher</code> that implements the specified |
|
474 * transformation, operates on the specified context document and serializes |
|
475 * the document with the specified canonicalization algorithm before it |
|
476 * encrypts the document. |
|
477 * <p> |
|
478 * |
|
479 * @param transformation the name of the transformation |
|
480 * @param provider the JCE provider that supplies the transformation |
|
481 * @param canon the name of the c14n algorithm, if <code>null</code> use standard |
|
482 * serializer |
|
483 * @return the XMLCipher |
|
484 * @throws XMLEncryptionException |
|
485 */ |
|
486 public static XMLCipher getProviderInstance( |
|
487 String transformation, String provider, String canon |
|
488 ) throws XMLEncryptionException { |
|
489 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
490 log.log(java.util.logging.Level.FINE, "Getting XMLCipher with transformation, provider and c14n algorithm"); |
|
491 } |
|
492 if (null == provider) { |
|
493 throw new NullPointerException("Provider unexpectedly null.."); |
|
494 } |
|
495 validateTransformation(transformation); |
|
496 return new XMLCipher(transformation, provider, canon, null); |
|
497 } |
|
498 |
|
499 /** |
|
500 * Returns an <code>XMLCipher</code> that implements the specified |
|
501 * transformation, operates on the specified context document and serializes |
|
502 * the document with the specified canonicalization algorithm before it |
|
503 * encrypts the document. |
|
504 * <p> |
|
505 * |
|
506 * @param transformation the name of the transformation |
|
507 * @param provider the JCE provider that supplies the transformation |
|
508 * @param canon the name of the c14n algorithm, if <code>null</code> use standard |
|
509 * serializer |
|
510 * @param digestMethod An optional digestMethod to use |
|
511 * @return the XMLCipher |
|
512 * @throws XMLEncryptionException |
|
513 */ |
|
514 public static XMLCipher getProviderInstance( |
|
515 String transformation, String provider, String canon, String digestMethod |
|
516 ) throws XMLEncryptionException { |
|
517 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
518 log.log(java.util.logging.Level.FINE, "Getting XMLCipher with transformation, provider and c14n algorithm"); |
|
519 } |
|
520 if (null == provider) { |
|
521 throw new NullPointerException("Provider unexpectedly null.."); |
|
522 } |
|
523 validateTransformation(transformation); |
|
524 return new XMLCipher(transformation, provider, canon, digestMethod); |
|
525 } |
|
526 |
|
527 /** |
|
528 * Returns an <code>XMLCipher</code> that implements no specific |
|
529 * transformation, and can therefore only be used for decrypt or |
|
530 * unwrap operations where the encryption method is defined in the |
|
531 * <code>EncryptionMethod</code> element. |
|
532 * |
|
533 * @return The XMLCipher |
|
534 * @throws XMLEncryptionException |
|
535 */ |
|
536 public static XMLCipher getInstance() throws XMLEncryptionException { |
|
537 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
538 log.log(java.util.logging.Level.FINE, "Getting XMLCipher with no arguments"); |
|
539 } |
|
540 return new XMLCipher(null, null, null, null); |
|
541 } |
|
542 |
|
543 /** |
|
544 * Returns an <code>XMLCipher</code> that implements no specific |
|
545 * transformation, and can therefore only be used for decrypt or |
|
546 * unwrap operations where the encryption method is defined in the |
|
547 * <code>EncryptionMethod</code> element. |
|
548 * |
|
549 * Allows the caller to specify a provider that will be used for |
|
550 * cryptographic operations. |
|
551 * |
|
552 * @param provider the JCE provider that supplies the transformation |
|
553 * @return the XMLCipher |
|
554 * @throws XMLEncryptionException |
|
555 */ |
|
556 public static XMLCipher getProviderInstance(String provider) throws XMLEncryptionException { |
|
557 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
558 log.log(java.util.logging.Level.FINE, "Getting XMLCipher with provider"); |
|
559 } |
|
560 return new XMLCipher(null, provider, null, null); |
|
561 } |
|
562 |
|
563 /** |
|
564 * Initializes this cipher with a key. |
|
565 * <p> |
|
566 * The cipher is initialized for one of the following four operations: |
|
567 * encryption, decryption, key wrapping or key unwrapping, depending on the |
|
568 * value of opmode. |
|
569 * |
|
570 * For WRAP and ENCRYPT modes, this also initialises the internal |
|
571 * EncryptedKey or EncryptedData (with a CipherValue) |
|
572 * structure that will be used during the ensuing operations. This |
|
573 * can be obtained (in order to modify KeyInfo elements etc. prior to |
|
574 * finalising the encryption) by calling |
|
575 * {@link #getEncryptedData} or {@link #getEncryptedKey}. |
|
576 * |
|
577 * @param opmode the operation mode of this cipher (this is one of the |
|
578 * following: ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE or UNWRAP_MODE) |
|
579 * @param key |
|
580 * @see javax.crypto.Cipher#init(int, java.security.Key) |
|
581 * @throws XMLEncryptionException |
|
582 */ |
|
583 public void init(int opmode, Key key) throws XMLEncryptionException { |
|
584 // sanity checks |
|
585 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
586 log.log(java.util.logging.Level.FINE, "Initializing XMLCipher..."); |
|
587 } |
|
588 |
|
589 ek = null; |
|
590 ed = null; |
|
591 |
|
592 switch (opmode) { |
|
593 |
|
594 case ENCRYPT_MODE : |
|
595 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
596 log.log(java.util.logging.Level.FINE, "opmode = ENCRYPT_MODE"); |
|
597 } |
|
598 ed = createEncryptedData(CipherData.VALUE_TYPE, "NO VALUE YET"); |
|
599 break; |
|
600 case DECRYPT_MODE : |
|
601 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
602 log.log(java.util.logging.Level.FINE, "opmode = DECRYPT_MODE"); |
|
603 } |
|
604 break; |
|
605 case WRAP_MODE : |
|
606 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
607 log.log(java.util.logging.Level.FINE, "opmode = WRAP_MODE"); |
|
608 } |
|
609 ek = createEncryptedKey(CipherData.VALUE_TYPE, "NO VALUE YET"); |
|
610 break; |
|
611 case UNWRAP_MODE : |
|
612 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
613 log.log(java.util.logging.Level.FINE, "opmode = UNWRAP_MODE"); |
|
614 } |
|
615 break; |
|
616 default : |
|
617 log.log(java.util.logging.Level.SEVERE, "Mode unexpectedly invalid"); |
|
618 throw new XMLEncryptionException("Invalid mode in init"); |
|
619 } |
|
620 |
|
621 cipherMode = opmode; |
|
622 this.key = key; |
|
623 } |
|
624 |
|
625 /** |
|
626 * Set whether secure validation is enabled or not. The default is false. |
|
627 */ |
|
628 public void setSecureValidation(boolean secureValidation) { |
|
629 this.secureValidation = secureValidation; |
|
630 } |
|
631 |
|
632 /** |
|
633 * This method is used to add a custom {@link KeyResolverSpi} to an XMLCipher. |
|
634 * These KeyResolvers are used in KeyInfo objects in DECRYPT and |
|
635 * UNWRAP modes. |
|
636 * |
|
637 * @param keyResolver |
|
638 */ |
|
639 public void registerInternalKeyResolver(KeyResolverSpi keyResolver) { |
|
640 if (internalKeyResolvers == null) { |
|
641 internalKeyResolvers = new ArrayList<KeyResolverSpi>(); |
|
642 } |
|
643 internalKeyResolvers.add(keyResolver); |
|
644 } |
|
645 |
|
646 /** |
|
647 * Get the EncryptedData being built |
|
648 * <p> |
|
649 * Returns the EncryptedData being built during an ENCRYPT operation. |
|
650 * This can then be used by applications to add KeyInfo elements and |
|
651 * set other parameters. |
|
652 * |
|
653 * @return The EncryptedData being built |
|
654 */ |
|
655 public EncryptedData getEncryptedData() { |
|
656 // Sanity checks |
|
657 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
658 log.log(java.util.logging.Level.FINE, "Returning EncryptedData"); |
|
659 } |
|
660 return ed; |
|
661 } |
|
662 |
|
663 /** |
|
664 * Get the EncryptedData being build |
|
665 * |
|
666 * Returns the EncryptedData being built during an ENCRYPT operation. |
|
667 * This can then be used by applications to add KeyInfo elements and |
|
668 * set other parameters. |
|
669 * |
|
670 * @return The EncryptedData being built |
|
671 */ |
|
672 public EncryptedKey getEncryptedKey() { |
|
673 // Sanity checks |
|
674 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
675 log.log(java.util.logging.Level.FINE, "Returning EncryptedKey"); |
|
676 } |
|
677 return ek; |
|
678 } |
|
679 |
|
680 /** |
|
681 * Set a Key Encryption Key. |
|
682 * <p> |
|
683 * The Key Encryption Key (KEK) is used for encrypting/decrypting |
|
684 * EncryptedKey elements. By setting this separately, the XMLCipher |
|
685 * class can know whether a key applies to the data part or wrapped key |
|
686 * part of an encrypted object. |
|
687 * |
|
688 * @param kek The key to use for de/encrypting key data |
|
689 */ |
|
690 |
|
691 public void setKEK(Key kek) { |
|
692 this.kek = kek; |
|
693 } |
|
694 |
|
695 /** |
|
696 * Martial an EncryptedData |
|
697 * |
|
698 * Takes an EncryptedData object and returns a DOM Element that |
|
699 * represents the appropriate <code>EncryptedData</code> |
|
700 * <p> |
|
701 * <b>Note:</b> This should only be used in cases where the context |
|
702 * document has been passed in via a call to doFinal. |
|
703 * |
|
704 * @param encryptedData EncryptedData object to martial |
|
705 * @return the DOM <code>Element</code> representing the passed in |
|
706 * object |
|
707 */ |
|
708 public Element martial(EncryptedData encryptedData) { |
|
709 return factory.toElement(encryptedData); |
|
710 } |
|
711 |
|
712 /** |
|
713 * Martial an EncryptedData |
|
714 * |
|
715 * Takes an EncryptedData object and returns a DOM Element that |
|
716 * represents the appropriate <code>EncryptedData</code> |
|
717 * |
|
718 * @param context The document that will own the returned nodes |
|
719 * @param encryptedData EncryptedData object to martial |
|
720 * @return the DOM <code>Element</code> representing the passed in |
|
721 * object |
|
722 */ |
|
723 public Element martial(Document context, EncryptedData encryptedData) { |
|
724 contextDocument = context; |
|
725 return factory.toElement(encryptedData); |
|
726 } |
|
727 |
|
728 /** |
|
729 * Martial an EncryptedKey |
|
730 * |
|
731 * Takes an EncryptedKey object and returns a DOM Element that |
|
732 * represents the appropriate <code>EncryptedKey</code> |
|
733 * |
|
734 * <p> |
|
735 * <b>Note:</b> This should only be used in cases where the context |
|
736 * document has been passed in via a call to doFinal. |
|
737 * |
|
738 * @param encryptedKey EncryptedKey object to martial |
|
739 * @return the DOM <code>Element</code> representing the passed in |
|
740 * object |
|
741 */ |
|
742 public Element martial(EncryptedKey encryptedKey) { |
|
743 return factory.toElement(encryptedKey); |
|
744 } |
|
745 |
|
746 /** |
|
747 * Martial an EncryptedKey |
|
748 * |
|
749 * Takes an EncryptedKey object and returns a DOM Element that |
|
750 * represents the appropriate <code>EncryptedKey</code> |
|
751 * |
|
752 * @param context The document that will own the created nodes |
|
753 * @param encryptedKey EncryptedKey object to martial |
|
754 * @return the DOM <code>Element</code> representing the passed in |
|
755 * object |
|
756 */ |
|
757 public Element martial(Document context, EncryptedKey encryptedKey) { |
|
758 contextDocument = context; |
|
759 return factory.toElement(encryptedKey); |
|
760 } |
|
761 |
|
762 /** |
|
763 * Martial a ReferenceList |
|
764 * |
|
765 * Takes a ReferenceList object and returns a DOM Element that |
|
766 * represents the appropriate <code>ReferenceList</code> |
|
767 * |
|
768 * <p> |
|
769 * <b>Note:</b> This should only be used in cases where the context |
|
770 * document has been passed in via a call to doFinal. |
|
771 * |
|
772 * @param referenceList ReferenceList object to martial |
|
773 * @return the DOM <code>Element</code> representing the passed in |
|
774 * object |
|
775 */ |
|
776 public Element martial(ReferenceList referenceList) { |
|
777 return factory.toElement(referenceList); |
|
778 } |
|
779 |
|
780 /** |
|
781 * Martial a ReferenceList |
|
782 * |
|
783 * Takes a ReferenceList object and returns a DOM Element that |
|
784 * represents the appropriate <code>ReferenceList</code> |
|
785 * |
|
786 * @param context The document that will own the created nodes |
|
787 * @param referenceList ReferenceList object to martial |
|
788 * @return the DOM <code>Element</code> representing the passed in |
|
789 * object |
|
790 */ |
|
791 public Element martial(Document context, ReferenceList referenceList) { |
|
792 contextDocument = context; |
|
793 return factory.toElement(referenceList); |
|
794 } |
|
795 |
|
796 /** |
|
797 * Encrypts an <code>Element</code> and replaces it with its encrypted |
|
798 * counterpart in the context <code>Document</code>, that is, the |
|
799 * <code>Document</code> specified when one calls |
|
800 * {@link #getInstance(String) getInstance}. |
|
801 * |
|
802 * @param element the <code>Element</code> to encrypt. |
|
803 * @return the context <code>Document</code> with the encrypted |
|
804 * <code>Element</code> having replaced the source <code>Element</code>. |
|
805 * @throws Exception |
|
806 */ |
|
807 private Document encryptElement(Element element) throws Exception{ |
|
808 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
809 log.log(java.util.logging.Level.FINE, "Encrypting element..."); |
|
810 } |
|
811 if (null == element) { |
|
812 log.log(java.util.logging.Level.SEVERE, "Element unexpectedly null..."); |
|
813 } |
|
814 if (cipherMode != ENCRYPT_MODE && log.isLoggable(java.util.logging.Level.FINE)) { |
|
815 log.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE..."); |
|
816 } |
|
817 |
|
818 if (algorithm == null) { |
|
819 throw new XMLEncryptionException("XMLCipher instance without transformation specified"); |
|
820 } |
|
821 encryptData(contextDocument, element, false); |
|
822 |
|
823 Element encryptedElement = factory.toElement(ed); |
|
824 |
|
825 Node sourceParent = element.getParentNode(); |
|
826 sourceParent.replaceChild(encryptedElement, element); |
|
827 |
|
828 return contextDocument; |
|
829 } |
|
830 |
|
831 /** |
|
832 * Encrypts a <code>NodeList</code> (the contents of an |
|
833 * <code>Element</code>) and replaces its parent <code>Element</code>'s |
|
834 * content with this the resulting <code>EncryptedType</code> within the |
|
835 * context <code>Document</code>, that is, the <code>Document</code> |
|
836 * specified when one calls |
|
837 * {@link #getInstance(String) getInstance}. |
|
838 * |
|
839 * @param element the <code>NodeList</code> to encrypt. |
|
840 * @return the context <code>Document</code> with the encrypted |
|
841 * <code>NodeList</code> having replaced the content of the source |
|
842 * <code>Element</code>. |
|
843 * @throws Exception |
|
844 */ |
|
845 private Document encryptElementContent(Element element) throws /* XMLEncryption */Exception { |
|
846 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
847 log.log(java.util.logging.Level.FINE, "Encrypting element content..."); |
|
848 } |
|
849 if (null == element) { |
|
850 log.log(java.util.logging.Level.SEVERE, "Element unexpectedly null..."); |
|
851 } |
|
852 if (cipherMode != ENCRYPT_MODE && log.isLoggable(java.util.logging.Level.FINE)) { |
|
853 log.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE..."); |
|
854 } |
|
855 |
|
856 if (algorithm == null) { |
|
857 throw new XMLEncryptionException("XMLCipher instance without transformation specified"); |
|
858 } |
|
859 encryptData(contextDocument, element, true); |
|
860 |
|
861 Element encryptedElement = factory.toElement(ed); |
|
862 |
|
863 removeContent(element); |
|
864 element.appendChild(encryptedElement); |
|
865 |
|
866 return contextDocument; |
|
867 } |
|
868 |
|
869 /** |
|
870 * Process a DOM <code>Document</code> node. The processing depends on the |
|
871 * initialization parameters of {@link #init(int, Key) init()}. |
|
872 * |
|
873 * @param context the context <code>Document</code>. |
|
874 * @param source the <code>Document</code> to be encrypted or decrypted. |
|
875 * @return the processed <code>Document</code>. |
|
876 * @throws Exception to indicate any exceptional conditions. |
|
877 */ |
|
878 public Document doFinal(Document context, Document source) throws /* XMLEncryption */Exception { |
|
879 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
880 log.log(java.util.logging.Level.FINE, "Processing source document..."); |
|
881 } |
|
882 if (null == context) { |
|
883 log.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null..."); |
|
884 } |
|
885 if (null == source) { |
|
886 log.log(java.util.logging.Level.SEVERE, "Source document unexpectedly null..."); |
|
887 } |
|
888 |
|
889 contextDocument = context; |
|
890 |
|
891 Document result = null; |
|
892 |
|
893 switch (cipherMode) { |
|
894 case DECRYPT_MODE: |
|
895 result = decryptElement(source.getDocumentElement()); |
|
896 break; |
|
897 case ENCRYPT_MODE: |
|
898 result = encryptElement(source.getDocumentElement()); |
|
899 break; |
|
900 case UNWRAP_MODE: |
|
901 case WRAP_MODE: |
|
902 break; |
|
903 default: |
|
904 throw new XMLEncryptionException("empty", new IllegalStateException()); |
|
905 } |
|
906 |
|
907 return result; |
|
908 } |
|
909 |
|
910 /** |
|
911 * Process a DOM <code>Element</code> node. The processing depends on the |
|
912 * initialization parameters of {@link #init(int, Key) init()}. |
|
913 * |
|
914 * @param context the context <code>Document</code>. |
|
915 * @param element the <code>Element</code> to be encrypted. |
|
916 * @return the processed <code>Document</code>. |
|
917 * @throws Exception to indicate any exceptional conditions. |
|
918 */ |
|
919 public Document doFinal(Document context, Element element) throws /* XMLEncryption */Exception { |
|
920 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
921 log.log(java.util.logging.Level.FINE, "Processing source element..."); |
|
922 } |
|
923 if (null == context) { |
|
924 log.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null..."); |
|
925 } |
|
926 if (null == element) { |
|
927 log.log(java.util.logging.Level.SEVERE, "Source element unexpectedly null..."); |
|
928 } |
|
929 |
|
930 contextDocument = context; |
|
931 |
|
932 Document result = null; |
|
933 |
|
934 switch (cipherMode) { |
|
935 case DECRYPT_MODE: |
|
936 result = decryptElement(element); |
|
937 break; |
|
938 case ENCRYPT_MODE: |
|
939 result = encryptElement(element); |
|
940 break; |
|
941 case UNWRAP_MODE: |
|
942 case WRAP_MODE: |
|
943 break; |
|
944 default: |
|
945 throw new XMLEncryptionException("empty", new IllegalStateException()); |
|
946 } |
|
947 |
|
948 return result; |
|
949 } |
|
950 |
|
951 /** |
|
952 * Process the contents of a DOM <code>Element</code> node. The processing |
|
953 * depends on the initialization parameters of |
|
954 * {@link #init(int, Key) init()}. |
|
955 * |
|
956 * @param context the context <code>Document</code>. |
|
957 * @param element the <code>Element</code> which contents is to be |
|
958 * encrypted. |
|
959 * @param content |
|
960 * @return the processed <code>Document</code>. |
|
961 * @throws Exception to indicate any exceptional conditions. |
|
962 */ |
|
963 public Document doFinal(Document context, Element element, boolean content) |
|
964 throws /* XMLEncryption*/ Exception { |
|
965 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
966 log.log(java.util.logging.Level.FINE, "Processing source element..."); |
|
967 } |
|
968 if (null == context) { |
|
969 log.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null..."); |
|
970 } |
|
971 if (null == element) { |
|
972 log.log(java.util.logging.Level.SEVERE, "Source element unexpectedly null..."); |
|
973 } |
|
974 |
|
975 contextDocument = context; |
|
976 |
|
977 Document result = null; |
|
978 |
|
979 switch (cipherMode) { |
|
980 case DECRYPT_MODE: |
|
981 if (content) { |
|
982 result = decryptElementContent(element); |
|
983 } else { |
|
984 result = decryptElement(element); |
|
985 } |
|
986 break; |
|
987 case ENCRYPT_MODE: |
|
988 if (content) { |
|
989 result = encryptElementContent(element); |
|
990 } else { |
|
991 result = encryptElement(element); |
|
992 } |
|
993 break; |
|
994 case UNWRAP_MODE: |
|
995 case WRAP_MODE: |
|
996 break; |
|
997 default: |
|
998 throw new XMLEncryptionException("empty", new IllegalStateException()); |
|
999 } |
|
1000 |
|
1001 return result; |
|
1002 } |
|
1003 |
|
1004 /** |
|
1005 * Returns an <code>EncryptedData</code> interface. Use this operation if |
|
1006 * you want to have full control over the contents of the |
|
1007 * <code>EncryptedData</code> structure. |
|
1008 * |
|
1009 * This does not change the source document in any way. |
|
1010 * |
|
1011 * @param context the context <code>Document</code>. |
|
1012 * @param element the <code>Element</code> that will be encrypted. |
|
1013 * @return the <code>EncryptedData</code> |
|
1014 * @throws Exception |
|
1015 */ |
|
1016 public EncryptedData encryptData(Document context, Element element) throws |
|
1017 /* XMLEncryption */Exception { |
|
1018 return encryptData(context, element, false); |
|
1019 } |
|
1020 |
|
1021 /** |
|
1022 * Returns an <code>EncryptedData</code> interface. Use this operation if |
|
1023 * you want to have full control over the serialization of the element |
|
1024 * or element content. |
|
1025 * |
|
1026 * This does not change the source document in any way. |
|
1027 * |
|
1028 * @param context the context <code>Document</code>. |
|
1029 * @param type a URI identifying type information about the plaintext form |
|
1030 * of the encrypted content (may be <code>null</code>) |
|
1031 * @param serializedData the serialized data |
|
1032 * @return the <code>EncryptedData</code> |
|
1033 * @throws Exception |
|
1034 */ |
|
1035 public EncryptedData encryptData( |
|
1036 Document context, String type, InputStream serializedData |
|
1037 ) throws Exception { |
|
1038 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1039 log.log(java.util.logging.Level.FINE, "Encrypting element..."); |
|
1040 } |
|
1041 if (null == context) { |
|
1042 log.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null..."); |
|
1043 } |
|
1044 if (null == serializedData) { |
|
1045 log.log(java.util.logging.Level.SEVERE, "Serialized data unexpectedly null..."); |
|
1046 } |
|
1047 if (cipherMode != ENCRYPT_MODE && log.isLoggable(java.util.logging.Level.FINE)) { |
|
1048 log.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE..."); |
|
1049 } |
|
1050 |
|
1051 return encryptData(context, null, type, serializedData); |
|
1052 } |
|
1053 |
|
1054 /** |
|
1055 * Returns an <code>EncryptedData</code> interface. Use this operation if |
|
1056 * you want to have full control over the contents of the |
|
1057 * <code>EncryptedData</code> structure. |
|
1058 * |
|
1059 * This does not change the source document in any way. |
|
1060 * |
|
1061 * @param context the context <code>Document</code>. |
|
1062 * @param element the <code>Element</code> that will be encrypted. |
|
1063 * @param contentMode <code>true</code> to encrypt element's content only, |
|
1064 * <code>false</code> otherwise |
|
1065 * @return the <code>EncryptedData</code> |
|
1066 * @throws Exception |
|
1067 */ |
|
1068 public EncryptedData encryptData( |
|
1069 Document context, Element element, boolean contentMode |
|
1070 ) throws /* XMLEncryption */ Exception { |
|
1071 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1072 log.log(java.util.logging.Level.FINE, "Encrypting element..."); |
|
1073 } |
|
1074 if (null == context) { |
|
1075 log.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null..."); |
|
1076 } |
|
1077 if (null == element) { |
|
1078 log.log(java.util.logging.Level.SEVERE, "Element unexpectedly null..."); |
|
1079 } |
|
1080 if (cipherMode != ENCRYPT_MODE && log.isLoggable(java.util.logging.Level.FINE)) { |
|
1081 log.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE..."); |
|
1082 } |
|
1083 |
|
1084 if (contentMode) { |
|
1085 return encryptData(context, element, EncryptionConstants.TYPE_CONTENT, null); |
|
1086 } else { |
|
1087 return encryptData(context, element, EncryptionConstants.TYPE_ELEMENT, null); |
|
1088 } |
|
1089 } |
|
1090 |
|
1091 private EncryptedData encryptData( |
|
1092 Document context, Element element, String type, InputStream serializedData |
|
1093 ) throws /* XMLEncryption */ Exception { |
|
1094 contextDocument = context; |
|
1095 |
|
1096 if (algorithm == null) { |
|
1097 throw new XMLEncryptionException("XMLCipher instance without transformation specified"); |
|
1098 } |
|
1099 |
|
1100 byte[] serializedOctets = null; |
|
1101 if (serializedData == null) { |
|
1102 if (type.equals(EncryptionConstants.TYPE_CONTENT)) { |
|
1103 NodeList children = element.getChildNodes(); |
|
1104 if (null != children) { |
|
1105 serializedOctets = serializer.serializeToByteArray(children); |
|
1106 } else { |
|
1107 Object exArgs[] = { "Element has no content." }; |
|
1108 throw new XMLEncryptionException("empty", exArgs); |
|
1109 } |
|
1110 } else { |
|
1111 serializedOctets = serializer.serializeToByteArray(element); |
|
1112 } |
|
1113 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1114 log.log(java.util.logging.Level.FINE, "Serialized octets:\n" + new String(serializedOctets, "UTF-8")); |
|
1115 } |
|
1116 } |
|
1117 |
|
1118 byte[] encryptedBytes = null; |
|
1119 |
|
1120 // Now create the working cipher if none was created already |
|
1121 Cipher c; |
|
1122 if (contextCipher == null) { |
|
1123 c = constructCipher(algorithm, null); |
|
1124 } else { |
|
1125 c = contextCipher; |
|
1126 } |
|
1127 // Now perform the encryption |
|
1128 |
|
1129 try { |
|
1130 // The Spec mandates a 96-bit IV for GCM algorithms |
|
1131 if (AES_128_GCM.equals(algorithm) || AES_192_GCM.equals(algorithm) |
|
1132 || AES_256_GCM.equals(algorithm)) { |
|
1133 if (random == null) { |
|
1134 random = SecureRandom.getInstance("SHA1PRNG"); |
|
1135 } |
|
1136 byte[] temp = new byte[12]; |
|
1137 random.nextBytes(temp); |
|
1138 IvParameterSpec paramSpec = new IvParameterSpec(temp); |
|
1139 c.init(cipherMode, key, paramSpec); |
|
1140 } else { |
|
1141 c.init(cipherMode, key); |
|
1142 } |
|
1143 } catch (InvalidKeyException ike) { |
|
1144 throw new XMLEncryptionException("empty", ike); |
|
1145 } catch (NoSuchAlgorithmException ex) { |
|
1146 throw new XMLEncryptionException("empty", ex); |
|
1147 } |
|
1148 |
|
1149 try { |
|
1150 if (serializedData != null) { |
|
1151 int numBytes; |
|
1152 byte[] buf = new byte[8192]; |
|
1153 ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
|
1154 while ((numBytes = serializedData.read(buf)) != -1) { |
|
1155 byte[] data = c.update(buf, 0, numBytes); |
|
1156 baos.write(data); |
|
1157 } |
|
1158 baos.write(c.doFinal()); |
|
1159 encryptedBytes = baos.toByteArray(); |
|
1160 } else { |
|
1161 encryptedBytes = c.doFinal(serializedOctets); |
|
1162 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1163 log.log(java.util.logging.Level.FINE, "Expected cipher.outputSize = " + |
|
1164 Integer.toString(c.getOutputSize(serializedOctets.length))); |
|
1165 } |
|
1166 } |
|
1167 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1168 log.log(java.util.logging.Level.FINE, "Actual cipher.outputSize = " |
|
1169 + Integer.toString(encryptedBytes.length)); |
|
1170 } |
|
1171 } catch (IllegalStateException ise) { |
|
1172 throw new XMLEncryptionException("empty", ise); |
|
1173 } catch (IllegalBlockSizeException ibse) { |
|
1174 throw new XMLEncryptionException("empty", ibse); |
|
1175 } catch (BadPaddingException bpe) { |
|
1176 throw new XMLEncryptionException("empty", bpe); |
|
1177 } catch (UnsupportedEncodingException uee) { |
|
1178 throw new XMLEncryptionException("empty", uee); |
|
1179 } |
|
1180 |
|
1181 // Now build up to a properly XML Encryption encoded octet stream |
|
1182 // IvParameterSpec iv; |
|
1183 byte[] iv = c.getIV(); |
|
1184 byte[] finalEncryptedBytes = new byte[iv.length + encryptedBytes.length]; |
|
1185 System.arraycopy(iv, 0, finalEncryptedBytes, 0, iv.length); |
|
1186 System.arraycopy(encryptedBytes, 0, finalEncryptedBytes, iv.length, encryptedBytes.length); |
|
1187 String base64EncodedEncryptedOctets = Base64.encode(finalEncryptedBytes); |
|
1188 |
|
1189 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1190 log.log(java.util.logging.Level.FINE, "Encrypted octets:\n" + base64EncodedEncryptedOctets); |
|
1191 log.log(java.util.logging.Level.FINE, "Encrypted octets length = " + base64EncodedEncryptedOctets.length()); |
|
1192 } |
|
1193 |
|
1194 try { |
|
1195 CipherData cd = ed.getCipherData(); |
|
1196 CipherValue cv = cd.getCipherValue(); |
|
1197 // cv.setValue(base64EncodedEncryptedOctets.getBytes()); |
|
1198 cv.setValue(base64EncodedEncryptedOctets); |
|
1199 |
|
1200 if (type != null) { |
|
1201 ed.setType(new URI(type).toString()); |
|
1202 } |
|
1203 EncryptionMethod method = |
|
1204 factory.newEncryptionMethod(new URI(algorithm).toString()); |
|
1205 method.setDigestAlgorithm(digestAlg); |
|
1206 ed.setEncryptionMethod(method); |
|
1207 } catch (URISyntaxException ex) { |
|
1208 throw new XMLEncryptionException("empty", ex); |
|
1209 } |
|
1210 return ed; |
|
1211 } |
|
1212 |
|
1213 /** |
|
1214 * Returns an <code>EncryptedData</code> interface. Use this operation if |
|
1215 * you want to load an <code>EncryptedData</code> structure from a DOM |
|
1216 * structure and manipulate the contents. |
|
1217 * |
|
1218 * @param context the context <code>Document</code>. |
|
1219 * @param element the <code>Element</code> that will be loaded |
|
1220 * @throws XMLEncryptionException |
|
1221 * @return the <code>EncryptedData</code> |
|
1222 */ |
|
1223 public EncryptedData loadEncryptedData(Document context, Element element) |
|
1224 throws XMLEncryptionException { |
|
1225 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1226 log.log(java.util.logging.Level.FINE, "Loading encrypted element..."); |
|
1227 } |
|
1228 if (null == context) { |
|
1229 throw new NullPointerException("Context document unexpectedly null..."); |
|
1230 } |
|
1231 if (null == element) { |
|
1232 throw new NullPointerException("Element unexpectedly null..."); |
|
1233 } |
|
1234 if (cipherMode != DECRYPT_MODE) { |
|
1235 throw new XMLEncryptionException("XMLCipher unexpectedly not in DECRYPT_MODE..."); |
|
1236 } |
|
1237 |
|
1238 contextDocument = context; |
|
1239 ed = factory.newEncryptedData(element); |
|
1240 |
|
1241 return ed; |
|
1242 } |
|
1243 |
|
1244 /** |
|
1245 * Returns an <code>EncryptedKey</code> interface. Use this operation if |
|
1246 * you want to load an <code>EncryptedKey</code> structure from a DOM |
|
1247 * structure and manipulate the contents. |
|
1248 * |
|
1249 * @param context the context <code>Document</code>. |
|
1250 * @param element the <code>Element</code> that will be loaded |
|
1251 * @return the <code>EncryptedKey</code> |
|
1252 * @throws XMLEncryptionException |
|
1253 */ |
|
1254 public EncryptedKey loadEncryptedKey(Document context, Element element) |
|
1255 throws XMLEncryptionException { |
|
1256 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1257 log.log(java.util.logging.Level.FINE, "Loading encrypted key..."); |
|
1258 } |
|
1259 if (null == context) { |
|
1260 throw new NullPointerException("Context document unexpectedly null..."); |
|
1261 } |
|
1262 if (null == element) { |
|
1263 throw new NullPointerException("Element unexpectedly null..."); |
|
1264 } |
|
1265 if (cipherMode != UNWRAP_MODE && cipherMode != DECRYPT_MODE) { |
|
1266 throw new XMLEncryptionException( |
|
1267 "XMLCipher unexpectedly not in UNWRAP_MODE or DECRYPT_MODE..." |
|
1268 ); |
|
1269 } |
|
1270 |
|
1271 contextDocument = context; |
|
1272 ek = factory.newEncryptedKey(element); |
|
1273 return ek; |
|
1274 } |
|
1275 |
|
1276 /** |
|
1277 * Returns an <code>EncryptedKey</code> interface. Use this operation if |
|
1278 * you want to load an <code>EncryptedKey</code> structure from a DOM |
|
1279 * structure and manipulate the contents. |
|
1280 * |
|
1281 * Assumes that the context document is the document that owns the element |
|
1282 * |
|
1283 * @param element the <code>Element</code> that will be loaded |
|
1284 * @return the <code>EncryptedKey</code> |
|
1285 * @throws XMLEncryptionException |
|
1286 */ |
|
1287 public EncryptedKey loadEncryptedKey(Element element) throws XMLEncryptionException { |
|
1288 return loadEncryptedKey(element.getOwnerDocument(), element); |
|
1289 } |
|
1290 |
|
1291 /** |
|
1292 * Encrypts a key to an EncryptedKey structure |
|
1293 * |
|
1294 * @param doc the Context document that will be used to general DOM |
|
1295 * @param key Key to encrypt (will use previously set KEK to |
|
1296 * perform encryption |
|
1297 * @return the <code>EncryptedKey</code> |
|
1298 * @throws XMLEncryptionException |
|
1299 */ |
|
1300 public EncryptedKey encryptKey(Document doc, Key key) throws XMLEncryptionException { |
|
1301 return encryptKey(doc, key, null, null); |
|
1302 } |
|
1303 |
|
1304 /** |
|
1305 * Encrypts a key to an EncryptedKey structure |
|
1306 * |
|
1307 * @param doc the Context document that will be used to general DOM |
|
1308 * @param key Key to encrypt (will use previously set KEK to |
|
1309 * perform encryption |
|
1310 * @param mgfAlgorithm The xenc11 MGF Algorithm to use |
|
1311 * @param oaepParams The OAEPParams to use |
|
1312 * @return the <code>EncryptedKey</code> |
|
1313 * @throws XMLEncryptionException |
|
1314 */ |
|
1315 public EncryptedKey encryptKey( |
|
1316 Document doc, |
|
1317 Key key, |
|
1318 String mgfAlgorithm, |
|
1319 byte[] oaepParams |
|
1320 ) throws XMLEncryptionException { |
|
1321 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1322 log.log(java.util.logging.Level.FINE, "Encrypting key ..."); |
|
1323 } |
|
1324 |
|
1325 if (null == key) { |
|
1326 log.log(java.util.logging.Level.SEVERE, "Key unexpectedly null..."); |
|
1327 } |
|
1328 if (cipherMode != WRAP_MODE) { |
|
1329 log.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in WRAP_MODE..."); |
|
1330 } |
|
1331 if (algorithm == null) { |
|
1332 throw new XMLEncryptionException("XMLCipher instance without transformation specified"); |
|
1333 } |
|
1334 |
|
1335 contextDocument = doc; |
|
1336 |
|
1337 byte[] encryptedBytes = null; |
|
1338 Cipher c; |
|
1339 |
|
1340 if (contextCipher == null) { |
|
1341 // Now create the working cipher |
|
1342 c = constructCipher(algorithm, null); |
|
1343 } else { |
|
1344 c = contextCipher; |
|
1345 } |
|
1346 // Now perform the encryption |
|
1347 |
|
1348 try { |
|
1349 // Should internally generate an IV |
|
1350 // todo - allow user to set an IV |
|
1351 OAEPParameterSpec oaepParameters = |
|
1352 constructOAEPParameters( |
|
1353 algorithm, digestAlg, mgfAlgorithm, oaepParams |
|
1354 ); |
|
1355 if (oaepParameters == null) { |
|
1356 c.init(Cipher.WRAP_MODE, this.key); |
|
1357 } else { |
|
1358 c.init(Cipher.WRAP_MODE, this.key, oaepParameters); |
|
1359 } |
|
1360 encryptedBytes = c.wrap(key); |
|
1361 } catch (InvalidKeyException ike) { |
|
1362 throw new XMLEncryptionException("empty", ike); |
|
1363 } catch (IllegalBlockSizeException ibse) { |
|
1364 throw new XMLEncryptionException("empty", ibse); |
|
1365 } catch (InvalidAlgorithmParameterException e) { |
|
1366 throw new XMLEncryptionException("empty", e); |
|
1367 } |
|
1368 |
|
1369 String base64EncodedEncryptedOctets = Base64.encode(encryptedBytes); |
|
1370 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1371 log.log(java.util.logging.Level.FINE, "Encrypted key octets:\n" + base64EncodedEncryptedOctets); |
|
1372 log.log(java.util.logging.Level.FINE, "Encrypted key octets length = " + base64EncodedEncryptedOctets.length()); |
|
1373 } |
|
1374 |
|
1375 CipherValue cv = ek.getCipherData().getCipherValue(); |
|
1376 cv.setValue(base64EncodedEncryptedOctets); |
|
1377 |
|
1378 try { |
|
1379 EncryptionMethod method = factory.newEncryptionMethod(new URI(algorithm).toString()); |
|
1380 method.setDigestAlgorithm(digestAlg); |
|
1381 method.setMGFAlgorithm(mgfAlgorithm); |
|
1382 method.setOAEPparams(oaepParams); |
|
1383 ek.setEncryptionMethod(method); |
|
1384 } catch (URISyntaxException ex) { |
|
1385 throw new XMLEncryptionException("empty", ex); |
|
1386 } |
|
1387 return ek; |
|
1388 } |
|
1389 |
|
1390 /** |
|
1391 * Decrypt a key from a passed in EncryptedKey structure |
|
1392 * |
|
1393 * @param encryptedKey Previously loaded EncryptedKey that needs |
|
1394 * to be decrypted. |
|
1395 * @param algorithm Algorithm for the decryption |
|
1396 * @return a key corresponding to the given type |
|
1397 * @throws XMLEncryptionException |
|
1398 */ |
|
1399 public Key decryptKey(EncryptedKey encryptedKey, String algorithm) |
|
1400 throws XMLEncryptionException { |
|
1401 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1402 log.log(java.util.logging.Level.FINE, "Decrypting key from previously loaded EncryptedKey..."); |
|
1403 } |
|
1404 |
|
1405 if (cipherMode != UNWRAP_MODE && log.isLoggable(java.util.logging.Level.FINE)) { |
|
1406 log.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in UNWRAP_MODE..."); |
|
1407 } |
|
1408 |
|
1409 if (algorithm == null) { |
|
1410 throw new XMLEncryptionException("Cannot decrypt a key without knowing the algorithm"); |
|
1411 } |
|
1412 |
|
1413 if (key == null) { |
|
1414 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1415 log.log(java.util.logging.Level.FINE, "Trying to find a KEK via key resolvers"); |
|
1416 } |
|
1417 |
|
1418 KeyInfo ki = encryptedKey.getKeyInfo(); |
|
1419 if (ki != null) { |
|
1420 ki.setSecureValidation(secureValidation); |
|
1421 try { |
|
1422 String keyWrapAlg = encryptedKey.getEncryptionMethod().getAlgorithm(); |
|
1423 String keyType = JCEMapper.getJCEKeyAlgorithmFromURI(keyWrapAlg); |
|
1424 if ("RSA".equals(keyType)) { |
|
1425 key = ki.getPrivateKey(); |
|
1426 } else { |
|
1427 key = ki.getSecretKey(); |
|
1428 } |
|
1429 } |
|
1430 catch (Exception e) { |
|
1431 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1432 log.log(java.util.logging.Level.FINE, e.getMessage(), e); |
|
1433 } |
|
1434 } |
|
1435 } |
|
1436 if (key == null) { |
|
1437 log.log(java.util.logging.Level.SEVERE, "XMLCipher::decryptKey called without a KEK and cannot resolve"); |
|
1438 throw new XMLEncryptionException("Unable to decrypt without a KEK"); |
|
1439 } |
|
1440 } |
|
1441 |
|
1442 // Obtain the encrypted octets |
|
1443 XMLCipherInput cipherInput = new XMLCipherInput(encryptedKey); |
|
1444 cipherInput.setSecureValidation(secureValidation); |
|
1445 byte[] encryptedBytes = cipherInput.getBytes(); |
|
1446 |
|
1447 String jceKeyAlgorithm = JCEMapper.getJCEKeyAlgorithmFromURI(algorithm); |
|
1448 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1449 log.log(java.util.logging.Level.FINE, "JCE Key Algorithm: " + jceKeyAlgorithm); |
|
1450 } |
|
1451 |
|
1452 Cipher c; |
|
1453 if (contextCipher == null) { |
|
1454 // Now create the working cipher |
|
1455 c = |
|
1456 constructCipher( |
|
1457 encryptedKey.getEncryptionMethod().getAlgorithm(), |
|
1458 encryptedKey.getEncryptionMethod().getDigestAlgorithm() |
|
1459 ); |
|
1460 } else { |
|
1461 c = contextCipher; |
|
1462 } |
|
1463 |
|
1464 Key ret; |
|
1465 |
|
1466 try { |
|
1467 EncryptionMethod encMethod = encryptedKey.getEncryptionMethod(); |
|
1468 OAEPParameterSpec oaepParameters = |
|
1469 constructOAEPParameters( |
|
1470 encMethod.getAlgorithm(), encMethod.getDigestAlgorithm(), |
|
1471 encMethod.getMGFAlgorithm(), encMethod.getOAEPparams() |
|
1472 ); |
|
1473 if (oaepParameters == null) { |
|
1474 c.init(Cipher.UNWRAP_MODE, key); |
|
1475 } else { |
|
1476 c.init(Cipher.UNWRAP_MODE, key, oaepParameters); |
|
1477 } |
|
1478 ret = c.unwrap(encryptedBytes, jceKeyAlgorithm, Cipher.SECRET_KEY); |
|
1479 } catch (InvalidKeyException ike) { |
|
1480 throw new XMLEncryptionException("empty", ike); |
|
1481 } catch (NoSuchAlgorithmException nsae) { |
|
1482 throw new XMLEncryptionException("empty", nsae); |
|
1483 } catch (InvalidAlgorithmParameterException e) { |
|
1484 throw new XMLEncryptionException("empty", e); |
|
1485 } |
|
1486 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1487 log.log(java.util.logging.Level.FINE, "Decryption of key type " + algorithm + " OK"); |
|
1488 } |
|
1489 |
|
1490 return ret; |
|
1491 } |
|
1492 |
|
1493 /** |
|
1494 * Construct an OAEPParameterSpec object from the given parameters |
|
1495 */ |
|
1496 private OAEPParameterSpec constructOAEPParameters( |
|
1497 String encryptionAlgorithm, |
|
1498 String digestAlgorithm, |
|
1499 String mgfAlgorithm, |
|
1500 byte[] oaepParams |
|
1501 ) { |
|
1502 if (XMLCipher.RSA_OAEP.equals(encryptionAlgorithm) |
|
1503 || XMLCipher.RSA_OAEP_11.equals(encryptionAlgorithm)) { |
|
1504 |
|
1505 String jceDigestAlgorithm = "SHA-1"; |
|
1506 if (digestAlgorithm != null) { |
|
1507 jceDigestAlgorithm = JCEMapper.translateURItoJCEID(digestAlgorithm); |
|
1508 } |
|
1509 |
|
1510 PSource.PSpecified pSource = PSource.PSpecified.DEFAULT; |
|
1511 if (oaepParams != null) { |
|
1512 pSource = new PSource.PSpecified(oaepParams); |
|
1513 } |
|
1514 |
|
1515 MGF1ParameterSpec mgfParameterSpec = new MGF1ParameterSpec("SHA-1"); |
|
1516 if (XMLCipher.RSA_OAEP_11.equals(encryptionAlgorithm)) { |
|
1517 if (EncryptionConstants.MGF1_SHA256.equals(mgfAlgorithm)) { |
|
1518 mgfParameterSpec = new MGF1ParameterSpec("SHA-256"); |
|
1519 } else if (EncryptionConstants.MGF1_SHA384.equals(mgfAlgorithm)) { |
|
1520 mgfParameterSpec = new MGF1ParameterSpec("SHA-384"); |
|
1521 } else if (EncryptionConstants.MGF1_SHA512.equals(mgfAlgorithm)) { |
|
1522 mgfParameterSpec = new MGF1ParameterSpec("SHA-512"); |
|
1523 } |
|
1524 } |
|
1525 return new OAEPParameterSpec(jceDigestAlgorithm, "MGF1", mgfParameterSpec, pSource); |
|
1526 } |
|
1527 |
|
1528 return null; |
|
1529 } |
|
1530 |
|
1531 /** |
|
1532 * Construct a Cipher object |
|
1533 */ |
|
1534 private Cipher constructCipher(String algorithm, String digestAlgorithm) throws XMLEncryptionException { |
|
1535 String jceAlgorithm = JCEMapper.translateURItoJCEID(algorithm); |
|
1536 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1537 log.log(java.util.logging.Level.FINE, "JCE Algorithm = " + jceAlgorithm); |
|
1538 } |
|
1539 |
|
1540 Cipher c; |
|
1541 try { |
|
1542 if (requestedJCEProvider == null) { |
|
1543 c = Cipher.getInstance(jceAlgorithm); |
|
1544 } else { |
|
1545 c = Cipher.getInstance(jceAlgorithm, requestedJCEProvider); |
|
1546 } |
|
1547 } catch (NoSuchAlgorithmException nsae) { |
|
1548 // Check to see if an RSA OAEP MGF-1 with SHA-1 algorithm was requested |
|
1549 // Some JDKs don't support RSA/ECB/OAEPPadding |
|
1550 if (XMLCipher.RSA_OAEP.equals(algorithm) |
|
1551 && (digestAlgorithm == null |
|
1552 || MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA1.equals(digestAlgorithm))) { |
|
1553 try { |
|
1554 if (requestedJCEProvider == null) { |
|
1555 c = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding"); |
|
1556 } else { |
|
1557 c = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding", requestedJCEProvider); |
|
1558 } |
|
1559 } catch (Exception ex) { |
|
1560 throw new XMLEncryptionException("empty", ex); |
|
1561 } |
|
1562 } else { |
|
1563 throw new XMLEncryptionException("empty", nsae); |
|
1564 } |
|
1565 } catch (NoSuchProviderException nspre) { |
|
1566 throw new XMLEncryptionException("empty", nspre); |
|
1567 } catch (NoSuchPaddingException nspae) { |
|
1568 throw new XMLEncryptionException("empty", nspae); |
|
1569 } |
|
1570 |
|
1571 return c; |
|
1572 } |
|
1573 |
|
1574 /** |
|
1575 * Decrypt a key from a passed in EncryptedKey structure. This version |
|
1576 * is used mainly internally, when the cipher already has an |
|
1577 * EncryptedData loaded. The algorithm URI will be read from the |
|
1578 * EncryptedData |
|
1579 * |
|
1580 * @param encryptedKey Previously loaded EncryptedKey that needs |
|
1581 * to be decrypted. |
|
1582 * @return a key corresponding to the given type |
|
1583 * @throws XMLEncryptionException |
|
1584 */ |
|
1585 public Key decryptKey(EncryptedKey encryptedKey) throws XMLEncryptionException { |
|
1586 return decryptKey(encryptedKey, ed.getEncryptionMethod().getAlgorithm()); |
|
1587 } |
|
1588 |
|
1589 /** |
|
1590 * Removes the contents of a <code>Node</code>. |
|
1591 * |
|
1592 * @param node the <code>Node</code> to clear. |
|
1593 */ |
|
1594 private static void removeContent(Node node) { |
|
1595 while (node.hasChildNodes()) { |
|
1596 node.removeChild(node.getFirstChild()); |
|
1597 } |
|
1598 } |
|
1599 |
|
1600 /** |
|
1601 * Decrypts <code>EncryptedData</code> in a single-part operation. |
|
1602 * |
|
1603 * @param element the <code>EncryptedData</code> to decrypt. |
|
1604 * @return the <code>Node</code> as a result of the decrypt operation. |
|
1605 * @throws XMLEncryptionException |
|
1606 */ |
|
1607 private Document decryptElement(Element element) throws XMLEncryptionException { |
|
1608 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1609 log.log(java.util.logging.Level.FINE, "Decrypting element..."); |
|
1610 } |
|
1611 |
|
1612 if (cipherMode != DECRYPT_MODE) { |
|
1613 log.log(java.util.logging.Level.SEVERE, "XMLCipher unexpectedly not in DECRYPT_MODE..."); |
|
1614 } |
|
1615 |
|
1616 byte[] octets = decryptToByteArray(element); |
|
1617 |
|
1618 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1619 log.log(java.util.logging.Level.FINE, "Decrypted octets:\n" + new String(octets)); |
|
1620 } |
|
1621 |
|
1622 Node sourceParent = element.getParentNode(); |
|
1623 Node decryptedNode = serializer.deserialize(octets, sourceParent); |
|
1624 |
|
1625 // The de-serialiser returns a node whose children we need to take on. |
|
1626 if (sourceParent != null && Node.DOCUMENT_NODE == sourceParent.getNodeType()) { |
|
1627 // If this is a content decryption, this may have problems |
|
1628 contextDocument.removeChild(contextDocument.getDocumentElement()); |
|
1629 contextDocument.appendChild(decryptedNode); |
|
1630 } else if (sourceParent != null) { |
|
1631 sourceParent.replaceChild(decryptedNode, element); |
|
1632 } |
|
1633 |
|
1634 return contextDocument; |
|
1635 } |
|
1636 |
|
1637 /** |
|
1638 * |
|
1639 * @param element |
|
1640 * @return the <code>Node</code> as a result of the decrypt operation. |
|
1641 * @throws XMLEncryptionException |
|
1642 */ |
|
1643 private Document decryptElementContent(Element element) throws XMLEncryptionException { |
|
1644 Element e = |
|
1645 (Element) element.getElementsByTagNameNS( |
|
1646 EncryptionConstants.EncryptionSpecNS, |
|
1647 EncryptionConstants._TAG_ENCRYPTEDDATA |
|
1648 ).item(0); |
|
1649 |
|
1650 if (null == e) { |
|
1651 throw new XMLEncryptionException("No EncryptedData child element."); |
|
1652 } |
|
1653 |
|
1654 return decryptElement(e); |
|
1655 } |
|
1656 |
|
1657 /** |
|
1658 * Decrypt an EncryptedData element to a byte array. |
|
1659 * |
|
1660 * When passed in an EncryptedData node, returns the decryption |
|
1661 * as a byte array. |
|
1662 * |
|
1663 * Does not modify the source document. |
|
1664 * @param element |
|
1665 * @return the bytes resulting from the decryption |
|
1666 * @throws XMLEncryptionException |
|
1667 */ |
|
1668 public byte[] decryptToByteArray(Element element) throws XMLEncryptionException { |
|
1669 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1670 log.log(java.util.logging.Level.FINE, "Decrypting to ByteArray..."); |
|
1671 } |
|
1672 |
|
1673 if (cipherMode != DECRYPT_MODE) { |
|
1674 log.log(java.util.logging.Level.SEVERE, "XMLCipher unexpectedly not in DECRYPT_MODE..."); |
|
1675 } |
|
1676 |
|
1677 EncryptedData encryptedData = factory.newEncryptedData(element); |
|
1678 |
|
1679 if (key == null) { |
|
1680 KeyInfo ki = encryptedData.getKeyInfo(); |
|
1681 if (ki != null) { |
|
1682 try { |
|
1683 // Add an EncryptedKey resolver |
|
1684 String encMethodAlgorithm = encryptedData.getEncryptionMethod().getAlgorithm(); |
|
1685 EncryptedKeyResolver resolver = new EncryptedKeyResolver(encMethodAlgorithm, kek); |
|
1686 if (internalKeyResolvers != null) { |
|
1687 int size = internalKeyResolvers.size(); |
|
1688 for (int i = 0; i < size; i++) { |
|
1689 resolver.registerInternalKeyResolver(internalKeyResolvers.get(i)); |
|
1690 } |
|
1691 } |
|
1692 ki.registerInternalKeyResolver(resolver); |
|
1693 ki.setSecureValidation(secureValidation); |
|
1694 key = ki.getSecretKey(); |
|
1695 } catch (KeyResolverException kre) { |
|
1696 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1697 log.log(java.util.logging.Level.FINE, kre.getMessage(), kre); |
|
1698 } |
|
1699 } |
|
1700 } |
|
1701 |
|
1702 if (key == null) { |
|
1703 log.log(java.util.logging.Level.SEVERE, |
|
1704 "XMLCipher::decryptElement called without a key and unable to resolve" |
|
1705 ); |
|
1706 throw new XMLEncryptionException("encryption.nokey"); |
|
1707 } |
|
1708 } |
|
1709 |
|
1710 // Obtain the encrypted octets |
|
1711 XMLCipherInput cipherInput = new XMLCipherInput(encryptedData); |
|
1712 cipherInput.setSecureValidation(secureValidation); |
|
1713 byte[] encryptedBytes = cipherInput.getBytes(); |
|
1714 |
|
1715 // Now create the working cipher |
|
1716 String jceAlgorithm = |
|
1717 JCEMapper.translateURItoJCEID(encryptedData.getEncryptionMethod().getAlgorithm()); |
|
1718 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
1719 log.log(java.util.logging.Level.FINE, "JCE Algorithm = " + jceAlgorithm); |
|
1720 } |
|
1721 |
|
1722 Cipher c; |
|
1723 try { |
|
1724 if (requestedJCEProvider == null) { |
|
1725 c = Cipher.getInstance(jceAlgorithm); |
|
1726 } else { |
|
1727 c = Cipher.getInstance(jceAlgorithm, requestedJCEProvider); |
|
1728 } |
|
1729 } catch (NoSuchAlgorithmException nsae) { |
|
1730 throw new XMLEncryptionException("empty", nsae); |
|
1731 } catch (NoSuchProviderException nspre) { |
|
1732 throw new XMLEncryptionException("empty", nspre); |
|
1733 } catch (NoSuchPaddingException nspae) { |
|
1734 throw new XMLEncryptionException("empty", nspae); |
|
1735 } |
|
1736 |
|
1737 // Calculate the IV length and copy out |
|
1738 |
|
1739 // For now, we only work with Block ciphers, so this will work. |
|
1740 // This should probably be put into the JCE mapper. |
|
1741 |
|
1742 int ivLen = c.getBlockSize(); |
|
1743 String alg = encryptedData.getEncryptionMethod().getAlgorithm(); |
|
1744 if (AES_128_GCM.equals(alg) || AES_192_GCM.equals(alg) || AES_256_GCM.equals(alg)) { |
|
1745 ivLen = 12; |
|
1746 } |
|
1747 byte[] ivBytes = new byte[ivLen]; |
|
1748 |
|
1749 // You may be able to pass the entire piece in to IvParameterSpec |
|
1750 // and it will only take the first x bytes, but no way to be certain |
|
1751 // that this will work for every JCE provider, so lets copy the |
|
1752 // necessary bytes into a dedicated array. |
|
1753 |
|
1754 System.arraycopy(encryptedBytes, 0, ivBytes, 0, ivLen); |
|
1755 IvParameterSpec iv = new IvParameterSpec(ivBytes); |
|
1756 |
|
1757 try { |
|
1758 c.init(cipherMode, key, iv); |
|
1759 } catch (InvalidKeyException ike) { |
|
1760 throw new XMLEncryptionException("empty", ike); |
|
1761 } catch (InvalidAlgorithmParameterException iape) { |
|
1762 throw new XMLEncryptionException("empty", iape); |
|
1763 } |
|
1764 |
|
1765 try { |
|
1766 return c.doFinal(encryptedBytes, ivLen, encryptedBytes.length - ivLen); |
|
1767 } catch (IllegalBlockSizeException ibse) { |
|
1768 throw new XMLEncryptionException("empty", ibse); |
|
1769 } catch (BadPaddingException bpe) { |
|
1770 throw new XMLEncryptionException("empty", bpe); |
|
1771 } |
|
1772 } |
|
1773 |
|
1774 /* |
|
1775 * Expose the interface for creating XML Encryption objects |
|
1776 */ |
|
1777 |
|
1778 /** |
|
1779 * Creates an <code>EncryptedData</code> <code>Element</code>. |
|
1780 * |
|
1781 * The newEncryptedData and newEncryptedKey methods create fairly complete |
|
1782 * elements that are immediately useable. All the other create* methods |
|
1783 * return bare elements that still need to be built upon. |
|
1784 *<p> |
|
1785 * An EncryptionMethod will still need to be added however |
|
1786 * |
|
1787 * @param type Either REFERENCE_TYPE or VALUE_TYPE - defines what kind of |
|
1788 * CipherData this EncryptedData will contain. |
|
1789 * @param value the Base 64 encoded, encrypted text to wrap in the |
|
1790 * <code>EncryptedData</code> or the URI to set in the CipherReference |
|
1791 * (usage will depend on the <code>type</code> |
|
1792 * @return the <code>EncryptedData</code> <code>Element</code>. |
|
1793 * |
|
1794 * <!-- |
|
1795 * <EncryptedData Id[OPT] Type[OPT] MimeType[OPT] Encoding[OPT]> |
|
1796 * <EncryptionMethod/>[OPT] |
|
1797 * <ds:KeyInfo>[OPT] |
|
1798 * <EncryptedKey/>[OPT] |
|
1799 * <AgreementMethod/>[OPT] |
|
1800 * <ds:KeyName/>[OPT] |
|
1801 * <ds:RetrievalMethod/>[OPT] |
|
1802 * <ds:[MUL]/>[OPT] |
|
1803 * </ds:KeyInfo> |
|
1804 * <CipherData>[MAN] |
|
1805 * <CipherValue/> XOR <CipherReference/> |
|
1806 * </CipherData> |
|
1807 * <EncryptionProperties/>[OPT] |
|
1808 * </EncryptedData> |
|
1809 * --> |
|
1810 * @throws XMLEncryptionException |
|
1811 */ |
|
1812 public EncryptedData createEncryptedData(int type, String value) throws XMLEncryptionException { |
|
1813 EncryptedData result = null; |
|
1814 CipherData data = null; |
|
1815 |
|
1816 switch (type) { |
|
1817 case CipherData.REFERENCE_TYPE: |
|
1818 CipherReference cipherReference = factory.newCipherReference(value); |
|
1819 data = factory.newCipherData(type); |
|
1820 data.setCipherReference(cipherReference); |
|
1821 result = factory.newEncryptedData(data); |
|
1822 break; |
|
1823 case CipherData.VALUE_TYPE: |
|
1824 CipherValue cipherValue = factory.newCipherValue(value); |
|
1825 data = factory.newCipherData(type); |
|
1826 data.setCipherValue(cipherValue); |
|
1827 result = factory.newEncryptedData(data); |
|
1828 } |
|
1829 |
|
1830 return result; |
|
1831 } |
|
1832 |
|
1833 /** |
|
1834 * Creates an <code>EncryptedKey</code> <code>Element</code>. |
|
1835 * |
|
1836 * The newEncryptedData and newEncryptedKey methods create fairly complete |
|
1837 * elements that are immediately useable. All the other create* methods |
|
1838 * return bare elements that still need to be built upon. |
|
1839 *<p> |
|
1840 * An EncryptionMethod will still need to be added however |
|
1841 * |
|
1842 * @param type Either REFERENCE_TYPE or VALUE_TYPE - defines what kind of |
|
1843 * CipherData this EncryptedData will contain. |
|
1844 * @param value the Base 64 encoded, encrypted text to wrap in the |
|
1845 * <code>EncryptedKey</code> or the URI to set in the CipherReference |
|
1846 * (usage will depend on the <code>type</code> |
|
1847 * @return the <code>EncryptedKey</code> <code>Element</code>. |
|
1848 * |
|
1849 * <!-- |
|
1850 * <EncryptedKey Id[OPT] Type[OPT] MimeType[OPT] Encoding[OPT]> |
|
1851 * <EncryptionMethod/>[OPT] |
|
1852 * <ds:KeyInfo>[OPT] |
|
1853 * <EncryptedKey/>[OPT] |
|
1854 * <AgreementMethod/>[OPT] |
|
1855 * <ds:KeyName/>[OPT] |
|
1856 * <ds:RetrievalMethod/>[OPT] |
|
1857 * <ds:[MUL]/>[OPT] |
|
1858 * </ds:KeyInfo> |
|
1859 * <CipherData>[MAN] |
|
1860 * <CipherValue/> XOR <CipherReference/> |
|
1861 * </CipherData> |
|
1862 * <EncryptionProperties/>[OPT] |
|
1863 * </EncryptedData> |
|
1864 * --> |
|
1865 * @throws XMLEncryptionException |
|
1866 */ |
|
1867 public EncryptedKey createEncryptedKey(int type, String value) throws XMLEncryptionException { |
|
1868 EncryptedKey result = null; |
|
1869 CipherData data = null; |
|
1870 |
|
1871 switch (type) { |
|
1872 case CipherData.REFERENCE_TYPE: |
|
1873 CipherReference cipherReference = factory.newCipherReference(value); |
|
1874 data = factory.newCipherData(type); |
|
1875 data.setCipherReference(cipherReference); |
|
1876 result = factory.newEncryptedKey(data); |
|
1877 break; |
|
1878 case CipherData.VALUE_TYPE: |
|
1879 CipherValue cipherValue = factory.newCipherValue(value); |
|
1880 data = factory.newCipherData(type); |
|
1881 data.setCipherValue(cipherValue); |
|
1882 result = factory.newEncryptedKey(data); |
|
1883 } |
|
1884 |
|
1885 return result; |
|
1886 } |
|
1887 |
|
1888 /** |
|
1889 * Create an AgreementMethod object |
|
1890 * |
|
1891 * @param algorithm Algorithm of the agreement method |
|
1892 * @return a new <code>AgreementMethod</code> |
|
1893 */ |
|
1894 public AgreementMethod createAgreementMethod(String algorithm) { |
|
1895 return factory.newAgreementMethod(algorithm); |
|
1896 } |
|
1897 |
|
1898 /** |
|
1899 * Create a CipherData object |
|
1900 * |
|
1901 * @param type Type of this CipherData (either VALUE_TUPE or |
|
1902 * REFERENCE_TYPE) |
|
1903 * @return a new <code>CipherData</code> |
|
1904 */ |
|
1905 public CipherData createCipherData(int type) { |
|
1906 return factory.newCipherData(type); |
|
1907 } |
|
1908 |
|
1909 /** |
|
1910 * Create a CipherReference object |
|
1911 * |
|
1912 * @param uri The URI that the reference will refer |
|
1913 * @return a new <code>CipherReference</code> |
|
1914 */ |
|
1915 public CipherReference createCipherReference(String uri) { |
|
1916 return factory.newCipherReference(uri); |
|
1917 } |
|
1918 |
|
1919 /** |
|
1920 * Create a CipherValue element |
|
1921 * |
|
1922 * @param value The value to set the ciphertext to |
|
1923 * @return a new <code>CipherValue</code> |
|
1924 */ |
|
1925 public CipherValue createCipherValue(String value) { |
|
1926 return factory.newCipherValue(value); |
|
1927 } |
|
1928 |
|
1929 /** |
|
1930 * Create an EncryptionMethod object |
|
1931 * |
|
1932 * @param algorithm Algorithm for the encryption |
|
1933 * @return a new <code>EncryptionMethod</code> |
|
1934 */ |
|
1935 public EncryptionMethod createEncryptionMethod(String algorithm) { |
|
1936 return factory.newEncryptionMethod(algorithm); |
|
1937 } |
|
1938 |
|
1939 /** |
|
1940 * Create an EncryptionProperties element |
|
1941 * @return a new <code>EncryptionProperties</code> |
|
1942 */ |
|
1943 public EncryptionProperties createEncryptionProperties() { |
|
1944 return factory.newEncryptionProperties(); |
|
1945 } |
|
1946 |
|
1947 /** |
|
1948 * Create a new EncryptionProperty element |
|
1949 * @return a new <code>EncryptionProperty</code> |
|
1950 */ |
|
1951 public EncryptionProperty createEncryptionProperty() { |
|
1952 return factory.newEncryptionProperty(); |
|
1953 } |
|
1954 |
|
1955 /** |
|
1956 * Create a new ReferenceList object |
|
1957 * @param type ReferenceList.DATA_REFERENCE or ReferenceList.KEY_REFERENCE |
|
1958 * @return a new <code>ReferenceList</code> |
|
1959 */ |
|
1960 public ReferenceList createReferenceList(int type) { |
|
1961 return factory.newReferenceList(type); |
|
1962 } |
|
1963 |
|
1964 /** |
|
1965 * Create a new Transforms object |
|
1966 * <p> |
|
1967 * <b>Note</b>: A context document <i>must</i> have been set |
|
1968 * elsewhere (possibly via a call to doFinal). If not, use the |
|
1969 * createTransforms(Document) method. |
|
1970 * @return a new <code>Transforms</code> |
|
1971 */ |
|
1972 public Transforms createTransforms() { |
|
1973 return factory.newTransforms(); |
|
1974 } |
|
1975 |
|
1976 /** |
|
1977 * Create a new Transforms object |
|
1978 * |
|
1979 * Because the handling of Transforms is currently done in the signature |
|
1980 * code, the creation of a Transforms object <b>requires</b> a |
|
1981 * context document. |
|
1982 * |
|
1983 * @param doc Document that will own the created Transforms node |
|
1984 * @return a new <code>Transforms</code> |
|
1985 */ |
|
1986 public Transforms createTransforms(Document doc) { |
|
1987 return factory.newTransforms(doc); |
|
1988 } |
|
1989 |
|
1990 /** |
|
1991 * |
|
1992 * @author Axl Mattheus |
|
1993 */ |
|
1994 private class Factory { |
|
1995 /** |
|
1996 * @param algorithm |
|
1997 * @return a new AgreementMethod |
|
1998 */ |
|
1999 AgreementMethod newAgreementMethod(String algorithm) { |
|
2000 return new AgreementMethodImpl(algorithm); |
|
2001 } |
|
2002 |
|
2003 /** |
|
2004 * @param type |
|
2005 * @return a new CipherData |
|
2006 * |
|
2007 */ |
|
2008 CipherData newCipherData(int type) { |
|
2009 return new CipherDataImpl(type); |
|
2010 } |
|
2011 |
|
2012 /** |
|
2013 * @param uri |
|
2014 * @return a new CipherReference |
|
2015 */ |
|
2016 CipherReference newCipherReference(String uri) { |
|
2017 return new CipherReferenceImpl(uri); |
|
2018 } |
|
2019 |
|
2020 /** |
|
2021 * @param value |
|
2022 * @return a new CipherValue |
|
2023 */ |
|
2024 CipherValue newCipherValue(String value) { |
|
2025 return new CipherValueImpl(value); |
|
2026 } |
|
2027 |
|
2028 /* |
|
2029 CipherValue newCipherValue(byte[] value) { |
|
2030 return new CipherValueImpl(value); |
|
2031 } |
|
2032 */ |
|
2033 |
|
2034 /** |
|
2035 * @param data |
|
2036 * @return a new EncryptedData |
|
2037 */ |
|
2038 EncryptedData newEncryptedData(CipherData data) { |
|
2039 return new EncryptedDataImpl(data); |
|
2040 } |
|
2041 |
|
2042 /** |
|
2043 * @param data |
|
2044 * @return a new EncryptedKey |
|
2045 */ |
|
2046 EncryptedKey newEncryptedKey(CipherData data) { |
|
2047 return new EncryptedKeyImpl(data); |
|
2048 } |
|
2049 |
|
2050 /** |
|
2051 * @param algorithm |
|
2052 * @return a new EncryptionMethod |
|
2053 */ |
|
2054 EncryptionMethod newEncryptionMethod(String algorithm) { |
|
2055 return new EncryptionMethodImpl(algorithm); |
|
2056 } |
|
2057 |
|
2058 /** |
|
2059 * @return a new EncryptionProperties |
|
2060 */ |
|
2061 EncryptionProperties newEncryptionProperties() { |
|
2062 return new EncryptionPropertiesImpl(); |
|
2063 } |
|
2064 |
|
2065 /** |
|
2066 * @return a new EncryptionProperty |
|
2067 */ |
|
2068 EncryptionProperty newEncryptionProperty() { |
|
2069 return new EncryptionPropertyImpl(); |
|
2070 } |
|
2071 |
|
2072 /** |
|
2073 * @param type ReferenceList.DATA_REFERENCE or ReferenceList.KEY_REFERENCE |
|
2074 * @return a new ReferenceList |
|
2075 */ |
|
2076 ReferenceList newReferenceList(int type) { |
|
2077 return new ReferenceListImpl(type); |
|
2078 } |
|
2079 |
|
2080 /** |
|
2081 * @return a new Transforms |
|
2082 */ |
|
2083 Transforms newTransforms() { |
|
2084 return new TransformsImpl(); |
|
2085 } |
|
2086 |
|
2087 /** |
|
2088 * @param doc |
|
2089 * @return a new Transforms |
|
2090 */ |
|
2091 Transforms newTransforms(Document doc) { |
|
2092 return new TransformsImpl(doc); |
|
2093 } |
|
2094 |
|
2095 /** |
|
2096 * @param element |
|
2097 * @return a new CipherData |
|
2098 * @throws XMLEncryptionException |
|
2099 */ |
|
2100 CipherData newCipherData(Element element) throws XMLEncryptionException { |
|
2101 if (null == element) { |
|
2102 throw new NullPointerException("element is null"); |
|
2103 } |
|
2104 |
|
2105 int type = 0; |
|
2106 Element e = null; |
|
2107 if (element.getElementsByTagNameNS( |
|
2108 EncryptionConstants.EncryptionSpecNS, |
|
2109 EncryptionConstants._TAG_CIPHERVALUE).getLength() > 0 |
|
2110 ) { |
|
2111 type = CipherData.VALUE_TYPE; |
|
2112 e = (Element) element.getElementsByTagNameNS( |
|
2113 EncryptionConstants.EncryptionSpecNS, |
|
2114 EncryptionConstants._TAG_CIPHERVALUE).item(0); |
|
2115 } else if (element.getElementsByTagNameNS( |
|
2116 EncryptionConstants.EncryptionSpecNS, |
|
2117 EncryptionConstants._TAG_CIPHERREFERENCE).getLength() > 0) { |
|
2118 type = CipherData.REFERENCE_TYPE; |
|
2119 e = (Element) element.getElementsByTagNameNS( |
|
2120 EncryptionConstants.EncryptionSpecNS, |
|
2121 EncryptionConstants._TAG_CIPHERREFERENCE).item(0); |
|
2122 } |
|
2123 |
|
2124 CipherData result = newCipherData(type); |
|
2125 if (type == CipherData.VALUE_TYPE) { |
|
2126 result.setCipherValue(newCipherValue(e)); |
|
2127 } else if (type == CipherData.REFERENCE_TYPE) { |
|
2128 result.setCipherReference(newCipherReference(e)); |
|
2129 } |
|
2130 |
|
2131 return result; |
|
2132 } |
|
2133 |
|
2134 /** |
|
2135 * @param element |
|
2136 * @return a new CipherReference |
|
2137 * @throws XMLEncryptionException |
|
2138 * |
|
2139 */ |
|
2140 CipherReference newCipherReference(Element element) throws XMLEncryptionException { |
|
2141 |
|
2142 Attr uriAttr = |
|
2143 element.getAttributeNodeNS(null, EncryptionConstants._ATT_URI); |
|
2144 CipherReference result = new CipherReferenceImpl(uriAttr); |
|
2145 |
|
2146 // Find any Transforms |
|
2147 NodeList transformsElements = |
|
2148 element.getElementsByTagNameNS( |
|
2149 EncryptionConstants.EncryptionSpecNS, EncryptionConstants._TAG_TRANSFORMS); |
|
2150 Element transformsElement = (Element) transformsElements.item(0); |
|
2151 |
|
2152 if (transformsElement != null) { |
|
2153 if (log.isLoggable(java.util.logging.Level.FINE)) { |
|
2154 log.log(java.util.logging.Level.FINE, "Creating a DSIG based Transforms element"); |
|
2155 } |
|
2156 try { |
|
2157 result.setTransforms(new TransformsImpl(transformsElement)); |
|
2158 } catch (XMLSignatureException xse) { |
|
2159 throw new XMLEncryptionException("empty", xse); |
|
2160 } catch (InvalidTransformException ite) { |
|
2161 throw new XMLEncryptionException("empty", ite); |
|
2162 } catch (XMLSecurityException xse) { |
|
2163 throw new XMLEncryptionException("empty", xse); |
|
2164 } |
|
2165 } |
|
2166 |
|
2167 return result; |
|
2168 } |
|
2169 |
|
2170 /** |
|
2171 * @param element |
|
2172 * @return a new CipherValue |
|
2173 */ |
|
2174 CipherValue newCipherValue(Element element) { |
|
2175 String value = XMLUtils.getFullTextChildrenFromElement(element); |
|
2176 |
|
2177 return newCipherValue(value); |
|
2178 } |
|
2179 |
|
2180 /** |
|
2181 * @param element |
|
2182 * @return a new EncryptedData |
|
2183 * @throws XMLEncryptionException |
|
2184 * |
|
2185 */ |
|
2186 EncryptedData newEncryptedData(Element element) throws XMLEncryptionException { |
|
2187 EncryptedData result = null; |
|
2188 |
|
2189 NodeList dataElements = |
|
2190 element.getElementsByTagNameNS( |
|
2191 EncryptionConstants.EncryptionSpecNS, EncryptionConstants._TAG_CIPHERDATA); |
|
2192 |
|
2193 // Need to get the last CipherData found, as earlier ones will |
|
2194 // be for elements in the KeyInfo lists |
|
2195 |
|
2196 Element dataElement = |
|
2197 (Element) dataElements.item(dataElements.getLength() - 1); |
|
2198 |
|
2199 CipherData data = newCipherData(dataElement); |
|
2200 |
|
2201 result = newEncryptedData(data); |
|
2202 |
|
2203 result.setId(element.getAttributeNS(null, EncryptionConstants._ATT_ID)); |
|
2204 result.setType(element.getAttributeNS(null, EncryptionConstants._ATT_TYPE)); |
|
2205 result.setMimeType(element.getAttributeNS(null, EncryptionConstants._ATT_MIMETYPE)); |
|
2206 result.setEncoding( element.getAttributeNS(null, Constants._ATT_ENCODING)); |
|
2207 |
|
2208 Element encryptionMethodElement = |
|
2209 (Element) element.getElementsByTagNameNS( |
|
2210 EncryptionConstants.EncryptionSpecNS, |
|
2211 EncryptionConstants._TAG_ENCRYPTIONMETHOD).item(0); |
|
2212 if (null != encryptionMethodElement) { |
|
2213 result.setEncryptionMethod(newEncryptionMethod(encryptionMethodElement)); |
|
2214 } |
|
2215 |
|
2216 // BFL 16/7/03 - simple implementation |
|
2217 // TODO: Work out how to handle relative URI |
|
2218 |
|
2219 Element keyInfoElement = |
|
2220 (Element) element.getElementsByTagNameNS( |
|
2221 Constants.SignatureSpecNS, Constants._TAG_KEYINFO).item(0); |
|
2222 if (null != keyInfoElement) { |
|
2223 KeyInfo ki = newKeyInfo(keyInfoElement); |
|
2224 result.setKeyInfo(ki); |
|
2225 } |
|
2226 |
|
2227 // TODO: Implement |
|
2228 Element encryptionPropertiesElement = |
|
2229 (Element) element.getElementsByTagNameNS( |
|
2230 EncryptionConstants.EncryptionSpecNS, |
|
2231 EncryptionConstants._TAG_ENCRYPTIONPROPERTIES).item(0); |
|
2232 if (null != encryptionPropertiesElement) { |
|
2233 result.setEncryptionProperties( |
|
2234 newEncryptionProperties(encryptionPropertiesElement) |
|
2235 ); |
|
2236 } |
|
2237 |
|
2238 return result; |
|
2239 } |
|
2240 |
|
2241 /** |
|
2242 * @param element |
|
2243 * @return a new EncryptedKey |
|
2244 * @throws XMLEncryptionException |
|
2245 */ |
|
2246 EncryptedKey newEncryptedKey(Element element) throws XMLEncryptionException { |
|
2247 EncryptedKey result = null; |
|
2248 NodeList dataElements = |
|
2249 element.getElementsByTagNameNS( |
|
2250 EncryptionConstants.EncryptionSpecNS, EncryptionConstants._TAG_CIPHERDATA); |
|
2251 Element dataElement = |
|
2252 (Element) dataElements.item(dataElements.getLength() - 1); |
|
2253 |
|
2254 CipherData data = newCipherData(dataElement); |
|
2255 result = newEncryptedKey(data); |
|
2256 |
|
2257 result.setId(element.getAttributeNS(null, EncryptionConstants._ATT_ID)); |
|
2258 result.setType(element.getAttributeNS(null, EncryptionConstants._ATT_TYPE)); |
|
2259 result.setMimeType(element.getAttributeNS(null, EncryptionConstants._ATT_MIMETYPE)); |
|
2260 result.setEncoding(element.getAttributeNS(null, Constants._ATT_ENCODING)); |
|
2261 result.setRecipient(element.getAttributeNS(null, EncryptionConstants._ATT_RECIPIENT)); |
|
2262 |
|
2263 Element encryptionMethodElement = |
|
2264 (Element) element.getElementsByTagNameNS( |
|
2265 EncryptionConstants.EncryptionSpecNS, |
|
2266 EncryptionConstants._TAG_ENCRYPTIONMETHOD).item(0); |
|
2267 if (null != encryptionMethodElement) { |
|
2268 result.setEncryptionMethod(newEncryptionMethod(encryptionMethodElement)); |
|
2269 } |
|
2270 |
|
2271 Element keyInfoElement = |
|
2272 (Element) element.getElementsByTagNameNS( |
|
2273 Constants.SignatureSpecNS, Constants._TAG_KEYINFO).item(0); |
|
2274 if (null != keyInfoElement) { |
|
2275 KeyInfo ki = newKeyInfo(keyInfoElement); |
|
2276 result.setKeyInfo(ki); |
|
2277 } |
|
2278 |
|
2279 // TODO: Implement |
|
2280 Element encryptionPropertiesElement = |
|
2281 (Element) element.getElementsByTagNameNS( |
|
2282 EncryptionConstants.EncryptionSpecNS, |
|
2283 EncryptionConstants._TAG_ENCRYPTIONPROPERTIES).item(0); |
|
2284 if (null != encryptionPropertiesElement) { |
|
2285 result.setEncryptionProperties( |
|
2286 newEncryptionProperties(encryptionPropertiesElement) |
|
2287 ); |
|
2288 } |
|
2289 |
|
2290 Element referenceListElement = |
|
2291 (Element) element.getElementsByTagNameNS( |
|
2292 EncryptionConstants.EncryptionSpecNS, |
|
2293 EncryptionConstants._TAG_REFERENCELIST).item(0); |
|
2294 if (null != referenceListElement) { |
|
2295 result.setReferenceList(newReferenceList(referenceListElement)); |
|
2296 } |
|
2297 |
|
2298 Element carriedNameElement = |
|
2299 (Element) element.getElementsByTagNameNS( |
|
2300 EncryptionConstants.EncryptionSpecNS, |
|
2301 EncryptionConstants._TAG_CARRIEDKEYNAME).item(0); |
|
2302 if (null != carriedNameElement) { |
|
2303 result.setCarriedName(carriedNameElement.getFirstChild().getNodeValue()); |
|
2304 } |
|
2305 |
|
2306 return result; |
|
2307 } |
|
2308 |
|
2309 /** |
|
2310 * @param element |
|
2311 * @return a new KeyInfo |
|
2312 * @throws XMLEncryptionException |
|
2313 */ |
|
2314 KeyInfo newKeyInfo(Element element) throws XMLEncryptionException { |
|
2315 try { |
|
2316 KeyInfo ki = new KeyInfo(element, null); |
|
2317 ki.setSecureValidation(secureValidation); |
|
2318 if (internalKeyResolvers != null) { |
|
2319 int size = internalKeyResolvers.size(); |
|
2320 for (int i = 0; i < size; i++) { |
|
2321 ki.registerInternalKeyResolver(internalKeyResolvers.get(i)); |
|
2322 } |
|
2323 } |
|
2324 return ki; |
|
2325 } catch (XMLSecurityException xse) { |
|
2326 throw new XMLEncryptionException("Error loading Key Info", xse); |
|
2327 } |
|
2328 } |
|
2329 |
|
2330 /** |
|
2331 * @param element |
|
2332 * @return a new EncryptionMethod |
|
2333 */ |
|
2334 EncryptionMethod newEncryptionMethod(Element element) { |
|
2335 String encAlgorithm = element.getAttributeNS(null, EncryptionConstants._ATT_ALGORITHM); |
|
2336 EncryptionMethod result = newEncryptionMethod(encAlgorithm); |
|
2337 |
|
2338 Element keySizeElement = |
|
2339 (Element) element.getElementsByTagNameNS( |
|
2340 EncryptionConstants.EncryptionSpecNS, |
|
2341 EncryptionConstants._TAG_KEYSIZE).item(0); |
|
2342 if (null != keySizeElement) { |
|
2343 result.setKeySize( |
|
2344 Integer.valueOf( |
|
2345 keySizeElement.getFirstChild().getNodeValue()).intValue()); |
|
2346 } |
|
2347 |
|
2348 Element oaepParamsElement = |
|
2349 (Element) element.getElementsByTagNameNS( |
|
2350 EncryptionConstants.EncryptionSpecNS, |
|
2351 EncryptionConstants._TAG_OAEPPARAMS).item(0); |
|
2352 if (null != oaepParamsElement) { |
|
2353 try { |
|
2354 String oaepParams = oaepParamsElement.getFirstChild().getNodeValue(); |
|
2355 result.setOAEPparams(Base64.decode(oaepParams.getBytes("UTF-8"))); |
|
2356 } catch(UnsupportedEncodingException e) { |
|
2357 throw new RuntimeException("UTF-8 not supported", e); |
|
2358 } catch (Base64DecodingException e) { |
|
2359 throw new RuntimeException("BASE-64 decoding error", e); |
|
2360 } |
|
2361 } |
|
2362 |
|
2363 Element digestElement = |
|
2364 (Element) element.getElementsByTagNameNS( |
|
2365 Constants.SignatureSpecNS, Constants._TAG_DIGESTMETHOD).item(0); |
|
2366 if (digestElement != null) { |
|
2367 String digestAlgorithm = digestElement.getAttributeNS(null, "Algorithm"); |
|
2368 result.setDigestAlgorithm(digestAlgorithm); |
|
2369 } |
|
2370 |
|
2371 Element mgfElement = |
|
2372 (Element) element.getElementsByTagNameNS( |
|
2373 EncryptionConstants.EncryptionSpec11NS, EncryptionConstants._TAG_MGF).item(0); |
|
2374 if (mgfElement != null && !XMLCipher.RSA_OAEP.equals(algorithm)) { |
|
2375 String mgfAlgorithm = mgfElement.getAttributeNS(null, "Algorithm"); |
|
2376 result.setMGFAlgorithm(mgfAlgorithm); |
|
2377 } |
|
2378 |
|
2379 // TODO: Make this mess work |
|
2380 // <any namespace='##other' minOccurs='0' maxOccurs='unbounded'/> |
|
2381 |
|
2382 return result; |
|
2383 } |
|
2384 |
|
2385 /** |
|
2386 * @param element |
|
2387 * @return a new EncryptionProperties |
|
2388 */ |
|
2389 EncryptionProperties newEncryptionProperties(Element element) { |
|
2390 EncryptionProperties result = newEncryptionProperties(); |
|
2391 |
|
2392 result.setId(element.getAttributeNS(null, EncryptionConstants._ATT_ID)); |
|
2393 |
|
2394 NodeList encryptionPropertyList = |
|
2395 element.getElementsByTagNameNS( |
|
2396 EncryptionConstants.EncryptionSpecNS, |
|
2397 EncryptionConstants._TAG_ENCRYPTIONPROPERTY); |
|
2398 for (int i = 0; i < encryptionPropertyList.getLength(); i++) { |
|
2399 Node n = encryptionPropertyList.item(i); |
|
2400 if (null != n) { |
|
2401 result.addEncryptionProperty(newEncryptionProperty((Element) n)); |
|
2402 } |
|
2403 } |
|
2404 |
|
2405 return result; |
|
2406 } |
|
2407 |
|
2408 /** |
|
2409 * @param element |
|
2410 * @return a new EncryptionProperty |
|
2411 */ |
|
2412 EncryptionProperty newEncryptionProperty(Element element) { |
|
2413 EncryptionProperty result = newEncryptionProperty(); |
|
2414 |
|
2415 result.setTarget(element.getAttributeNS(null, EncryptionConstants._ATT_TARGET)); |
|
2416 result.setId(element.getAttributeNS(null, EncryptionConstants._ATT_ID)); |
|
2417 // TODO: Make this lot work... |
|
2418 // <anyAttribute namespace="http://www.w3.org/XML/1998/namespace"/> |
|
2419 |
|
2420 // TODO: Make this work... |
|
2421 // <any namespace='##other' processContents='lax'/> |
|
2422 |
|
2423 return result; |
|
2424 } |
|
2425 |
|
2426 /** |
|
2427 * @param element |
|
2428 * @return a new ReferenceList |
|
2429 */ |
|
2430 ReferenceList newReferenceList(Element element) { |
|
2431 int type = 0; |
|
2432 if (null != element.getElementsByTagNameNS( |
|
2433 EncryptionConstants.EncryptionSpecNS, |
|
2434 EncryptionConstants._TAG_DATAREFERENCE).item(0)) { |
|
2435 type = ReferenceList.DATA_REFERENCE; |
|
2436 } else if (null != element.getElementsByTagNameNS( |
|
2437 EncryptionConstants.EncryptionSpecNS, |
|
2438 EncryptionConstants._TAG_KEYREFERENCE).item(0)) { |
|
2439 type = ReferenceList.KEY_REFERENCE; |
|
2440 } |
|
2441 |
|
2442 ReferenceList result = new ReferenceListImpl(type); |
|
2443 NodeList list = null; |
|
2444 switch (type) { |
|
2445 case ReferenceList.DATA_REFERENCE: |
|
2446 list = |
|
2447 element.getElementsByTagNameNS( |
|
2448 EncryptionConstants.EncryptionSpecNS, |
|
2449 EncryptionConstants._TAG_DATAREFERENCE); |
|
2450 for (int i = 0; i < list.getLength() ; i++) { |
|
2451 String uri = ((Element) list.item(i)).getAttribute("URI"); |
|
2452 result.add(result.newDataReference(uri)); |
|
2453 } |
|
2454 break; |
|
2455 case ReferenceList.KEY_REFERENCE: |
|
2456 list = |
|
2457 element.getElementsByTagNameNS( |
|
2458 EncryptionConstants.EncryptionSpecNS, |
|
2459 EncryptionConstants._TAG_KEYREFERENCE); |
|
2460 for (int i = 0; i < list.getLength() ; i++) { |
|
2461 String uri = ((Element) list.item(i)).getAttribute("URI"); |
|
2462 result.add(result.newKeyReference(uri)); |
|
2463 } |
|
2464 } |
|
2465 |
|
2466 return result; |
|
2467 } |
|
2468 |
|
2469 /** |
|
2470 * @param encryptedData |
|
2471 * @return the XML Element form of that EncryptedData |
|
2472 */ |
|
2473 Element toElement(EncryptedData encryptedData) { |
|
2474 return ((EncryptedDataImpl) encryptedData).toElement(); |
|
2475 } |
|
2476 |
|
2477 /** |
|
2478 * @param encryptedKey |
|
2479 * @return the XML Element form of that EncryptedKey |
|
2480 */ |
|
2481 Element toElement(EncryptedKey encryptedKey) { |
|
2482 return ((EncryptedKeyImpl) encryptedKey).toElement(); |
|
2483 } |
|
2484 |
|
2485 /** |
|
2486 * @param referenceList |
|
2487 * @return the XML Element form of that ReferenceList |
|
2488 */ |
|
2489 Element toElement(ReferenceList referenceList) { |
|
2490 return ((ReferenceListImpl) referenceList).toElement(); |
|
2491 } |
|
2492 |
|
2493 private class AgreementMethodImpl implements AgreementMethod { |
|
2494 private byte[] kaNonce = null; |
|
2495 private List<Element> agreementMethodInformation = null; |
|
2496 private KeyInfo originatorKeyInfo = null; |
|
2497 private KeyInfo recipientKeyInfo = null; |
|
2498 private String algorithmURI = null; |
|
2499 |
|
2500 /** |
|
2501 * @param algorithm |
|
2502 */ |
|
2503 public AgreementMethodImpl(String algorithm) { |
|
2504 agreementMethodInformation = new LinkedList<Element>(); |
|
2505 URI tmpAlgorithm = null; |
|
2506 try { |
|
2507 tmpAlgorithm = new URI(algorithm); |
|
2508 } catch (URISyntaxException ex) { |
|
2509 throw (IllegalArgumentException) |
|
2510 new IllegalArgumentException().initCause(ex); |
|
2511 } |
|
2512 algorithmURI = tmpAlgorithm.toString(); |
|
2513 } |
|
2514 |
|
2515 /** @inheritDoc */ |
|
2516 public byte[] getKANonce() { |
|
2517 return kaNonce; |
|
2518 } |
|
2519 |
|
2520 /** @inheritDoc */ |
|
2521 public void setKANonce(byte[] kanonce) { |
|
2522 kaNonce = kanonce; |
|
2523 } |
|
2524 |
|
2525 /** @inheritDoc */ |
|
2526 public Iterator<Element> getAgreementMethodInformation() { |
|
2527 return agreementMethodInformation.iterator(); |
|
2528 } |
|
2529 |
|
2530 /** @inheritDoc */ |
|
2531 public void addAgreementMethodInformation(Element info) { |
|
2532 agreementMethodInformation.add(info); |
|
2533 } |
|
2534 |
|
2535 /** @inheritDoc */ |
|
2536 public void revoveAgreementMethodInformation(Element info) { |
|
2537 agreementMethodInformation.remove(info); |
|
2538 } |
|
2539 |
|
2540 /** @inheritDoc */ |
|
2541 public KeyInfo getOriginatorKeyInfo() { |
|
2542 return originatorKeyInfo; |
|
2543 } |
|
2544 |
|
2545 /** @inheritDoc */ |
|
2546 public void setOriginatorKeyInfo(KeyInfo keyInfo) { |
|
2547 originatorKeyInfo = keyInfo; |
|
2548 } |
|
2549 |
|
2550 /** @inheritDoc */ |
|
2551 public KeyInfo getRecipientKeyInfo() { |
|
2552 return recipientKeyInfo; |
|
2553 } |
|
2554 |
|
2555 /** @inheritDoc */ |
|
2556 public void setRecipientKeyInfo(KeyInfo keyInfo) { |
|
2557 recipientKeyInfo = keyInfo; |
|
2558 } |
|
2559 |
|
2560 /** @inheritDoc */ |
|
2561 public String getAlgorithm() { |
|
2562 return algorithmURI; |
|
2563 } |
|
2564 } |
|
2565 |
|
2566 private class CipherDataImpl implements CipherData { |
|
2567 private static final String valueMessage = |
|
2568 "Data type is reference type."; |
|
2569 private static final String referenceMessage = |
|
2570 "Data type is value type."; |
|
2571 private CipherValue cipherValue = null; |
|
2572 private CipherReference cipherReference = null; |
|
2573 private int cipherType = Integer.MIN_VALUE; |
|
2574 |
|
2575 /** |
|
2576 * @param type |
|
2577 */ |
|
2578 public CipherDataImpl(int type) { |
|
2579 cipherType = type; |
|
2580 } |
|
2581 |
|
2582 /** @inheritDoc */ |
|
2583 public CipherValue getCipherValue() { |
|
2584 return cipherValue; |
|
2585 } |
|
2586 |
|
2587 /** @inheritDoc */ |
|
2588 public void setCipherValue(CipherValue value) throws XMLEncryptionException { |
|
2589 |
|
2590 if (cipherType == REFERENCE_TYPE) { |
|
2591 throw new XMLEncryptionException( |
|
2592 "empty", new UnsupportedOperationException(valueMessage) |
|
2593 ); |
|
2594 } |
|
2595 |
|
2596 cipherValue = value; |
|
2597 } |
|
2598 |
|
2599 /** @inheritDoc */ |
|
2600 public CipherReference getCipherReference() { |
|
2601 return cipherReference; |
|
2602 } |
|
2603 |
|
2604 /** @inheritDoc */ |
|
2605 public void setCipherReference(CipherReference reference) throws |
|
2606 XMLEncryptionException { |
|
2607 if (cipherType == VALUE_TYPE) { |
|
2608 throw new XMLEncryptionException( |
|
2609 "empty", new UnsupportedOperationException(referenceMessage) |
|
2610 ); |
|
2611 } |
|
2612 |
|
2613 cipherReference = reference; |
|
2614 } |
|
2615 |
|
2616 /** @inheritDoc */ |
|
2617 public int getDataType() { |
|
2618 return cipherType; |
|
2619 } |
|
2620 |
|
2621 Element toElement() { |
|
2622 Element result = |
|
2623 XMLUtils.createElementInEncryptionSpace( |
|
2624 contextDocument, EncryptionConstants._TAG_CIPHERDATA |
|
2625 ); |
|
2626 if (cipherType == VALUE_TYPE) { |
|
2627 result.appendChild(((CipherValueImpl) cipherValue).toElement()); |
|
2628 } else if (cipherType == REFERENCE_TYPE) { |
|
2629 result.appendChild(((CipherReferenceImpl) cipherReference).toElement()); |
|
2630 } |
|
2631 |
|
2632 return result; |
|
2633 } |
|
2634 } |
|
2635 |
|
2636 private class CipherReferenceImpl implements CipherReference { |
|
2637 private String referenceURI = null; |
|
2638 private Transforms referenceTransforms = null; |
|
2639 private Attr referenceNode = null; |
|
2640 |
|
2641 /** |
|
2642 * @param uri |
|
2643 */ |
|
2644 public CipherReferenceImpl(String uri) { |
|
2645 /* Don't check validity of URI as may be "" */ |
|
2646 referenceURI = uri; |
|
2647 referenceNode = null; |
|
2648 } |
|
2649 |
|
2650 /** |
|
2651 * @param uri |
|
2652 */ |
|
2653 public CipherReferenceImpl(Attr uri) { |
|
2654 referenceURI = uri.getNodeValue(); |
|
2655 referenceNode = uri; |
|
2656 } |
|
2657 |
|
2658 /** @inheritDoc */ |
|
2659 public String getURI() { |
|
2660 return referenceURI; |
|
2661 } |
|
2662 |
|
2663 /** @inheritDoc */ |
|
2664 public Attr getURIAsAttr() { |
|
2665 return referenceNode; |
|
2666 } |
|
2667 |
|
2668 /** @inheritDoc */ |
|
2669 public Transforms getTransforms() { |
|
2670 return referenceTransforms; |
|
2671 } |
|
2672 |
|
2673 /** @inheritDoc */ |
|
2674 public void setTransforms(Transforms transforms) { |
|
2675 referenceTransforms = transforms; |
|
2676 } |
|
2677 |
|
2678 Element toElement() { |
|
2679 Element result = |
|
2680 XMLUtils.createElementInEncryptionSpace( |
|
2681 contextDocument, EncryptionConstants._TAG_CIPHERREFERENCE |
|
2682 ); |
|
2683 result.setAttributeNS(null, EncryptionConstants._ATT_URI, referenceURI); |
|
2684 if (null != referenceTransforms) { |
|
2685 result.appendChild(((TransformsImpl) referenceTransforms).toElement()); |
|
2686 } |
|
2687 |
|
2688 return result; |
|
2689 } |
|
2690 } |
|
2691 |
|
2692 private class CipherValueImpl implements CipherValue { |
|
2693 private String cipherValue = null; |
|
2694 |
|
2695 /** |
|
2696 * @param value |
|
2697 */ |
|
2698 public CipherValueImpl(String value) { |
|
2699 cipherValue = value; |
|
2700 } |
|
2701 |
|
2702 /** @inheritDoc */ |
|
2703 public String getValue() { |
|
2704 return cipherValue; |
|
2705 } |
|
2706 |
|
2707 /** @inheritDoc */ |
|
2708 public void setValue(String value) { |
|
2709 cipherValue = value; |
|
2710 } |
|
2711 |
|
2712 Element toElement() { |
|
2713 Element result = |
|
2714 XMLUtils.createElementInEncryptionSpace( |
|
2715 contextDocument, EncryptionConstants._TAG_CIPHERVALUE |
|
2716 ); |
|
2717 result.appendChild(contextDocument.createTextNode(cipherValue)); |
|
2718 |
|
2719 return result; |
|
2720 } |
|
2721 } |
|
2722 |
|
2723 private class EncryptedDataImpl extends EncryptedTypeImpl implements EncryptedData { |
|
2724 |
|
2725 /** |
|
2726 * @param data |
|
2727 */ |
|
2728 public EncryptedDataImpl(CipherData data) { |
|
2729 super(data); |
|
2730 } |
|
2731 |
|
2732 Element toElement() { |
|
2733 Element result = |
|
2734 ElementProxy.createElementForFamily( |
|
2735 contextDocument, EncryptionConstants.EncryptionSpecNS, |
|
2736 EncryptionConstants._TAG_ENCRYPTEDDATA |
|
2737 ); |
|
2738 |
|
2739 if (null != super.getId()) { |
|
2740 result.setAttributeNS(null, EncryptionConstants._ATT_ID, super.getId()); |
|
2741 } |
|
2742 if (null != super.getType()) { |
|
2743 result.setAttributeNS(null, EncryptionConstants._ATT_TYPE, super.getType()); |
|
2744 } |
|
2745 if (null != super.getMimeType()) { |
|
2746 result.setAttributeNS( |
|
2747 null, EncryptionConstants._ATT_MIMETYPE, super.getMimeType() |
|
2748 ); |
|
2749 } |
|
2750 if (null != super.getEncoding()) { |
|
2751 result.setAttributeNS( |
|
2752 null, EncryptionConstants._ATT_ENCODING, super.getEncoding() |
|
2753 ); |
|
2754 } |
|
2755 if (null != super.getEncryptionMethod()) { |
|
2756 result.appendChild( |
|
2757 ((EncryptionMethodImpl)super.getEncryptionMethod()).toElement() |
|
2758 ); |
|
2759 } |
|
2760 if (null != super.getKeyInfo()) { |
|
2761 result.appendChild(super.getKeyInfo().getElement().cloneNode(true)); |
|
2762 } |
|
2763 |
|
2764 result.appendChild(((CipherDataImpl) super.getCipherData()).toElement()); |
|
2765 if (null != super.getEncryptionProperties()) { |
|
2766 result.appendChild(((EncryptionPropertiesImpl) |
|
2767 super.getEncryptionProperties()).toElement()); |
|
2768 } |
|
2769 |
|
2770 return result; |
|
2771 } |
|
2772 } |
|
2773 |
|
2774 private class EncryptedKeyImpl extends EncryptedTypeImpl implements EncryptedKey { |
|
2775 private String keyRecipient = null; |
|
2776 private ReferenceList referenceList = null; |
|
2777 private String carriedName = null; |
|
2778 |
|
2779 /** |
|
2780 * @param data |
|
2781 */ |
|
2782 public EncryptedKeyImpl(CipherData data) { |
|
2783 super(data); |
|
2784 } |
|
2785 |
|
2786 /** @inheritDoc */ |
|
2787 public String getRecipient() { |
|
2788 return keyRecipient; |
|
2789 } |
|
2790 |
|
2791 /** @inheritDoc */ |
|
2792 public void setRecipient(String recipient) { |
|
2793 keyRecipient = recipient; |
|
2794 } |
|
2795 |
|
2796 /** @inheritDoc */ |
|
2797 public ReferenceList getReferenceList() { |
|
2798 return referenceList; |
|
2799 } |
|
2800 |
|
2801 /** @inheritDoc */ |
|
2802 public void setReferenceList(ReferenceList list) { |
|
2803 referenceList = list; |
|
2804 } |
|
2805 |
|
2806 /** @inheritDoc */ |
|
2807 public String getCarriedName() { |
|
2808 return carriedName; |
|
2809 } |
|
2810 |
|
2811 /** @inheritDoc */ |
|
2812 public void setCarriedName(String name) { |
|
2813 carriedName = name; |
|
2814 } |
|
2815 |
|
2816 Element toElement() { |
|
2817 Element result = |
|
2818 ElementProxy.createElementForFamily( |
|
2819 contextDocument, EncryptionConstants.EncryptionSpecNS, |
|
2820 EncryptionConstants._TAG_ENCRYPTEDKEY |
|
2821 ); |
|
2822 |
|
2823 if (null != super.getId()) { |
|
2824 result.setAttributeNS(null, EncryptionConstants._ATT_ID, super.getId()); |
|
2825 } |
|
2826 if (null != super.getType()) { |
|
2827 result.setAttributeNS(null, EncryptionConstants._ATT_TYPE, super.getType()); |
|
2828 } |
|
2829 if (null != super.getMimeType()) { |
|
2830 result.setAttributeNS( |
|
2831 null, EncryptionConstants._ATT_MIMETYPE, super.getMimeType() |
|
2832 ); |
|
2833 } |
|
2834 if (null != super.getEncoding()) { |
|
2835 result.setAttributeNS(null, Constants._ATT_ENCODING, super.getEncoding()); |
|
2836 } |
|
2837 if (null != getRecipient()) { |
|
2838 result.setAttributeNS( |
|
2839 null, EncryptionConstants._ATT_RECIPIENT, getRecipient() |
|
2840 ); |
|
2841 } |
|
2842 if (null != super.getEncryptionMethod()) { |
|
2843 result.appendChild(((EncryptionMethodImpl) |
|
2844 super.getEncryptionMethod()).toElement()); |
|
2845 } |
|
2846 if (null != super.getKeyInfo()) { |
|
2847 result.appendChild(super.getKeyInfo().getElement().cloneNode(true)); |
|
2848 } |
|
2849 result.appendChild(((CipherDataImpl) super.getCipherData()).toElement()); |
|
2850 if (null != super.getEncryptionProperties()) { |
|
2851 result.appendChild(((EncryptionPropertiesImpl) |
|
2852 super.getEncryptionProperties()).toElement()); |
|
2853 } |
|
2854 if (referenceList != null && !referenceList.isEmpty()) { |
|
2855 result.appendChild(((ReferenceListImpl)getReferenceList()).toElement()); |
|
2856 } |
|
2857 if (null != carriedName) { |
|
2858 Element element = |
|
2859 ElementProxy.createElementForFamily( |
|
2860 contextDocument, |
|
2861 EncryptionConstants.EncryptionSpecNS, |
|
2862 EncryptionConstants._TAG_CARRIEDKEYNAME |
|
2863 ); |
|
2864 Node node = contextDocument.createTextNode(carriedName); |
|
2865 element.appendChild(node); |
|
2866 result.appendChild(element); |
|
2867 } |
|
2868 |
|
2869 return result; |
|
2870 } |
|
2871 } |
|
2872 |
|
2873 private abstract class EncryptedTypeImpl { |
|
2874 private String id = null; |
|
2875 private String type = null; |
|
2876 private String mimeType = null; |
|
2877 private String encoding = null; |
|
2878 private EncryptionMethod encryptionMethod = null; |
|
2879 private KeyInfo keyInfo = null; |
|
2880 private CipherData cipherData = null; |
|
2881 private EncryptionProperties encryptionProperties = null; |
|
2882 |
|
2883 /** |
|
2884 * Constructor. |
|
2885 * @param data |
|
2886 */ |
|
2887 protected EncryptedTypeImpl(CipherData data) { |
|
2888 cipherData = data; |
|
2889 } |
|
2890 |
|
2891 /** |
|
2892 * |
|
2893 * @return the Id |
|
2894 */ |
|
2895 public String getId() { |
|
2896 return id; |
|
2897 } |
|
2898 |
|
2899 /** |
|
2900 * |
|
2901 * @param id |
|
2902 */ |
|
2903 public void setId(String id) { |
|
2904 this.id = id; |
|
2905 } |
|
2906 |
|
2907 /** |
|
2908 * |
|
2909 * @return the type |
|
2910 */ |
|
2911 public String getType() { |
|
2912 return type; |
|
2913 } |
|
2914 |
|
2915 /** |
|
2916 * |
|
2917 * @param type |
|
2918 */ |
|
2919 public void setType(String type) { |
|
2920 if (type == null || type.length() == 0) { |
|
2921 this.type = null; |
|
2922 } else { |
|
2923 URI tmpType = null; |
|
2924 try { |
|
2925 tmpType = new URI(type); |
|
2926 } catch (URISyntaxException ex) { |
|
2927 throw (IllegalArgumentException) |
|
2928 new IllegalArgumentException().initCause(ex); |
|
2929 } |
|
2930 this.type = tmpType.toString(); |
|
2931 } |
|
2932 } |
|
2933 |
|
2934 /** |
|
2935 * |
|
2936 * @return the MimeType |
|
2937 */ |
|
2938 public String getMimeType() { |
|
2939 return mimeType; |
|
2940 } |
|
2941 /** |
|
2942 * |
|
2943 * @param type |
|
2944 */ |
|
2945 public void setMimeType(String type) { |
|
2946 mimeType = type; |
|
2947 } |
|
2948 |
|
2949 /** |
|
2950 * |
|
2951 * @return the encoding |
|
2952 */ |
|
2953 public String getEncoding() { |
|
2954 return encoding; |
|
2955 } |
|
2956 |
|
2957 /** |
|
2958 * |
|
2959 * @param encoding |
|
2960 */ |
|
2961 public void setEncoding(String encoding) { |
|
2962 if (encoding == null || encoding.length() == 0) { |
|
2963 this.encoding = null; |
|
2964 } else { |
|
2965 URI tmpEncoding = null; |
|
2966 try { |
|
2967 tmpEncoding = new URI(encoding); |
|
2968 } catch (URISyntaxException ex) { |
|
2969 throw (IllegalArgumentException) |
|
2970 new IllegalArgumentException().initCause(ex); |
|
2971 } |
|
2972 this.encoding = tmpEncoding.toString(); |
|
2973 } |
|
2974 } |
|
2975 |
|
2976 /** |
|
2977 * |
|
2978 * @return the EncryptionMethod |
|
2979 */ |
|
2980 public EncryptionMethod getEncryptionMethod() { |
|
2981 return encryptionMethod; |
|
2982 } |
|
2983 |
|
2984 /** |
|
2985 * |
|
2986 * @param method |
|
2987 */ |
|
2988 public void setEncryptionMethod(EncryptionMethod method) { |
|
2989 encryptionMethod = method; |
|
2990 } |
|
2991 |
|
2992 /** |
|
2993 * |
|
2994 * @return the KeyInfo |
|
2995 */ |
|
2996 public KeyInfo getKeyInfo() { |
|
2997 return keyInfo; |
|
2998 } |
|
2999 |
|
3000 /** |
|
3001 * |
|
3002 * @param info |
|
3003 */ |
|
3004 public void setKeyInfo(KeyInfo info) { |
|
3005 keyInfo = info; |
|
3006 } |
|
3007 |
|
3008 /** |
|
3009 * |
|
3010 * @return the CipherData |
|
3011 */ |
|
3012 public CipherData getCipherData() { |
|
3013 return cipherData; |
|
3014 } |
|
3015 |
|
3016 /** |
|
3017 * |
|
3018 * @return the EncryptionProperties |
|
3019 */ |
|
3020 public EncryptionProperties getEncryptionProperties() { |
|
3021 return encryptionProperties; |
|
3022 } |
|
3023 |
|
3024 /** |
|
3025 * |
|
3026 * @param properties |
|
3027 */ |
|
3028 public void setEncryptionProperties(EncryptionProperties properties) { |
|
3029 encryptionProperties = properties; |
|
3030 } |
|
3031 } |
|
3032 |
|
3033 private class EncryptionMethodImpl implements EncryptionMethod { |
|
3034 private String algorithm = null; |
|
3035 private int keySize = Integer.MIN_VALUE; |
|
3036 private byte[] oaepParams = null; |
|
3037 private List<Element> encryptionMethodInformation = null; |
|
3038 private String digestAlgorithm = null; |
|
3039 private String mgfAlgorithm = null; |
|
3040 |
|
3041 /** |
|
3042 * Constructor. |
|
3043 * @param algorithm |
|
3044 */ |
|
3045 public EncryptionMethodImpl(String algorithm) { |
|
3046 URI tmpAlgorithm = null; |
|
3047 try { |
|
3048 tmpAlgorithm = new URI(algorithm); |
|
3049 } catch (URISyntaxException ex) { |
|
3050 throw (IllegalArgumentException) |
|
3051 new IllegalArgumentException().initCause(ex); |
|
3052 } |
|
3053 this.algorithm = tmpAlgorithm.toString(); |
|
3054 encryptionMethodInformation = new LinkedList<Element>(); |
|
3055 } |
|
3056 |
|
3057 /** @inheritDoc */ |
|
3058 public String getAlgorithm() { |
|
3059 return algorithm; |
|
3060 } |
|
3061 |
|
3062 /** @inheritDoc */ |
|
3063 public int getKeySize() { |
|
3064 return keySize; |
|
3065 } |
|
3066 |
|
3067 /** @inheritDoc */ |
|
3068 public void setKeySize(int size) { |
|
3069 keySize = size; |
|
3070 } |
|
3071 |
|
3072 /** @inheritDoc */ |
|
3073 public byte[] getOAEPparams() { |
|
3074 return oaepParams; |
|
3075 } |
|
3076 |
|
3077 /** @inheritDoc */ |
|
3078 public void setOAEPparams(byte[] params) { |
|
3079 oaepParams = params; |
|
3080 } |
|
3081 |
|
3082 /** @inheritDoc */ |
|
3083 public void setDigestAlgorithm(String digestAlgorithm) { |
|
3084 this.digestAlgorithm = digestAlgorithm; |
|
3085 } |
|
3086 |
|
3087 /** @inheritDoc */ |
|
3088 public String getDigestAlgorithm() { |
|
3089 return digestAlgorithm; |
|
3090 } |
|
3091 |
|
3092 /** @inheritDoc */ |
|
3093 public void setMGFAlgorithm(String mgfAlgorithm) { |
|
3094 this.mgfAlgorithm = mgfAlgorithm; |
|
3095 } |
|
3096 |
|
3097 /** @inheritDoc */ |
|
3098 public String getMGFAlgorithm() { |
|
3099 return mgfAlgorithm; |
|
3100 } |
|
3101 |
|
3102 /** @inheritDoc */ |
|
3103 public Iterator<Element> getEncryptionMethodInformation() { |
|
3104 return encryptionMethodInformation.iterator(); |
|
3105 } |
|
3106 |
|
3107 /** @inheritDoc */ |
|
3108 public void addEncryptionMethodInformation(Element info) { |
|
3109 encryptionMethodInformation.add(info); |
|
3110 } |
|
3111 |
|
3112 /** @inheritDoc */ |
|
3113 public void removeEncryptionMethodInformation(Element info) { |
|
3114 encryptionMethodInformation.remove(info); |
|
3115 } |
|
3116 |
|
3117 Element toElement() { |
|
3118 Element result = |
|
3119 XMLUtils.createElementInEncryptionSpace( |
|
3120 contextDocument, EncryptionConstants._TAG_ENCRYPTIONMETHOD |
|
3121 ); |
|
3122 result.setAttributeNS(null, EncryptionConstants._ATT_ALGORITHM, algorithm); |
|
3123 if (keySize > 0) { |
|
3124 result.appendChild( |
|
3125 XMLUtils.createElementInEncryptionSpace( |
|
3126 contextDocument, EncryptionConstants._TAG_KEYSIZE |
|
3127 ).appendChild(contextDocument.createTextNode(String.valueOf(keySize)))); |
|
3128 } |
|
3129 if (null != oaepParams) { |
|
3130 Element oaepElement = |
|
3131 XMLUtils.createElementInEncryptionSpace( |
|
3132 contextDocument, EncryptionConstants._TAG_OAEPPARAMS |
|
3133 ); |
|
3134 oaepElement.appendChild(contextDocument.createTextNode(Base64.encode(oaepParams))); |
|
3135 result.appendChild(oaepElement); |
|
3136 } |
|
3137 if (digestAlgorithm != null) { |
|
3138 Element digestElement = |
|
3139 XMLUtils.createElementInSignatureSpace(contextDocument, Constants._TAG_DIGESTMETHOD); |
|
3140 digestElement.setAttributeNS(null, "Algorithm", digestAlgorithm); |
|
3141 result.appendChild(digestElement); |
|
3142 } |
|
3143 if (mgfAlgorithm != null) { |
|
3144 Element mgfElement = |
|
3145 XMLUtils.createElementInEncryption11Space( |
|
3146 contextDocument, EncryptionConstants._TAG_MGF |
|
3147 ); |
|
3148 mgfElement.setAttributeNS(null, "Algorithm", mgfAlgorithm); |
|
3149 mgfElement.setAttributeNS( |
|
3150 Constants.NamespaceSpecNS, |
|
3151 "xmlns:" + ElementProxy.getDefaultPrefix(EncryptionConstants.EncryptionSpec11NS), |
|
3152 EncryptionConstants.EncryptionSpec11NS |
|
3153 ); |
|
3154 result.appendChild(mgfElement); |
|
3155 } |
|
3156 Iterator<Element> itr = encryptionMethodInformation.iterator(); |
|
3157 while (itr.hasNext()) { |
|
3158 result.appendChild(itr.next()); |
|
3159 } |
|
3160 |
|
3161 return result; |
|
3162 } |
|
3163 } |
|
3164 |
|
3165 private class EncryptionPropertiesImpl implements EncryptionProperties { |
|
3166 private String id = null; |
|
3167 private List<EncryptionProperty> encryptionProperties = null; |
|
3168 |
|
3169 /** |
|
3170 * Constructor. |
|
3171 */ |
|
3172 public EncryptionPropertiesImpl() { |
|
3173 encryptionProperties = new LinkedList<EncryptionProperty>(); |
|
3174 } |
|
3175 |
|
3176 /** @inheritDoc */ |
|
3177 public String getId() { |
|
3178 return id; |
|
3179 } |
|
3180 |
|
3181 /** @inheritDoc */ |
|
3182 public void setId(String id) { |
|
3183 this.id = id; |
|
3184 } |
|
3185 |
|
3186 /** @inheritDoc */ |
|
3187 public Iterator<EncryptionProperty> getEncryptionProperties() { |
|
3188 return encryptionProperties.iterator(); |
|
3189 } |
|
3190 |
|
3191 /** @inheritDoc */ |
|
3192 public void addEncryptionProperty(EncryptionProperty property) { |
|
3193 encryptionProperties.add(property); |
|
3194 } |
|
3195 |
|
3196 /** @inheritDoc */ |
|
3197 public void removeEncryptionProperty(EncryptionProperty property) { |
|
3198 encryptionProperties.remove(property); |
|
3199 } |
|
3200 |
|
3201 Element toElement() { |
|
3202 Element result = |
|
3203 XMLUtils.createElementInEncryptionSpace( |
|
3204 contextDocument, EncryptionConstants._TAG_ENCRYPTIONPROPERTIES |
|
3205 ); |
|
3206 if (null != id) { |
|
3207 result.setAttributeNS(null, EncryptionConstants._ATT_ID, id); |
|
3208 } |
|
3209 Iterator<EncryptionProperty> itr = getEncryptionProperties(); |
|
3210 while (itr.hasNext()) { |
|
3211 result.appendChild(((EncryptionPropertyImpl)itr.next()).toElement()); |
|
3212 } |
|
3213 |
|
3214 return result; |
|
3215 } |
|
3216 } |
|
3217 |
|
3218 private class EncryptionPropertyImpl implements EncryptionProperty { |
|
3219 private String target = null; |
|
3220 private String id = null; |
|
3221 private Map<String, String> attributeMap = new HashMap<String, String>(); |
|
3222 private List<Element> encryptionInformation = null; |
|
3223 |
|
3224 /** |
|
3225 * Constructor. |
|
3226 */ |
|
3227 public EncryptionPropertyImpl() { |
|
3228 encryptionInformation = new LinkedList<Element>(); |
|
3229 } |
|
3230 |
|
3231 /** @inheritDoc */ |
|
3232 public String getTarget() { |
|
3233 return target; |
|
3234 } |
|
3235 |
|
3236 /** @inheritDoc */ |
|
3237 public void setTarget(String target) { |
|
3238 if (target == null || target.length() == 0) { |
|
3239 this.target = null; |
|
3240 } else if (target.startsWith("#")) { |
|
3241 /* |
|
3242 * This is a same document URI reference. Do not parse, |
|
3243 * because it has no scheme. |
|
3244 */ |
|
3245 this.target = target; |
|
3246 } else { |
|
3247 URI tmpTarget = null; |
|
3248 try { |
|
3249 tmpTarget = new URI(target); |
|
3250 } catch (URISyntaxException ex) { |
|
3251 throw (IllegalArgumentException) |
|
3252 new IllegalArgumentException().initCause(ex); |
|
3253 } |
|
3254 this.target = tmpTarget.toString(); |
|
3255 } |
|
3256 } |
|
3257 |
|
3258 /** @inheritDoc */ |
|
3259 public String getId() { |
|
3260 return id; |
|
3261 } |
|
3262 |
|
3263 /** @inheritDoc */ |
|
3264 public void setId(String id) { |
|
3265 this.id = id; |
|
3266 } |
|
3267 |
|
3268 /** @inheritDoc */ |
|
3269 public String getAttribute(String attribute) { |
|
3270 return attributeMap.get(attribute); |
|
3271 } |
|
3272 |
|
3273 /** @inheritDoc */ |
|
3274 public void setAttribute(String attribute, String value) { |
|
3275 attributeMap.put(attribute, value); |
|
3276 } |
|
3277 |
|
3278 /** @inheritDoc */ |
|
3279 public Iterator<Element> getEncryptionInformation() { |
|
3280 return encryptionInformation.iterator(); |
|
3281 } |
|
3282 |
|
3283 /** @inheritDoc */ |
|
3284 public void addEncryptionInformation(Element info) { |
|
3285 encryptionInformation.add(info); |
|
3286 } |
|
3287 |
|
3288 /** @inheritDoc */ |
|
3289 public void removeEncryptionInformation(Element info) { |
|
3290 encryptionInformation.remove(info); |
|
3291 } |
|
3292 |
|
3293 Element toElement() { |
|
3294 Element result = |
|
3295 XMLUtils.createElementInEncryptionSpace( |
|
3296 contextDocument, EncryptionConstants._TAG_ENCRYPTIONPROPERTY |
|
3297 ); |
|
3298 if (null != target) { |
|
3299 result.setAttributeNS(null, EncryptionConstants._ATT_TARGET, target); |
|
3300 } |
|
3301 if (null != id) { |
|
3302 result.setAttributeNS(null, EncryptionConstants._ATT_ID, id); |
|
3303 } |
|
3304 // TODO: figure out the anyAttribyte stuff... |
|
3305 // TODO: figure out the any stuff... |
|
3306 |
|
3307 return result; |
|
3308 } |
|
3309 } |
|
3310 |
|
3311 private class TransformsImpl extends com.sun.org.apache.xml.internal.security.transforms.Transforms |
|
3312 implements Transforms { |
|
3313 |
|
3314 /** |
|
3315 * Construct Transforms |
|
3316 */ |
|
3317 public TransformsImpl() { |
|
3318 super(contextDocument); |
|
3319 } |
|
3320 |
|
3321 /** |
|
3322 * |
|
3323 * @param doc |
|
3324 */ |
|
3325 public TransformsImpl(Document doc) { |
|
3326 if (doc == null) { |
|
3327 throw new RuntimeException("Document is null"); |
|
3328 } |
|
3329 |
|
3330 this.doc = doc; |
|
3331 this.constructionElement = |
|
3332 createElementForFamilyLocal( |
|
3333 this.doc, this.getBaseNamespace(), this.getBaseLocalName() |
|
3334 ); |
|
3335 } |
|
3336 |
|
3337 /** |
|
3338 * |
|
3339 * @param element |
|
3340 * @throws XMLSignatureException |
|
3341 * @throws InvalidTransformException |
|
3342 * @throws XMLSecurityException |
|
3343 * @throws TransformationException |
|
3344 */ |
|
3345 public TransformsImpl(Element element) |
|
3346 throws XMLSignatureException, InvalidTransformException, |
|
3347 XMLSecurityException, TransformationException { |
|
3348 super(element, ""); |
|
3349 } |
|
3350 |
|
3351 /** |
|
3352 * |
|
3353 * @return the XML Element form of that Transforms |
|
3354 */ |
|
3355 public Element toElement() { |
|
3356 if (doc == null) { |
|
3357 doc = contextDocument; |
|
3358 } |
|
3359 |
|
3360 return getElement(); |
|
3361 } |
|
3362 |
|
3363 /** @inheritDoc */ |
|
3364 public com.sun.org.apache.xml.internal.security.transforms.Transforms getDSTransforms() { |
|
3365 return this; |
|
3366 } |
|
3367 |
|
3368 // Over-ride the namespace |
|
3369 /** @inheritDoc */ |
|
3370 public String getBaseNamespace() { |
|
3371 return EncryptionConstants.EncryptionSpecNS; |
|
3372 } |
|
3373 } |
|
3374 |
|
3375 private class ReferenceListImpl implements ReferenceList { |
|
3376 private Class<?> sentry; |
|
3377 private List<Reference> references; |
|
3378 |
|
3379 /** |
|
3380 * Constructor. |
|
3381 * @param type |
|
3382 */ |
|
3383 public ReferenceListImpl(int type) { |
|
3384 if (type == ReferenceList.DATA_REFERENCE) { |
|
3385 sentry = DataReference.class; |
|
3386 } else if (type == ReferenceList.KEY_REFERENCE) { |
|
3387 sentry = KeyReference.class; |
|
3388 } else { |
|
3389 throw new IllegalArgumentException(); |
|
3390 } |
|
3391 references = new LinkedList<Reference>(); |
|
3392 } |
|
3393 |
|
3394 /** @inheritDoc */ |
|
3395 public void add(Reference reference) { |
|
3396 if (!reference.getClass().equals(sentry)) { |
|
3397 throw new IllegalArgumentException(); |
|
3398 } |
|
3399 references.add(reference); |
|
3400 } |
|
3401 |
|
3402 /** @inheritDoc */ |
|
3403 public void remove(Reference reference) { |
|
3404 if (!reference.getClass().equals(sentry)) { |
|
3405 throw new IllegalArgumentException(); |
|
3406 } |
|
3407 references.remove(reference); |
|
3408 } |
|
3409 |
|
3410 /** @inheritDoc */ |
|
3411 public int size() { |
|
3412 return references.size(); |
|
3413 } |
|
3414 |
|
3415 /** @inheritDoc */ |
|
3416 public boolean isEmpty() { |
|
3417 return references.isEmpty(); |
|
3418 } |
|
3419 |
|
3420 /** @inheritDoc */ |
|
3421 public Iterator<Reference> getReferences() { |
|
3422 return references.iterator(); |
|
3423 } |
|
3424 |
|
3425 Element toElement() { |
|
3426 Element result = |
|
3427 ElementProxy.createElementForFamily( |
|
3428 contextDocument, |
|
3429 EncryptionConstants.EncryptionSpecNS, |
|
3430 EncryptionConstants._TAG_REFERENCELIST |
|
3431 ); |
|
3432 Iterator<Reference> eachReference = references.iterator(); |
|
3433 while (eachReference.hasNext()) { |
|
3434 Reference reference = eachReference.next(); |
|
3435 result.appendChild(((ReferenceImpl) reference).toElement()); |
|
3436 } |
|
3437 return result; |
|
3438 } |
|
3439 |
|
3440 /** @inheritDoc */ |
|
3441 public Reference newDataReference(String uri) { |
|
3442 return new DataReference(uri); |
|
3443 } |
|
3444 |
|
3445 /** @inheritDoc */ |
|
3446 public Reference newKeyReference(String uri) { |
|
3447 return new KeyReference(uri); |
|
3448 } |
|
3449 |
|
3450 /** |
|
3451 * <code>ReferenceImpl</code> is an implementation of |
|
3452 * <code>Reference</code>. |
|
3453 * |
|
3454 * @see Reference |
|
3455 */ |
|
3456 private abstract class ReferenceImpl implements Reference { |
|
3457 private String uri; |
|
3458 private List<Element> referenceInformation; |
|
3459 |
|
3460 ReferenceImpl(String uri) { |
|
3461 this.uri = uri; |
|
3462 referenceInformation = new LinkedList<Element>(); |
|
3463 } |
|
3464 |
|
3465 /** @inheritDoc */ |
|
3466 public abstract String getType(); |
|
3467 |
|
3468 /** @inheritDoc */ |
|
3469 public String getURI() { |
|
3470 return uri; |
|
3471 } |
|
3472 |
|
3473 /** @inheritDoc */ |
|
3474 public Iterator<Element> getElementRetrievalInformation() { |
|
3475 return referenceInformation.iterator(); |
|
3476 } |
|
3477 |
|
3478 /** @inheritDoc */ |
|
3479 public void setURI(String uri) { |
|
3480 this.uri = uri; |
|
3481 } |
|
3482 |
|
3483 /** @inheritDoc */ |
|
3484 public void removeElementRetrievalInformation(Element node) { |
|
3485 referenceInformation.remove(node); |
|
3486 } |
|
3487 |
|
3488 /** @inheritDoc */ |
|
3489 public void addElementRetrievalInformation(Element node) { |
|
3490 referenceInformation.add(node); |
|
3491 } |
|
3492 |
|
3493 /** |
|
3494 * @return the XML Element form of that Reference |
|
3495 */ |
|
3496 public Element toElement() { |
|
3497 String tagName = getType(); |
|
3498 Element result = |
|
3499 ElementProxy.createElementForFamily( |
|
3500 contextDocument, |
|
3501 EncryptionConstants.EncryptionSpecNS, |
|
3502 tagName |
|
3503 ); |
|
3504 result.setAttribute(EncryptionConstants._ATT_URI, uri); |
|
3505 |
|
3506 // TODO: Need to martial referenceInformation |
|
3507 // Figure out how to make this work.. |
|
3508 // <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> |
|
3509 |
|
3510 return result; |
|
3511 } |
|
3512 } |
|
3513 |
|
3514 private class DataReference extends ReferenceImpl { |
|
3515 |
|
3516 DataReference(String uri) { |
|
3517 super(uri); |
|
3518 } |
|
3519 |
|
3520 /** @inheritDoc */ |
|
3521 public String getType() { |
|
3522 return EncryptionConstants._TAG_DATAREFERENCE; |
|
3523 } |
|
3524 } |
|
3525 |
|
3526 private class KeyReference extends ReferenceImpl { |
|
3527 |
|
3528 KeyReference(String uri) { |
|
3529 super(uri); |
|
3530 } |
|
3531 |
|
3532 /** @inheritDoc */ |
|
3533 public String getType() { |
|
3534 return EncryptionConstants._TAG_KEYREFERENCE; |
|
3535 } |
|
3536 } |
|
3537 } |
|
3538 } |
|
3539 } |
|