Frames | No Frames |
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: // Class methods. 162: // ------------------------------------------------------------------------ 163: 164: /** 165: * <p>Creates a new cipher instance for the given transformation.</p> 166: * 167: * <p>The installed providers are tried in order for an 168: * implementation, and the first appropriate instance is returned. If 169: * no installed provider can provide the implementation, an 170: * appropriate exception is thrown.</p> 171: * 172: * @param transformation The transformation to create. 173: * @return An appropriate cipher for this transformation. 174: * @throws java.security.NoSuchAlgorithmException If no installed 175: * provider can supply the appropriate cipher or mode. 176: * @throws javax.crypto.NoSuchPaddingException If no installed 177: * provider can supply the appropriate padding. 178: */ 179: public static final Cipher getInstance(String transformation) 180: throws NoSuchAlgorithmException, NoSuchPaddingException 181: { 182: Provider[] providers = Security.getProviders(); 183: NoSuchPaddingException ex = null; 184: String msg = ""; 185: for (int i = 0; i < providers.length; i++) 186: { 187: try 188: { 189: return getInstance(transformation, providers[i]); 190: } 191: catch (NoSuchAlgorithmException nsae) 192: { 193: msg = nsae.getMessage(); 194: ex = null; 195: } 196: catch (NoSuchPaddingException nspe) 197: { 198: ex = nspe; 199: } 200: } 201: if (ex != null) 202: { 203: throw ex; 204: } 205: throw new NoSuchAlgorithmException(msg); 206: } 207: 208: /** 209: * <p>Creates a new cipher instance for the given transformation and 210: * the named provider.</p> 211: * 212: * @param transformation The transformation to create. 213: * @param provider The name of the provider to use. 214: * @return An appropriate cipher for this transformation. 215: * @throws java.security.NoSuchAlgorithmException If the provider cannot 216: * supply the appropriate cipher or mode. 217: * @throws java.security.NoSuchProviderException If the named provider 218: * is not installed. 219: * @throws javax.crypto.NoSuchPaddingException If the provider cannot 220: * supply the appropriate padding. 221: */ 222: public static final Cipher getInstance(String transformation, String provider) 223: throws NoSuchAlgorithmException, NoSuchProviderException, 224: NoSuchPaddingException 225: { 226: Provider p = Security.getProvider(provider); 227: if (p == null) 228: { 229: throw new NoSuchProviderException(provider); 230: } 231: return getInstance(transformation, p); 232: } 233: 234: /** 235: * Creates a new cipher instance for the given transform and the given 236: * provider. 237: * 238: * @param transformation The transformation to create. 239: * @param provider The provider to use. 240: * @return An appropriate cipher for this transformation. 241: * @throws java.security.NoSuchAlgorithmException If the given 242: * provider cannot supply the appropriate cipher or mode. 243: * @throws javax.crypto.NoSuchPaddingException If the given 244: * provider cannot supply the appropriate padding scheme. 245: */ 246: public static final Cipher getInstance(String transformation, Provider provider) 247: throws NoSuchAlgorithmException, NoSuchPaddingException 248: { 249: CipherSpi result = null; 250: String key = null; 251: String alg = null, mode = null, pad = null; 252: String msg = ""; 253: if (transformation.indexOf('/') < 0) 254: { 255: try 256: { 257: result = (CipherSpi) Engine.getInstance(SERVICE, transformation, 258: provider); 259: return new Cipher(result, provider, transformation); 260: } 261: catch (Exception e) 262: { 263: msg = e.getMessage(); 264: } 265: } 266: else 267: { 268: StringTokenizer tok = new StringTokenizer(transformation, "/"); 269: if (tok.countTokens() != 3) 270: { 271: throw new NoSuchAlgorithmException("badly formed transformation"); 272: } 273: alg = tok.nextToken(); 274: mode = tok.nextToken(); 275: pad = tok.nextToken(); 276: try 277: { 278: result = (CipherSpi) Engine.getInstance(SERVICE, transformation, 279: provider); 280: return new Cipher(result, provider, transformation); 281: } 282: catch (Exception e) 283: { 284: msg = e.getMessage(); 285: } 286: try 287: { 288: result = (CipherSpi) Engine.getInstance(SERVICE, alg + '/' + mode, 289: provider); 290: result.engineSetPadding(pad); 291: return new Cipher(result, provider, transformation); 292: } 293: catch (Exception e) 294: { 295: if (e instanceof NoSuchPaddingException) 296: { 297: throw (NoSuchPaddingException) e; 298: } 299: msg = e.getMessage(); 300: } 301: try 302: { 303: result = (CipherSpi) Engine.getInstance(SERVICE, alg + "//" + pad, 304: provider); 305: result.engineSetMode(mode); 306: return new Cipher(result, provider, transformation); 307: } 308: catch (Exception e) 309: { 310: msg = e.getMessage(); 311: } 312: try 313: { 314: result = (CipherSpi) Engine.getInstance(SERVICE, alg, provider); 315: result.engineSetMode(mode); 316: result.engineSetPadding(pad); 317: return new Cipher(result, provider, transformation); 318: } 319: catch (Exception e) 320: { 321: if (e instanceof NoSuchPaddingException) 322: { 323: throw (NoSuchPaddingException) e; 324: } 325: msg = e.getMessage(); 326: } 327: } 328: throw new NoSuchAlgorithmException(transformation + ": " + msg); 329: } 330: 331: // Constructor. 332: // ------------------------------------------------------------------------ 333: 334: /** 335: * Create a cipher. 336: * 337: * @param cipherSpi The underlying implementation of the cipher. 338: * @param provider The provider of this cipher implementation. 339: * @param transformation The transformation this cipher performs. 340: */ 341: protected 342: Cipher(CipherSpi cipherSpi, Provider provider, String transformation) 343: { 344: this.cipherSpi = cipherSpi; 345: this.provider = provider; 346: this.transformation = transformation; 347: state = INITIAL_STATE; 348: } 349: 350: // Public instance methods. 351: // ------------------------------------------------------------------------ 352: 353: /** 354: * Get the name that this cipher instance was created with; this is 355: * equivalent to the "transformation" argument given to any of the 356: * {@link #getInstance()} methods. 357: * 358: * @return The cipher name. 359: */ 360: public final String getAlgorithm() 361: { 362: return transformation; 363: } 364: 365: /** 366: * Return the size of blocks, in bytes, that this cipher processes. 367: * 368: * @return The block size. 369: */ 370: public final int getBlockSize() 371: { 372: if (cipherSpi != null) 373: { 374: return cipherSpi.engineGetBlockSize(); 375: } 376: return 1; 377: } 378: 379: /** 380: * Return the currently-operating {@link ExemptionMechanism}. 381: * 382: * @return null, currently. 383: */ 384: public final ExemptionMechanism getExemptionMechanism() 385: { 386: return null; 387: } 388: 389: /** 390: * Return the <i>initialization vector</i> that this instance was 391: * initialized with. 392: * 393: * @return The IV. 394: */ 395: public final byte[] getIV() 396: { 397: if (cipherSpi != null) 398: { 399: return cipherSpi.engineGetIV(); 400: } 401: return null; 402: } 403: 404: /** 405: * Return the {@link java.security.AlgorithmParameters} that this 406: * instance was initialized with. 407: * 408: * @return The parameters. 409: */ 410: public final AlgorithmParameters getParameters() 411: { 412: if (cipherSpi != null) { 413: return cipherSpi.engineGetParameters(); 414: } 415: return null; 416: } 417: 418: /** 419: * Return this cipher's provider. 420: * 421: * @return The provider. 422: */ 423: public final Provider getProvider() 424: { 425: return provider; 426: } 427: 428: /** 429: * Finishes a multi-part transformation, and returns the final 430: * transformed bytes. 431: * 432: * @return The final transformed bytes. 433: * @throws java.lang.IllegalStateException If this instance has not 434: * been initialized, or if a <tt>doFinal</tt> call has already 435: * been made. 436: * @throws javax.crypto.IllegalBlockSizeException If this instance has 437: * no padding and the input is not a multiple of this cipher's 438: * block size. 439: * @throws javax.crypto.BadPaddingException If this instance is 440: * decrypting and the padding bytes do not match this 441: * instance's padding scheme. 442: */ 443: public final byte[] doFinal() 444: throws IllegalStateException, IllegalBlockSizeException, BadPaddingException 445: { 446: return doFinal(new byte[0], 0, 0); 447: } 448: 449: /** 450: * Finishes a multi-part transformation or does an entire 451: * transformation on the input, and returns the transformed bytes. 452: * 453: * @param input The final input bytes. 454: * @return The final transformed bytes. 455: * @throws java.lang.IllegalStateException If this instance has not 456: * been initialized, or if a <tt>doFinal</tt> call has already 457: * been made. 458: * @throws javax.crypto.IllegalBlockSizeException If this instance has 459: * no padding and the input is not a multiple of this cipher's 460: * block size. 461: * @throws javax.crypto.BadPaddingException If this instance is 462: * decrypting and the padding bytes do not match this 463: * instance's padding scheme. 464: */ 465: public final byte[] doFinal(byte[] input) 466: throws IllegalStateException, IllegalBlockSizeException, BadPaddingException 467: { 468: return doFinal(input, 0, input.length); 469: } 470: 471: /** 472: * Finishes a multi-part transformation or does an entire 473: * transformation on the input, and returns the transformed bytes. 474: * 475: * @param input The final input bytes. 476: * @param inputOffset The index in the input bytes to start. 477: * @param inputLength The number of bytes to read from the input. 478: * @return The final transformed bytes. 479: * @throws java.lang.IllegalStateException If this instance has not 480: * been initialized, or if a <tt>doFinal</tt> call has already 481: * been made. 482: * @throws javax.crypto.IllegalBlockSizeException If this instance has 483: * no padding and the input is not a multiple of this cipher's 484: * block size. 485: * @throws javax.crypto.BadPaddingException If this instance is 486: * decrypting and the padding bytes do not match this 487: * instance's padding scheme. 488: */ 489: public final byte[] doFinal(byte[] input, int inputOffset, int inputLength) 490: throws IllegalStateException, IllegalBlockSizeException, BadPaddingException 491: { 492: if (cipherSpi == null) 493: { 494: byte[] b = new byte[inputLength]; 495: System.arraycopy(input, inputOffset, b, 0, inputLength); 496: return b; 497: } 498: if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 499: { 500: throw new IllegalStateException("neither encrypting nor decrypting"); 501: } 502: return cipherSpi.engineDoFinal(input, inputOffset, inputLength); 503: } 504: 505: /** 506: * Finishes a multi-part transformation and stores the transformed 507: * bytes into the given array. 508: * 509: * @param output The destination for the transformed bytes. 510: * @param outputOffset The offset in <tt>output</tt> to start storing 511: * bytes. 512: * @return The number of bytes placed into the output array. 513: * @throws java.lang.IllegalStateException If this instance has not 514: * been initialized, or if a <tt>doFinal</tt> call has already 515: * been made. 516: * @throws javax.crypto.IllegalBlockSizeException If this instance has 517: * no padding and the input is not a multiple of this cipher's 518: * block size. 519: * @throws javax.crypto.BadPaddingException If this instance is 520: * decrypting and the padding bytes do not match this 521: * instance's padding scheme. 522: * @throws javax.crypto.ShortBufferException If the output array is 523: * not large enough to hold the transformed bytes. 524: */ 525: public final int doFinal(byte[] output, int outputOffset) 526: throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, 527: ShortBufferException 528: { 529: if (cipherSpi == null) 530: { 531: return 0; 532: } 533: if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 534: { 535: throw new IllegalStateException("neither encrypting nor decrypting"); 536: } 537: return cipherSpi.engineDoFinal(new byte[0], 0, 0, output, outputOffset); 538: } 539: 540: /** 541: * Finishes a multi-part transformation or transforms a portion of a 542: * byte array, and stores the result in the given byte array. 543: * 544: * @param input The input bytes. 545: * @param inputOffset The index in <tt>input</tt> to start. 546: * @param inputLength The number of bytes to transform. 547: * @param output The output buffer. 548: * @param outputOffset The index in <tt>output</tt> to start. 549: * @return The number of bytes placed into the output array. 550: * @throws java.lang.IllegalStateException If this instance has not 551: * been initialized, or if a <tt>doFinal</tt> call has already 552: * been made. 553: * @throws javax.crypto.IllegalBlockSizeException If this instance has 554: * no padding and the input is not a multiple of this cipher's 555: * block size. 556: * @throws javax.crypto.BadPaddingException If this instance is 557: * decrypting and the padding bytes do not match this 558: * instance's padding scheme. 559: * @throws javax.crypto.ShortBufferException If the output array is 560: * not large enough to hold the transformed bytes. 561: */ 562: public final int doFinal(byte[] input, int inputOffset, int inputLength, 563: byte[] output, int outputOffset) 564: throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, 565: ShortBufferException 566: { 567: if (cipherSpi == null) 568: { 569: if (inputLength > output.length - outputOffset) 570: { 571: throw new ShortBufferException(); 572: } 573: System.arraycopy(input, inputOffset, output, outputOffset, inputLength); 574: return inputLength; 575: } 576: if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 577: { 578: throw new IllegalStateException("neither encrypting nor decrypting"); 579: } 580: return cipherSpi.engineDoFinal(input, inputOffset, inputLength, 581: output, outputOffset); 582: } 583: 584: public final int doFinal(byte[] input, int inputOffset, int inputLength, 585: byte[] output) 586: throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, 587: ShortBufferException 588: { 589: return doFinal(input, inputOffset, inputLength, output, 0); 590: } 591: 592: /** 593: * Finishes a multi-part transformation with, or completely 594: * transforms, a byte buffer, and stores the result into the output 595: * buffer. 596: * 597: * @param input The input buffer. 598: * @param output The output buffer. 599: * @return The number of bytes stored into the output buffer. 600: * @throws IllegalArgumentException If the input and output buffers 601: * are the same object. 602: * @throws IllegalStateException If this cipher was not initialized 603: * for encryption or decryption. 604: * @throws ReadOnlyBufferException If the output buffer is not 605: * writable. 606: * @throws IllegalBlockSizeException If this cipher requires a total 607: * input that is a multiple of its block size to complete this 608: * transformation. 609: * @throws ShortBufferException If the output buffer is not large 610: * enough to hold the transformed bytes. 611: * @throws BadPaddingException If the cipher is a block cipher with 612: * a padding scheme, and the decrypted bytes do not end with a 613: * valid padding. 614: * @since 1.5 615: */ 616: public final int doFinal (ByteBuffer input, ByteBuffer output) 617: throws ReadOnlyBufferException, ShortBufferException, 618: BadPaddingException, IllegalBlockSizeException 619: { 620: if (input == output) 621: throw new IllegalArgumentException 622: ("input and output buffers cannot be the same"); 623: if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 624: throw new IllegalStateException 625: ("not initialized for encrypting or decrypting"); 626: return cipherSpi.engineDoFinal (input, output); 627: } 628: 629: /** 630: * Returns the size an output buffer needs to be if this cipher is 631: * updated with a number of bytes. 632: * 633: * @param inputLength The input length. 634: * @return The output length given this input length. 635: * @throws java.lang.IllegalStateException If this instance has not 636: * been initialized, or if a <tt>doFinal</tt> call has already 637: * been made. 638: */ 639: public final int getOutputSize(int inputLength) throws IllegalStateException 640: { 641: if (cipherSpi == null) 642: return inputLength; 643: return cipherSpi.engineGetOutputSize(inputLength); 644: } 645: 646: /** 647: * <p>Initialize this cipher with the public key from the given 648: * certificate.</p> 649: * 650: * <p>The cipher will be initialized for encryption, decryption, key 651: * wrapping, or key unwrapping, depending upon whether the 652: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 653: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 654: * respectively.</p> 655: * 656: * <p>As per the Java 1.4 specification, if <code>cert</code> is an 657: * instance of an {@link java.security.cert.X509Certificate} and its 658: * <i>key usage</i> extension field is incompatible with 659: * <code>opmode</code> then an {@link 660: * java.security.InvalidKeyException} is thrown.</p> 661: * 662: * <p>If this cipher requires any random bytes (for example for an 663: * initilization vector) than the {@link java.security.SecureRandom} 664: * with the highest priority is used as the source of these bytes.</p> 665: * 666: * <p>A call to any of the <code>init</code> methods overrides the 667: * state of the instance, and is equivalent to creating a new instance 668: * and calling its <code>init</code> method.</p> 669: * 670: * @param opmode The operation mode to use. 671: * @param certificate The certificate. 672: * @throws java.security.InvalidKeyException If the underlying cipher 673: * instance rejects the certificate's public key, or if the 674: * public key cannot be used as described above. 675: */ 676: public final void init(int opmode, Certificate certificate) 677: throws InvalidKeyException 678: { 679: init(opmode, certificate, new SecureRandom()); 680: } 681: 682: /** 683: * <p>Initialize this cipher with the supplied key.</p> 684: * 685: * <p>The cipher will be initialized for encryption, decryption, key 686: * wrapping, or key unwrapping, depending upon whether the 687: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 688: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 689: * respectively.</p> 690: * 691: * <p>If this cipher requires any random bytes (for example for an 692: * initilization vector) than the {@link java.security.SecureRandom} 693: * with the highest priority is used as the source of these bytes.</p> 694: * 695: * <p>A call to any of the <code>init</code> methods overrides the 696: * state of the instance, and is equivalent to creating a new instance 697: * and calling its <code>init</code> method.</p> 698: * 699: * @param opmode The operation mode to use. 700: * @param key The key. 701: * @throws java.security.InvalidKeyException If the underlying cipher 702: * instance rejects the given key. 703: */ 704: public final void init(int opmode, Key key) throws InvalidKeyException 705: { 706: if (cipherSpi != null) 707: { 708: cipherSpi.engineInit(opmode, key, new SecureRandom()); 709: } 710: state = opmode; 711: } 712: 713: /** 714: * <p>Initialize this cipher with the public key from the given 715: * certificate and the specified source of randomness.</p> 716: * 717: * <p>The cipher will be initialized for encryption, decryption, key 718: * wrapping, or key unwrapping, depending upon whether the 719: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 720: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 721: * respectively.</p> 722: * 723: * <p>As per the Java 1.4 specification, if <code>cert</code> is an 724: * instance of an {@link java.security.cert.X509Certificate} and its 725: * <i>key usage</i> extension field is incompatible with 726: * <code>opmode</code> then an {@link 727: * java.security.InvalidKeyException} is thrown.</p> 728: * 729: * <p>If this cipher requires any random bytes (for example for an 730: * initilization vector) than the {@link java.security.SecureRandom} 731: * with the highest priority is used as the source of these bytes.</p> 732: * 733: * <p>A call to any of the <code>init</code> methods overrides the 734: * state of the instance, and is equivalent to creating a new instance 735: * and calling its <code>init</code> method.</p> 736: * 737: * @param opmode The operation mode to use. 738: * @param certificate The certificate. 739: * @param random The source of randomness. 740: * @throws java.security.InvalidKeyException If the underlying cipher 741: * instance rejects the certificate's public key, or if the 742: * public key cannot be used as described above. 743: */ 744: public final void 745: init(int opmode, Certificate certificate, SecureRandom random) 746: throws InvalidKeyException 747: { 748: if (certificate instanceof X509Certificate) 749: { 750: boolean[] keyInfo = ((X509Certificate) certificate).getKeyUsage(); 751: if (keyInfo != null) 752: { 753: switch (opmode) 754: { 755: case DECRYPT_MODE: 756: if (!keyInfo[3]) 757: { 758: throw new InvalidKeyException( 759: "the certificate's key cannot be used for transforming data"); 760: } 761: if (keyInfo[7]) 762: { 763: throw new InvalidKeyException( 764: "the certificate's key can only be used for encryption"); 765: } 766: break; 767: 768: case ENCRYPT_MODE: 769: if (!keyInfo[3]) 770: { 771: throw new InvalidKeyException( 772: "the certificate's key cannot be used for transforming data"); 773: } 774: if (keyInfo[8]) 775: { 776: throw new InvalidKeyException( 777: "the certificate's key can only be used for decryption"); 778: } 779: break; 780: 781: case UNWRAP_MODE: 782: if (!keyInfo[2] || keyInfo[7]) 783: { 784: throw new InvalidKeyException( 785: "the certificate's key cannot be used for key unwrapping"); 786: } 787: break; 788: 789: case WRAP_MODE: 790: if (!keyInfo[2] || keyInfo[8]) 791: { 792: throw new InvalidKeyException( 793: "the certificate's key cannot be used for key wrapping"); 794: } 795: break; 796: } 797: } 798: } 799: init(opmode, certificate.getPublicKey(), random); 800: } 801: 802: /** 803: * <p>Initialize this cipher with the supplied key and source of 804: * randomness.</p> 805: * 806: * <p>The cipher will be initialized for encryption, decryption, key 807: * wrapping, or key unwrapping, depending upon whether the 808: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 809: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 810: * respectively.</p> 811: * 812: * <p>A call to any of the <code>init</code> methods overrides the 813: * state of the instance, and is equivalent to creating a new instance 814: * and calling its <code>init</code> method.</p> 815: * 816: * @param opmode The operation mode to use. 817: * @param key The key. 818: * @param random The source of randomness to use. 819: * @throws java.security.InvalidKeyException If the underlying cipher 820: * instance rejects the given key. 821: */ 822: public final void init(int opmode, Key key, SecureRandom random) 823: throws InvalidKeyException 824: { 825: if (cipherSpi != null) 826: { 827: cipherSpi.engineInit(opmode, key, random); 828: } 829: state = opmode; 830: } 831: 832: /** 833: * <p>Initialize this cipher with the supplied key and parameters.</p> 834: * 835: * <p>The cipher will be initialized for encryption, decryption, key 836: * wrapping, or key unwrapping, depending upon whether the 837: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 838: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 839: * respectively.</p> 840: * 841: * <p>If this cipher requires any random bytes (for example for an 842: * initilization vector) then the {@link java.security.SecureRandom} 843: * with the highest priority is used as the source of these bytes.</p> 844: * 845: * <p>A call to any of the <code>init</code> methods overrides the 846: * state of the instance, and is equivalent to creating a new instance 847: * and calling its <code>init</code> method.</p> 848: * 849: * @param opmode The operation mode to use. 850: * @param key The key. 851: * @param params The algorithm parameters to initialize this instance 852: * with. 853: * @throws java.security.InvalidKeyException If the underlying cipher 854: * instance rejects the given key. 855: * @throws java.security.InvalidAlgorithmParameterException If the 856: * supplied parameters are inappropriate for this cipher. 857: */ 858: public final void init(int opmode, Key key, AlgorithmParameters params) 859: throws InvalidKeyException, InvalidAlgorithmParameterException 860: { 861: init(opmode, key, params, new SecureRandom()); 862: } 863: 864: /** 865: * <p>Initialize this cipher with the supplied key and parameters.</p> 866: * 867: * <p>The cipher will be initialized for encryption, decryption, key 868: * wrapping, or key unwrapping, depending upon whether the 869: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 870: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 871: * respectively.</p> 872: * 873: * <p>If this cipher requires any random bytes (for example for an 874: * initilization vector) then the {@link java.security.SecureRandom} 875: * with the highest priority is used as the source of these bytes.</p> 876: * 877: * <p>A call to any of the <code>init</code> methods overrides the 878: * state of the instance, and is equivalent to creating a new instance 879: * and calling its <code>init</code> method.</p> 880: * 881: * @param opmode The operation mode to use. 882: * @param key The key. 883: * @param params The algorithm parameters to initialize this instance 884: * with. 885: * @throws java.security.InvalidKeyException If the underlying cipher 886: * instance rejects the given key. 887: * @throws java.security.InvalidAlgorithmParameterException If the 888: * supplied parameters are inappropriate for this cipher. 889: */ 890: public final void init(int opmode, Key key, AlgorithmParameterSpec params) 891: throws InvalidKeyException, InvalidAlgorithmParameterException 892: { 893: init(opmode, key, params, new SecureRandom()); 894: } 895: 896: /** 897: * <p>Initialize this cipher with the supplied key, parameters, and 898: * source of randomness.</p> 899: * 900: * <p>The cipher will be initialized for encryption, decryption, key 901: * wrapping, or key unwrapping, depending upon whether the 902: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 903: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 904: * respectively.</p> 905: * 906: * <p>A call to any of the <code>init</code> methods overrides the 907: * state of the instance, and is equivalent to creating a new instance 908: * and calling its <code>init</code> method.</p> 909: * 910: * @param opmode The operation mode to use. 911: * @param key The key. 912: * @param params The algorithm parameters to initialize this instance 913: * with. 914: * @param random The source of randomness to use. 915: * @throws java.security.InvalidKeyException If the underlying cipher 916: * instance rejects the given key. 917: * @throws java.security.InvalidAlgorithmParameterException If the 918: * supplied parameters are inappropriate for this cipher. 919: */ 920: public final void init(int opmode, Key key, AlgorithmParameters params, 921: SecureRandom random) 922: throws InvalidKeyException, InvalidAlgorithmParameterException 923: { 924: if (cipherSpi != null) 925: { 926: cipherSpi.engineInit(opmode, key, params, random); 927: } 928: state = opmode; 929: } 930: 931: /** 932: * <p>Initialize this cipher with the supplied key, parameters, and 933: * source of randomness.</p> 934: * 935: * <p>The cipher will be initialized for encryption, decryption, key 936: * wrapping, or key unwrapping, depending upon whether the 937: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 938: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 939: * respectively.</p> 940: * 941: * <p>A call to any of the <code>init</code> methods overrides the 942: * state of the instance, and is equivalent to creating a new instance 943: * and calling its <code>init</code> method.</p> 944: * 945: * @param opmode The operation mode to use. 946: * @param key The key. 947: * @param params The algorithm parameters to initialize this instance 948: * with. 949: * @param random The source of randomness to use. 950: * @throws java.security.InvalidKeyException If the underlying cipher 951: * instance rejects the given key. 952: * @throws java.security.InvalidAlgorithmParameterException If the 953: * supplied parameters are inappropriate for this cipher. 954: */ 955: public final void init(int opmode, Key key, AlgorithmParameterSpec params, 956: SecureRandom random) 957: throws InvalidKeyException, InvalidAlgorithmParameterException 958: { 959: if (cipherSpi != null) 960: { 961: cipherSpi.engineInit(opmode, key, params, random); 962: } 963: state = opmode; 964: } 965: 966: /** 967: * Unwrap a previously-wrapped key. 968: * 969: * @param wrappedKey The wrapped key. 970: * @param wrappedKeyAlgorithm The algorithm with which the key was 971: * wrapped. 972: * @param wrappedKeyType The type of key (public, private, or 973: * secret) that this wrapped key respresents. 974: * @return The unwrapped key. 975: * @throws java.lang.IllegalStateException If this instance has not be 976: * initialized for unwrapping. 977: * @throws java.security.InvalidKeyException If <code>wrappedKey</code> 978: * is not a wrapped key, if the algorithm cannot unwrap this 979: * key, or if the unwrapped key's type differs from the 980: * specified type. 981: * @throws java.security.NoSuchAlgorithmException If 982: * <code>wrappedKeyAlgorithm</code> is not a valid algorithm 983: * name. 984: */ 985: public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, 986: int wrappedKeyType) 987: throws IllegalStateException, InvalidKeyException, NoSuchAlgorithmException 988: { 989: if (cipherSpi == null) 990: { 991: return null; 992: } 993: if (state != UNWRAP_MODE) 994: { 995: throw new IllegalStateException("instance is not for unwrapping"); 996: } 997: return cipherSpi.engineUnwrap(wrappedKey, wrappedKeyAlgorithm, 998: wrappedKeyType); 999: } 1000: 1001: /** 1002: * Continue a multi-part transformation on an entire byte array, 1003: * returning the transformed bytes. 1004: * 1005: * @param input The input bytes. 1006: * @return The transformed bytes. 1007: * @throws java.lang.IllegalStateException If this cipher was not 1008: * initialized for encryption or decryption. 1009: */ 1010: public final byte[] update(byte[] input) throws IllegalStateException 1011: { 1012: return update(input, 0, input.length); 1013: } 1014: 1015: /** 1016: * Continue a multi-part transformation on part of a byte array, 1017: * returning the transformed bytes. 1018: * 1019: * @param input The input bytes. 1020: * @param inputOffset The index in the input to start. 1021: * @param inputLength The number of bytes to transform. 1022: * @return The transformed bytes. 1023: * @throws java.lang.IllegalStateException If this cipher was not 1024: * initialized for encryption or decryption. 1025: */ 1026: public final byte[] update(byte[] input, int inputOffset, int inputLength) 1027: throws IllegalStateException 1028: { 1029: if (cipherSpi == null) 1030: { 1031: byte[] b = new byte[inputLength]; 1032: System.arraycopy(input, inputOffset, b, 0, inputLength); 1033: return b; 1034: } 1035: if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 1036: { 1037: throw new IllegalStateException( 1038: "cipher is not for encrypting or decrypting"); 1039: } 1040: return cipherSpi.engineUpdate(input, inputOffset, inputLength); 1041: } 1042: 1043: /** 1044: * Continue a multi-part transformation on part of a byte array, 1045: * placing the transformed bytes into the given array. 1046: * 1047: * @param input The input bytes. 1048: * @param inputOffset The index in the input to start. 1049: * @param inputLength The number of bytes to transform. 1050: * @param output The output byte array. 1051: * @return The number of transformed bytes. 1052: * @throws java.lang.IllegalStateException If this cipher was not 1053: * initialized for encryption or decryption. 1054: * @throws javax.security.ShortBufferException If there is not enough 1055: * room in the output array to hold the transformed bytes. 1056: */ 1057: public final int update(byte[] input, int inputOffset, int inputLength, 1058: byte[] output) 1059: throws IllegalStateException, ShortBufferException 1060: { 1061: return update(input, inputOffset, inputLength, output, 0); 1062: } 1063: 1064: /** 1065: * Continue a multi-part transformation on part of a byte array, 1066: * placing the transformed bytes into the given array. 1067: * 1068: * @param input The input bytes. 1069: * @param inputOffset The index in the input to start. 1070: * @param inputLength The number of bytes to transform. 1071: * @param output The output byte array. 1072: * @param outputOffset The index in the output array to start. 1073: * @return The number of transformed bytes. 1074: * @throws java.lang.IllegalStateException If this cipher was not 1075: * initialized for encryption or decryption. 1076: * @throws javax.security.ShortBufferException If there is not enough 1077: * room in the output array to hold the transformed bytes. 1078: */ 1079: public final int update(byte[] input, int inputOffset, int inputLength, 1080: byte[] output, int outputOffset) 1081: throws IllegalStateException, ShortBufferException 1082: { 1083: if (cipherSpi == null) 1084: { 1085: if (inputLength > output.length - outputOffset) 1086: { 1087: throw new ShortBufferException(); 1088: } 1089: System.arraycopy(input, inputOffset, output, outputOffset, inputLength); 1090: return inputLength; 1091: } 1092: if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 1093: { 1094: throw new IllegalStateException( 1095: "cipher is not for encrypting or decrypting"); 1096: } 1097: return cipherSpi.engineUpdate(input, inputOffset, inputLength, 1098: output, outputOffset); 1099: } 1100: 1101: /** 1102: * Continue a multi-part transformation on a byte buffer, storing 1103: * the transformed bytes into another buffer. 1104: * 1105: * @param input The input buffer. 1106: * @param output The output buffer. 1107: * @return The number of bytes stored in <i>output</i>. 1108: * @throws IllegalArgumentException If the two buffers are the same 1109: * object. 1110: * @throws IllegalStateException If this cipher was not initialized 1111: * for encrypting or decrypting. 1112: * @throws ReadOnlyBufferException If the output buffer is not 1113: * writable. 1114: * @throws ShortBufferException If the output buffer does not have 1115: * enough available space for the transformed bytes. 1116: * @since 1.5 1117: */ 1118: public final int update (ByteBuffer input, ByteBuffer output) 1119: throws ReadOnlyBufferException, ShortBufferException 1120: { 1121: if (input == output) 1122: throw new IllegalArgumentException 1123: ("input and output buffers must be different"); 1124: if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 1125: throw new IllegalStateException 1126: ("not initialized for encryption or decryption"); 1127: return cipherSpi.engineUpdate (input, output); 1128: } 1129: 1130: /** 1131: * Wrap a key. 1132: * 1133: * @param key The key to wrap. 1134: * @return The wrapped key. 1135: * @throws java.lang.IllegalStateException If this instance was not 1136: * initialized for key wrapping. 1137: * @throws javax.crypto.IllegalBlockSizeException If this instance has 1138: * no padding and the key is not a multiple of the block size. 1139: * @throws java.security.InvalidKeyException If this instance cannot 1140: * wrap this key. 1141: */ 1142: public final byte[] wrap(Key key) 1143: throws IllegalStateException, IllegalBlockSizeException, InvalidKeyException 1144: { 1145: if (cipherSpi == null) 1146: { 1147: return null; 1148: } 1149: if (state != WRAP_MODE) 1150: { 1151: throw new IllegalStateException("instance is not for key wrapping"); 1152: } 1153: return cipherSpi.engineWrap(key); 1154: } 1155: }