1 /* Cipher.java -- Interface to a cryptographic cipher. 2 Copyright (C) 2004, 2006 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package javax.crypto; 40 41 import gnu.java.security.Engine; 42 43 import java.nio.ByteBuffer; 44 import java.nio.ReadOnlyBufferException; 45 46 import java.security.AlgorithmParameters; 47 import java.security.InvalidAlgorithmParameterException; 48 import java.security.InvalidKeyException; 49 import java.security.Key; 50 import java.security.NoSuchAlgorithmException; 51 import java.security.NoSuchProviderException; 52 import java.security.Provider; 53 import java.security.SecureRandom; 54 import java.security.Security; 55 import java.security.cert.Certificate; 56 import java.security.cert.X509Certificate; 57 import java.security.spec.AlgorithmParameterSpec; 58 import java.util.StringTokenizer; 59 60 /** 61 * <p>This class implements a cryptographic cipher for transforming 62 * data.</p> 63 * 64 * <p>Ciphers cannot be instantiated directly; rather one of the 65 * <code>getInstance</code> must be used to instantiate a given 66 * <i>transformation</i>, optionally with a specific provider.</p> 67 * 68 * <p>A transformation is of the form:</p> 69 * 70 * <ul> 71 * <li><i>algorithm</i>/<i>mode</i>/<i>padding</i>, or</li> 72 * <li><i>algorithm</i> 73 * </ul> 74 * 75 * <p>where <i>algorithm</i> is the base name of a cryptographic cipher 76 * (such as "AES"), <i>mode</i> is the abbreviated name of a block 77 * cipher mode (such as "CBC" for cipher block chaining mode), and 78 * <i>padding</i> is the name of a padding scheme (such as 79 * "PKCS5Padding"). If only the algorithm name is supplied, then the 80 * provider-specific default mode and padding will be used.</p> 81 * 82 * <p>An example transformation is:</p> 83 * 84 * <blockquote><code>Cipher c = 85 * Cipher.getInstance("AES/CBC/PKCS5Padding");</code></blockquote> 86 * 87 * <p>Finally, when requesting a block cipher in stream cipher mode 88 * (such as <acronym title="Advanced Encryption Standard">AES</acronym> 89 * in OFB or CFB mode) the number of bits to be processed 90 * at a time may be specified by appending it to the name of the mode; 91 * e.g. <code>"AES/OFB8/NoPadding"</code>. If no such number is 92 * specified a provider-specific default value is used.</p> 93 * 94 * @author Casey Marshall (csm@gnu.org) 95 * @see java.security.KeyGenerator 96 * @see javax.crypto.SecretKey 97 */ 98 public class Cipher 99 { 100 101 // Constants and variables. 102 // ------------------------------------------------------------------------ 103 104 private static final String SERVICE = "Cipher"; 105 106 /** 107 * The decryption operation mode. 108 */ 109 public static final int DECRYPT_MODE = 2; 110 111 /** 112 * The encryption operation mode. 113 */ 114 public static final int ENCRYPT_MODE = 1; 115 116 /** 117 * Constant for when the key to be unwrapped is a private key. 118 */ 119 public static final int PRIVATE_KEY = 2; 120 121 /** 122 * Constant for when the key to be unwrapped is a public key. 123 */ 124 public static final int PUBLIC_KEY = 1; 125 126 /** 127 * Constant for when the key to be unwrapped is a secret key. 128 */ 129 public static final int SECRET_KEY = 3; 130 131 /** 132 * The key unwrapping operation mode. 133 */ 134 public static final int UNWRAP_MODE = 4; 135 136 /** 137 * The key wrapping operation mode. 138 */ 139 public static final int WRAP_MODE = 3; 140 141 /** 142 * The uninitialized state. This state signals that any of the 143 * <code>init</code> methods have not been called, and therefore no 144 * transformations can be done. 145 */ 146 private static final int INITIAL_STATE = 0; 147 148 /** The underlying cipher service provider interface. */ 149 private CipherSpi cipherSpi; 150 151 /** The provider from which this instance came. */ 152 private Provider provider; 153 154 /** The transformation requested. */ 155 private String transformation; 156 157 /** Our current state (encrypting, wrapping, etc.) */ 158 private int state; 159 160 /** 161 * Creates a new cipher instance for the given transformation. 162 * <p> 163 * The installed providers are tried in order for an implementation, and the 164 * first appropriate instance is returned. If no installed provider can 165 * provide the implementation, an appropriate exception is thrown. 166 * 167 * @param transformation The transformation to create. 168 * @return An appropriate cipher for this transformation. 169 * @throws NoSuchAlgorithmException If no installed provider can supply the 170 * appropriate cipher or mode. 171 * @throws NoSuchPaddingException If no installed provider can supply the 172 * appropriate padding. 173 */ getInstance(String transformation)174 public static final Cipher getInstance(String transformation) 175 throws NoSuchAlgorithmException, NoSuchPaddingException 176 { 177 Provider[] p = Security.getProviders(); 178 NoSuchAlgorithmException lastException = null; 179 NoSuchPaddingException lastPaddingException = null; 180 for (int i = 0; i < p.length; i++) 181 try 182 { 183 return getInstance(transformation, p[i]); 184 } 185 catch (NoSuchAlgorithmException x) 186 { 187 lastException = x; 188 lastPaddingException = null; 189 } 190 catch (NoSuchPaddingException x) 191 { 192 lastPaddingException = x; 193 } 194 if (lastPaddingException != null) 195 throw lastPaddingException; 196 if (lastException != null) 197 throw lastException; 198 throw new NoSuchAlgorithmException(transformation); 199 } 200 201 /** 202 * Creates a new cipher instance for the given transformation and the named 203 * provider. 204 * 205 * @param transformation The transformation to create. 206 * @param provider The name of the provider to use. 207 * @return An appropriate cipher for this transformation. 208 * @throws NoSuchAlgorithmException If the provider cannot supply the 209 * appropriate cipher or mode. 210 * @throws NoSuchProviderException If the named provider is not installed. 211 * @throws NoSuchPaddingException If the provider cannot supply the 212 * appropriate padding. 213 * @throws IllegalArgumentException if either <code>transformation</code> or 214 * <code>provider</code> is <code>null</code>. 215 */ getInstance(String transformation, String provider)216 public static final Cipher getInstance(String transformation, String provider) 217 throws NoSuchAlgorithmException, NoSuchProviderException, 218 NoSuchPaddingException 219 { 220 if (provider == null) 221 throw new IllegalArgumentException("provider MUST NOT be null"); 222 Provider p = Security.getProvider(provider); 223 if (p == null) 224 throw new NoSuchProviderException(provider); 225 return getInstance(transformation, p); 226 } 227 228 /** 229 * Creates a new cipher instance for a given transformation from a given 230 * provider. 231 * 232 * @param transformation The transformation to create. 233 * @param provider The provider to use. 234 * @return An appropriate cipher for this transformation. 235 * @throws NoSuchAlgorithmException If the given provider cannot supply the 236 * appropriate cipher or mode. 237 * @throws NoSuchPaddingException If the given provider cannot supply the 238 * appropriate padding scheme. 239 */ getInstance(String transformation, Provider provider)240 public static final Cipher getInstance(String transformation, 241 Provider provider) 242 throws NoSuchAlgorithmException, NoSuchPaddingException 243 { 244 StringBuilder sb = new StringBuilder().append("Cipher transformation [") 245 .append(transformation).append("] from provider [") 246 .append(provider).append("] "); 247 Throwable cause; 248 Object spi; 249 CipherSpi result; 250 if (transformation.indexOf('/') < 0) 251 { 252 try 253 { 254 spi = Engine.getInstance(SERVICE, transformation, provider); 255 return new Cipher((CipherSpi) spi, provider, transformation); 256 } 257 catch (Exception e) 258 { 259 if (e instanceof NoSuchAlgorithmException) 260 throw (NoSuchAlgorithmException) e; 261 cause = e; 262 } 263 } 264 else 265 { 266 StringTokenizer tok = new StringTokenizer(transformation, "/"); 267 if (tok.countTokens() != 3) 268 throw new NoSuchAlgorithmException(sb.append("is malformed").toString()); 269 270 String alg = tok.nextToken(); 271 String mode = tok.nextToken(); 272 String pad = tok.nextToken(); 273 try 274 { 275 spi = Engine.getInstance(SERVICE, transformation, provider); 276 return new Cipher((CipherSpi) spi, provider, transformation); 277 } 278 catch (Exception e) 279 { 280 cause = e; 281 } 282 283 try 284 { 285 spi = Engine.getInstance(SERVICE, alg + '/' + mode, provider); 286 result = (CipherSpi) spi; 287 result.engineSetPadding(pad); 288 return new Cipher(result, provider, transformation); 289 } 290 catch (Exception e) 291 { 292 if (e instanceof NoSuchPaddingException) 293 throw (NoSuchPaddingException) e; 294 cause = e; 295 } 296 297 try 298 { 299 spi = Engine.getInstance(SERVICE, alg + "//" + pad, provider); 300 result = (CipherSpi) spi; 301 result.engineSetMode(mode); 302 return new Cipher(result, provider, transformation); 303 } 304 catch (Exception e) 305 { 306 cause = e; 307 } 308 309 try 310 { 311 spi = Engine.getInstance(SERVICE, alg, provider); 312 result = (CipherSpi) spi; 313 result.engineSetMode(mode); 314 result.engineSetPadding(pad); 315 return new Cipher(result, provider, transformation); 316 } 317 catch (Exception e) 318 { 319 if (e instanceof NoSuchPaddingException) 320 throw (NoSuchPaddingException) e; 321 cause = e; 322 } 323 } 324 sb.append("could not be created"); 325 NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString()); 326 x.initCause(cause); 327 throw x; 328 } 329 330 /** 331 * Create a cipher. 332 * 333 * @param cipherSpi The underlying implementation of the cipher. 334 * @param provider The provider of this cipher implementation. 335 * @param transformation The transformation this cipher performs. 336 */ 337 protected Cipher(CipherSpi cipherSpi, Provider provider, String transformation)338 Cipher(CipherSpi cipherSpi, Provider provider, String transformation) 339 { 340 this.cipherSpi = cipherSpi; 341 this.provider = provider; 342 this.transformation = transformation; 343 state = INITIAL_STATE; 344 } 345 346 /** 347 * Get the name that this cipher instance was created with; this is 348 * equivalent to the "transformation" argument given to any of the 349 * {@link #getInstance()} methods. 350 * 351 * @return The cipher name. 352 */ getAlgorithm()353 public final String getAlgorithm() 354 { 355 return transformation; 356 } 357 358 /** 359 * Return the size of blocks, in bytes, that this cipher processes. 360 * 361 * @return The block size. 362 */ getBlockSize()363 public final int getBlockSize() 364 { 365 if (cipherSpi != null) 366 { 367 return cipherSpi.engineGetBlockSize(); 368 } 369 return 1; 370 } 371 372 /** 373 * Return the currently-operating {@link ExemptionMechanism}. 374 * 375 * @return null, currently. 376 */ getExemptionMechanism()377 public final ExemptionMechanism getExemptionMechanism() 378 { 379 return null; 380 } 381 382 /** 383 * Return the <i>initialization vector</i> that this instance was 384 * initialized with. 385 * 386 * @return The IV. 387 */ getIV()388 public final byte[] getIV() 389 { 390 if (cipherSpi != null) 391 { 392 return cipherSpi.engineGetIV(); 393 } 394 return null; 395 } 396 397 /** 398 * Return the {@link java.security.AlgorithmParameters} that this 399 * instance was initialized with. 400 * 401 * @return The parameters. 402 */ getParameters()403 public final AlgorithmParameters getParameters() 404 { 405 if (cipherSpi != null) { 406 return cipherSpi.engineGetParameters(); 407 } 408 return null; 409 } 410 411 /** 412 * Return this cipher's provider. 413 * 414 * @return The provider. 415 */ getProvider()416 public final Provider getProvider() 417 { 418 return provider; 419 } 420 421 /** 422 * Finishes a multi-part transformation, and returns the final 423 * transformed bytes. 424 * 425 * @return The final transformed bytes. 426 * @throws java.lang.IllegalStateException If this instance has not 427 * been initialized, or if a <tt>doFinal</tt> call has already 428 * been made. 429 * @throws javax.crypto.IllegalBlockSizeException If this instance has 430 * no padding and the input is not a multiple of this cipher's 431 * block size. 432 * @throws javax.crypto.BadPaddingException If this instance is 433 * decrypting and the padding bytes do not match this 434 * instance's padding scheme. 435 */ doFinal()436 public final byte[] doFinal() 437 throws IllegalStateException, IllegalBlockSizeException, BadPaddingException 438 { 439 return doFinal(new byte[0], 0, 0); 440 } 441 442 /** 443 * Finishes a multi-part transformation or does an entire 444 * transformation on the input, and returns the transformed bytes. 445 * 446 * @param input The final input bytes. 447 * @return The final transformed bytes. 448 * @throws java.lang.IllegalStateException If this instance has not 449 * been initialized, or if a <tt>doFinal</tt> call has already 450 * been made. 451 * @throws javax.crypto.IllegalBlockSizeException If this instance has 452 * no padding and the input is not a multiple of this cipher's 453 * block size. 454 * @throws javax.crypto.BadPaddingException If this instance is 455 * decrypting and the padding bytes do not match this 456 * instance's padding scheme. 457 */ doFinal(byte[] input)458 public final byte[] doFinal(byte[] input) 459 throws IllegalStateException, IllegalBlockSizeException, BadPaddingException 460 { 461 return doFinal(input, 0, input.length); 462 } 463 464 /** 465 * Finishes a multi-part transformation or does an entire 466 * transformation on the input, and returns the transformed bytes. 467 * 468 * @param input The final input bytes. 469 * @param inputOffset The index in the input bytes to start. 470 * @param inputLength The number of bytes to read from the input. 471 * @return The final transformed bytes. 472 * @throws java.lang.IllegalStateException If this instance has not 473 * been initialized, or if a <tt>doFinal</tt> call has already 474 * been made. 475 * @throws javax.crypto.IllegalBlockSizeException If this instance has 476 * no padding and the input is not a multiple of this cipher's 477 * block size. 478 * @throws javax.crypto.BadPaddingException If this instance is 479 * decrypting and the padding bytes do not match this 480 * instance's padding scheme. 481 */ doFinal(byte[] input, int inputOffset, int inputLength)482 public final byte[] doFinal(byte[] input, int inputOffset, int inputLength) 483 throws IllegalStateException, IllegalBlockSizeException, BadPaddingException 484 { 485 if (cipherSpi == null) 486 { 487 byte[] b = new byte[inputLength]; 488 System.arraycopy(input, inputOffset, b, 0, inputLength); 489 return b; 490 } 491 if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 492 { 493 throw new IllegalStateException("neither encrypting nor decrypting"); 494 } 495 return cipherSpi.engineDoFinal(input, inputOffset, inputLength); 496 } 497 498 /** 499 * Finishes a multi-part transformation and stores the transformed 500 * bytes into the given array. 501 * 502 * @param output The destination for the transformed bytes. 503 * @param outputOffset The offset in <tt>output</tt> to start storing 504 * bytes. 505 * @return The number of bytes placed into the output array. 506 * @throws java.lang.IllegalStateException If this instance has not 507 * been initialized, or if a <tt>doFinal</tt> call has already 508 * been made. 509 * @throws javax.crypto.IllegalBlockSizeException If this instance has 510 * no padding and the input is not a multiple of this cipher's 511 * block size. 512 * @throws javax.crypto.BadPaddingException If this instance is 513 * decrypting and the padding bytes do not match this 514 * instance's padding scheme. 515 * @throws javax.crypto.ShortBufferException If the output array is 516 * not large enough to hold the transformed bytes. 517 */ doFinal(byte[] output, int outputOffset)518 public final int doFinal(byte[] output, int outputOffset) 519 throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, 520 ShortBufferException 521 { 522 if (cipherSpi == null) 523 { 524 return 0; 525 } 526 if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 527 { 528 throw new IllegalStateException("neither encrypting nor decrypting"); 529 } 530 return cipherSpi.engineDoFinal(new byte[0], 0, 0, output, outputOffset); 531 } 532 533 /** 534 * Finishes a multi-part transformation or transforms a portion of a 535 * byte array, and stores the result in the given byte array. 536 * 537 * @param input The input bytes. 538 * @param inputOffset The index in <tt>input</tt> to start. 539 * @param inputLength The number of bytes to transform. 540 * @param output The output buffer. 541 * @param outputOffset The index in <tt>output</tt> to start. 542 * @return The number of bytes placed into the output array. 543 * @throws java.lang.IllegalStateException If this instance has not 544 * been initialized, or if a <tt>doFinal</tt> call has already 545 * been made. 546 * @throws javax.crypto.IllegalBlockSizeException If this instance has 547 * no padding and the input is not a multiple of this cipher's 548 * block size. 549 * @throws javax.crypto.BadPaddingException If this instance is 550 * decrypting and the padding bytes do not match this 551 * instance's padding scheme. 552 * @throws javax.crypto.ShortBufferException If the output array is 553 * not large enough to hold the transformed bytes. 554 */ doFinal(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset)555 public final int doFinal(byte[] input, int inputOffset, int inputLength, 556 byte[] output, int outputOffset) 557 throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, 558 ShortBufferException 559 { 560 if (cipherSpi == null) 561 { 562 if (inputLength > output.length - outputOffset) 563 { 564 throw new ShortBufferException(); 565 } 566 System.arraycopy(input, inputOffset, output, outputOffset, inputLength); 567 return inputLength; 568 } 569 if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 570 { 571 throw new IllegalStateException("neither encrypting nor decrypting"); 572 } 573 return cipherSpi.engineDoFinal(input, inputOffset, inputLength, 574 output, outputOffset); 575 } 576 doFinal(byte[] input, int inputOffset, int inputLength, byte[] output)577 public final int doFinal(byte[] input, int inputOffset, int inputLength, 578 byte[] output) 579 throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, 580 ShortBufferException 581 { 582 return doFinal(input, inputOffset, inputLength, output, 0); 583 } 584 585 /** 586 * Finishes a multi-part transformation with, or completely 587 * transforms, a byte buffer, and stores the result into the output 588 * buffer. 589 * 590 * @param input The input buffer. 591 * @param output The output buffer. 592 * @return The number of bytes stored into the output buffer. 593 * @throws IllegalArgumentException If the input and output buffers 594 * are the same object. 595 * @throws IllegalStateException If this cipher was not initialized 596 * for encryption or decryption. 597 * @throws ReadOnlyBufferException If the output buffer is not 598 * writable. 599 * @throws IllegalBlockSizeException If this cipher requires a total 600 * input that is a multiple of its block size to complete this 601 * transformation. 602 * @throws ShortBufferException If the output buffer is not large 603 * enough to hold the transformed bytes. 604 * @throws BadPaddingException If the cipher is a block cipher with 605 * a padding scheme, and the decrypted bytes do not end with a 606 * valid padding. 607 * @since 1.5 608 */ doFinal(ByteBuffer input, ByteBuffer output)609 public final int doFinal (ByteBuffer input, ByteBuffer output) 610 throws ReadOnlyBufferException, ShortBufferException, 611 BadPaddingException, IllegalBlockSizeException 612 { 613 if (input == output) 614 throw new IllegalArgumentException 615 ("input and output buffers cannot be the same"); 616 if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 617 throw new IllegalStateException 618 ("not initialized for encrypting or decrypting"); 619 return cipherSpi.engineDoFinal (input, output); 620 } 621 622 /** 623 * Returns the size an output buffer needs to be if this cipher is 624 * updated with a number of bytes. 625 * 626 * @param inputLength The input length. 627 * @return The output length given this input length. 628 * @throws java.lang.IllegalStateException If this instance has not 629 * been initialized, or if a <tt>doFinal</tt> call has already 630 * been made. 631 */ getOutputSize(int inputLength)632 public final int getOutputSize(int inputLength) throws IllegalStateException 633 { 634 if (cipherSpi == null) 635 return inputLength; 636 return cipherSpi.engineGetOutputSize(inputLength); 637 } 638 639 /** 640 * <p>Initialize this cipher with the public key from the given 641 * certificate.</p> 642 * 643 * <p>The cipher will be initialized for encryption, decryption, key 644 * wrapping, or key unwrapping, depending upon whether the 645 * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 646 * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 647 * respectively.</p> 648 * 649 * <p>As per the Java 1.4 specification, if <code>cert</code> is an 650 * instance of an {@link java.security.cert.X509Certificate} and its 651 * <i>key usage</i> extension field is incompatible with 652 * <code>opmode</code> then an {@link 653 * java.security.InvalidKeyException} is thrown.</p> 654 * 655 * <p>If this cipher requires any random bytes (for example for an 656 * initilization vector) than the {@link java.security.SecureRandom} 657 * with the highest priority is used as the source of these bytes.</p> 658 * 659 * <p>A call to any of the <code>init</code> methods overrides the 660 * state of the instance, and is equivalent to creating a new instance 661 * and calling its <code>init</code> method.</p> 662 * 663 * @param opmode The operation mode to use. 664 * @param certificate The certificate. 665 * @throws java.security.InvalidKeyException If the underlying cipher 666 * instance rejects the certificate's public key, or if the 667 * public key cannot be used as described above. 668 */ init(int opmode, Certificate certificate)669 public final void init(int opmode, Certificate certificate) 670 throws InvalidKeyException 671 { 672 init(opmode, certificate, new SecureRandom()); 673 } 674 675 /** 676 * <p>Initialize this cipher with the supplied key.</p> 677 * 678 * <p>The cipher will be initialized for encryption, decryption, key 679 * wrapping, or key unwrapping, depending upon whether the 680 * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 681 * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 682 * respectively.</p> 683 * 684 * <p>If this cipher requires any random bytes (for example for an 685 * initilization vector) than the {@link java.security.SecureRandom} 686 * with the highest priority is used as the source of these bytes.</p> 687 * 688 * <p>A call to any of the <code>init</code> methods overrides the 689 * state of the instance, and is equivalent to creating a new instance 690 * and calling its <code>init</code> method.</p> 691 * 692 * @param opmode The operation mode to use. 693 * @param key The key. 694 * @throws java.security.InvalidKeyException If the underlying cipher 695 * instance rejects the given key. 696 */ init(int opmode, Key key)697 public final void init(int opmode, Key key) throws InvalidKeyException 698 { 699 if (cipherSpi != null) 700 { 701 cipherSpi.engineInit(opmode, key, new SecureRandom()); 702 } 703 state = opmode; 704 } 705 706 /** 707 * <p>Initialize this cipher with the public key from the given 708 * certificate and the specified source of randomness.</p> 709 * 710 * <p>The cipher will be initialized for encryption, decryption, key 711 * wrapping, or key unwrapping, depending upon whether the 712 * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 713 * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 714 * respectively.</p> 715 * 716 * <p>As per the Java 1.4 specification, if <code>cert</code> is an 717 * instance of an {@link java.security.cert.X509Certificate} and its 718 * <i>key usage</i> extension field is incompatible with 719 * <code>opmode</code> then an {@link 720 * java.security.InvalidKeyException} is thrown.</p> 721 * 722 * <p>If this cipher requires any random bytes (for example for an 723 * initilization vector) than the {@link java.security.SecureRandom} 724 * with the highest priority is used as the source of these bytes.</p> 725 * 726 * <p>A call to any of the <code>init</code> methods overrides the 727 * state of the instance, and is equivalent to creating a new instance 728 * and calling its <code>init</code> method.</p> 729 * 730 * @param opmode The operation mode to use. 731 * @param certificate The certificate. 732 * @param random The source of randomness. 733 * @throws java.security.InvalidKeyException If the underlying cipher 734 * instance rejects the certificate's public key, or if the 735 * public key cannot be used as described above. 736 */ 737 public final void init(int opmode, Certificate certificate, SecureRandom random)738 init(int opmode, Certificate certificate, SecureRandom random) 739 throws InvalidKeyException 740 { 741 if (certificate instanceof X509Certificate) 742 { 743 boolean[] keyInfo = ((X509Certificate) certificate).getKeyUsage(); 744 if (keyInfo != null) 745 { 746 switch (opmode) 747 { 748 case DECRYPT_MODE: 749 if (!keyInfo[3]) 750 { 751 throw new InvalidKeyException( 752 "the certificate's key cannot be used for transforming data"); 753 } 754 if (keyInfo[7]) 755 { 756 throw new InvalidKeyException( 757 "the certificate's key can only be used for encryption"); 758 } 759 break; 760 761 case ENCRYPT_MODE: 762 if (!keyInfo[3]) 763 { 764 throw new InvalidKeyException( 765 "the certificate's key cannot be used for transforming data"); 766 } 767 if (keyInfo[8]) 768 { 769 throw new InvalidKeyException( 770 "the certificate's key can only be used for decryption"); 771 } 772 break; 773 774 case UNWRAP_MODE: 775 if (!keyInfo[2] || keyInfo[7]) 776 { 777 throw new InvalidKeyException( 778 "the certificate's key cannot be used for key unwrapping"); 779 } 780 break; 781 782 case WRAP_MODE: 783 if (!keyInfo[2] || keyInfo[8]) 784 { 785 throw new InvalidKeyException( 786 "the certificate's key cannot be used for key wrapping"); 787 } 788 break; 789 } 790 } 791 } 792 init(opmode, certificate.getPublicKey(), random); 793 } 794 795 /** 796 * <p>Initialize this cipher with the supplied key and source of 797 * randomness.</p> 798 * 799 * <p>The cipher will be initialized for encryption, decryption, key 800 * wrapping, or key unwrapping, depending upon whether the 801 * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 802 * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 803 * respectively.</p> 804 * 805 * <p>A call to any of the <code>init</code> methods overrides the 806 * state of the instance, and is equivalent to creating a new instance 807 * and calling its <code>init</code> method.</p> 808 * 809 * @param opmode The operation mode to use. 810 * @param key The key. 811 * @param random The source of randomness to use. 812 * @throws java.security.InvalidKeyException If the underlying cipher 813 * instance rejects the given key. 814 */ init(int opmode, Key key, SecureRandom random)815 public final void init(int opmode, Key key, SecureRandom random) 816 throws InvalidKeyException 817 { 818 if (cipherSpi != null) 819 { 820 cipherSpi.engineInit(opmode, key, random); 821 } 822 state = opmode; 823 } 824 825 /** 826 * <p>Initialize this cipher with the supplied key and parameters.</p> 827 * 828 * <p>The cipher will be initialized for encryption, decryption, key 829 * wrapping, or key unwrapping, depending upon whether the 830 * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 831 * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 832 * respectively.</p> 833 * 834 * <p>If this cipher requires any random bytes (for example for an 835 * initilization vector) then the {@link java.security.SecureRandom} 836 * with the highest priority is used as the source of these bytes.</p> 837 * 838 * <p>A call to any of the <code>init</code> methods overrides the 839 * state of the instance, and is equivalent to creating a new instance 840 * and calling its <code>init</code> method.</p> 841 * 842 * @param opmode The operation mode to use. 843 * @param key The key. 844 * @param params The algorithm parameters to initialize this instance 845 * with. 846 * @throws java.security.InvalidKeyException If the underlying cipher 847 * instance rejects the given key. 848 * @throws java.security.InvalidAlgorithmParameterException If the 849 * supplied parameters are inappropriate for this cipher. 850 */ init(int opmode, Key key, AlgorithmParameters params)851 public final void init(int opmode, Key key, AlgorithmParameters params) 852 throws InvalidKeyException, InvalidAlgorithmParameterException 853 { 854 init(opmode, key, params, new SecureRandom()); 855 } 856 857 /** 858 * <p>Initialize this cipher with the supplied key and parameters.</p> 859 * 860 * <p>The cipher will be initialized for encryption, decryption, key 861 * wrapping, or key unwrapping, depending upon whether the 862 * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 863 * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 864 * respectively.</p> 865 * 866 * <p>If this cipher requires any random bytes (for example for an 867 * initilization vector) then the {@link java.security.SecureRandom} 868 * with the highest priority is used as the source of these bytes.</p> 869 * 870 * <p>A call to any of the <code>init</code> methods overrides the 871 * state of the instance, and is equivalent to creating a new instance 872 * and calling its <code>init</code> method.</p> 873 * 874 * @param opmode The operation mode to use. 875 * @param key The key. 876 * @param params The algorithm parameters to initialize this instance 877 * with. 878 * @throws java.security.InvalidKeyException If the underlying cipher 879 * instance rejects the given key. 880 * @throws java.security.InvalidAlgorithmParameterException If the 881 * supplied parameters are inappropriate for this cipher. 882 */ init(int opmode, Key key, AlgorithmParameterSpec params)883 public final void init(int opmode, Key key, AlgorithmParameterSpec params) 884 throws InvalidKeyException, InvalidAlgorithmParameterException 885 { 886 init(opmode, key, params, new SecureRandom()); 887 } 888 889 /** 890 * <p>Initialize this cipher with the supplied key, parameters, and 891 * source of randomness.</p> 892 * 893 * <p>The cipher will be initialized for encryption, decryption, key 894 * wrapping, or key unwrapping, depending upon whether the 895 * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 896 * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 897 * respectively.</p> 898 * 899 * <p>A call to any of the <code>init</code> methods overrides the 900 * state of the instance, and is equivalent to creating a new instance 901 * and calling its <code>init</code> method.</p> 902 * 903 * @param opmode The operation mode to use. 904 * @param key The key. 905 * @param params The algorithm parameters to initialize this instance 906 * with. 907 * @param random The source of randomness to use. 908 * @throws java.security.InvalidKeyException If the underlying cipher 909 * instance rejects the given key. 910 * @throws java.security.InvalidAlgorithmParameterException If the 911 * supplied parameters are inappropriate for this cipher. 912 */ init(int opmode, Key key, AlgorithmParameters params, SecureRandom random)913 public final void init(int opmode, Key key, AlgorithmParameters params, 914 SecureRandom random) 915 throws InvalidKeyException, InvalidAlgorithmParameterException 916 { 917 if (cipherSpi != null) 918 { 919 cipherSpi.engineInit(opmode, key, params, random); 920 } 921 state = opmode; 922 } 923 924 /** 925 * <p>Initialize this cipher with the supplied key, parameters, and 926 * source of randomness.</p> 927 * 928 * <p>The cipher will be initialized for encryption, decryption, key 929 * wrapping, or key unwrapping, depending upon whether the 930 * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 931 * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 932 * respectively.</p> 933 * 934 * <p>A call to any of the <code>init</code> methods overrides the 935 * state of the instance, and is equivalent to creating a new instance 936 * and calling its <code>init</code> method.</p> 937 * 938 * @param opmode The operation mode to use. 939 * @param key The key. 940 * @param params The algorithm parameters to initialize this instance 941 * with. 942 * @param random The source of randomness to use. 943 * @throws java.security.InvalidKeyException If the underlying cipher 944 * instance rejects the given key. 945 * @throws java.security.InvalidAlgorithmParameterException If the 946 * supplied parameters are inappropriate for this cipher. 947 */ init(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random)948 public final void init(int opmode, Key key, AlgorithmParameterSpec params, 949 SecureRandom random) 950 throws InvalidKeyException, InvalidAlgorithmParameterException 951 { 952 if (cipherSpi != null) 953 { 954 cipherSpi.engineInit(opmode, key, params, random); 955 } 956 state = opmode; 957 } 958 959 /** 960 * Unwrap a previously-wrapped key. 961 * 962 * @param wrappedKey The wrapped key. 963 * @param wrappedKeyAlgorithm The algorithm with which the key was 964 * wrapped. 965 * @param wrappedKeyType The type of key (public, private, or 966 * secret) that this wrapped key respresents. 967 * @return The unwrapped key. 968 * @throws java.lang.IllegalStateException If this instance has not be 969 * initialized for unwrapping. 970 * @throws java.security.InvalidKeyException If <code>wrappedKey</code> 971 * is not a wrapped key, if the algorithm cannot unwrap this 972 * key, or if the unwrapped key's type differs from the 973 * specified type. 974 * @throws java.security.NoSuchAlgorithmException If 975 * <code>wrappedKeyAlgorithm</code> is not a valid algorithm 976 * name. 977 */ unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType)978 public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, 979 int wrappedKeyType) 980 throws IllegalStateException, InvalidKeyException, NoSuchAlgorithmException 981 { 982 if (cipherSpi == null) 983 { 984 return null; 985 } 986 if (state != UNWRAP_MODE) 987 { 988 throw new IllegalStateException("instance is not for unwrapping"); 989 } 990 return cipherSpi.engineUnwrap(wrappedKey, wrappedKeyAlgorithm, 991 wrappedKeyType); 992 } 993 994 /** 995 * Continue a multi-part transformation on an entire byte array, 996 * returning the transformed bytes. 997 * 998 * @param input The input bytes. 999 * @return The transformed bytes. 1000 * @throws java.lang.IllegalStateException If this cipher was not 1001 * initialized for encryption or decryption. 1002 */ update(byte[] input)1003 public final byte[] update(byte[] input) throws IllegalStateException 1004 { 1005 return update(input, 0, input.length); 1006 } 1007 1008 /** 1009 * Continue a multi-part transformation on part of a byte array, 1010 * returning the transformed bytes. 1011 * 1012 * @param input The input bytes. 1013 * @param inputOffset The index in the input to start. 1014 * @param inputLength The number of bytes to transform. 1015 * @return The transformed bytes. 1016 * @throws java.lang.IllegalStateException If this cipher was not 1017 * initialized for encryption or decryption. 1018 */ update(byte[] input, int inputOffset, int inputLength)1019 public final byte[] update(byte[] input, int inputOffset, int inputLength) 1020 throws IllegalStateException 1021 { 1022 if (cipherSpi == null) 1023 { 1024 byte[] b = new byte[inputLength]; 1025 System.arraycopy(input, inputOffset, b, 0, inputLength); 1026 return b; 1027 } 1028 if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 1029 { 1030 throw new IllegalStateException( 1031 "cipher is not for encrypting or decrypting"); 1032 } 1033 return cipherSpi.engineUpdate(input, inputOffset, inputLength); 1034 } 1035 1036 /** 1037 * Continue a multi-part transformation on part of a byte array, 1038 * placing the transformed bytes into the given array. 1039 * 1040 * @param input The input bytes. 1041 * @param inputOffset The index in the input to start. 1042 * @param inputLength The number of bytes to transform. 1043 * @param output The output byte array. 1044 * @return The number of transformed bytes. 1045 * @throws java.lang.IllegalStateException If this cipher was not 1046 * initialized for encryption or decryption. 1047 * @throws javax.security.ShortBufferException If there is not enough 1048 * room in the output array to hold the transformed bytes. 1049 */ update(byte[] input, int inputOffset, int inputLength, byte[] output)1050 public final int update(byte[] input, int inputOffset, int inputLength, 1051 byte[] output) 1052 throws IllegalStateException, ShortBufferException 1053 { 1054 return update(input, inputOffset, inputLength, output, 0); 1055 } 1056 1057 /** 1058 * Continue a multi-part transformation on part of a byte array, 1059 * placing the transformed bytes into the given array. 1060 * 1061 * @param input The input bytes. 1062 * @param inputOffset The index in the input to start. 1063 * @param inputLength The number of bytes to transform. 1064 * @param output The output byte array. 1065 * @param outputOffset The index in the output array to start. 1066 * @return The number of transformed bytes. 1067 * @throws java.lang.IllegalStateException If this cipher was not 1068 * initialized for encryption or decryption. 1069 * @throws javax.security.ShortBufferException If there is not enough 1070 * room in the output array to hold the transformed bytes. 1071 */ update(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset)1072 public final int update(byte[] input, int inputOffset, int inputLength, 1073 byte[] output, int outputOffset) 1074 throws IllegalStateException, ShortBufferException 1075 { 1076 if (cipherSpi == null) 1077 { 1078 if (inputLength > output.length - outputOffset) 1079 { 1080 throw new ShortBufferException(); 1081 } 1082 System.arraycopy(input, inputOffset, output, outputOffset, inputLength); 1083 return inputLength; 1084 } 1085 if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 1086 { 1087 throw new IllegalStateException( 1088 "cipher is not for encrypting or decrypting"); 1089 } 1090 return cipherSpi.engineUpdate(input, inputOffset, inputLength, 1091 output, outputOffset); 1092 } 1093 1094 /** 1095 * Continue a multi-part transformation on a byte buffer, storing 1096 * the transformed bytes into another buffer. 1097 * 1098 * @param input The input buffer. 1099 * @param output The output buffer. 1100 * @return The number of bytes stored in <i>output</i>. 1101 * @throws IllegalArgumentException If the two buffers are the same 1102 * object. 1103 * @throws IllegalStateException If this cipher was not initialized 1104 * for encrypting or decrypting. 1105 * @throws ReadOnlyBufferException If the output buffer is not 1106 * writable. 1107 * @throws ShortBufferException If the output buffer does not have 1108 * enough available space for the transformed bytes. 1109 * @since 1.5 1110 */ update(ByteBuffer input, ByteBuffer output)1111 public final int update (ByteBuffer input, ByteBuffer output) 1112 throws ReadOnlyBufferException, ShortBufferException 1113 { 1114 if (input == output) 1115 throw new IllegalArgumentException 1116 ("input and output buffers must be different"); 1117 if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 1118 throw new IllegalStateException 1119 ("not initialized for encryption or decryption"); 1120 return cipherSpi.engineUpdate (input, output); 1121 } 1122 1123 /** 1124 * Wrap a key. 1125 * 1126 * @param key The key to wrap. 1127 * @return The wrapped key. 1128 * @throws java.lang.IllegalStateException If this instance was not 1129 * initialized for key wrapping. 1130 * @throws javax.crypto.IllegalBlockSizeException If this instance has 1131 * no padding and the key is not a multiple of the block size. 1132 * @throws java.security.InvalidKeyException If this instance cannot 1133 * wrap this key. 1134 */ wrap(Key key)1135 public final byte[] wrap(Key key) 1136 throws IllegalStateException, IllegalBlockSizeException, InvalidKeyException 1137 { 1138 if (cipherSpi == null) 1139 { 1140 return null; 1141 } 1142 if (state != WRAP_MODE) 1143 { 1144 throw new IllegalStateException("instance is not for key wrapping"); 1145 } 1146 return cipherSpi.engineWrap(key); 1147 } 1148 } 1149