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