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: { 643: return inputLength; 644: } 645: if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 646: { 647: throw new IllegalStateException("neither encrypting nor decrypting"); 648: } 649: return cipherSpi.engineGetOutputSize(inputLength); 650: } 651: 652: /** 653: * <p>Initialize this cipher with the public key from the given 654: * certificate.</p> 655: * 656: * <p>The cipher will be initialized for encryption, decryption, key 657: * wrapping, or key unwrapping, depending upon whether the 658: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 659: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 660: * respectively.</p> 661: * 662: * <p>As per the Java 1.4 specification, if <code>cert</code> is an 663: * instance of an {@link java.security.cert.X509Certificate} and its 664: * <i>key usage</i> extension field is incompatible with 665: * <code>opmode</code> then an {@link 666: * java.security.InvalidKeyException} is thrown.</p> 667: * 668: * <p>If this cipher requires any random bytes (for example for an 669: * initilization vector) than the {@link java.security.SecureRandom} 670: * with the highest priority is used as the source of these bytes.</p> 671: * 672: * <p>A call to any of the <code>init</code> methods overrides the 673: * state of the instance, and is equivalent to creating a new instance 674: * and calling its <code>init</code> method.</p> 675: * 676: * @param opmode The operation mode to use. 677: * @param certificate The certificate. 678: * @throws java.security.InvalidKeyException If the underlying cipher 679: * instance rejects the certificate's public key, or if the 680: * public key cannot be used as described above. 681: */ 682: public final void init(int opmode, Certificate certificate) 683: throws InvalidKeyException 684: { 685: init(opmode, certificate, new SecureRandom()); 686: } 687: 688: /** 689: * <p>Initialize this cipher with the supplied key.</p> 690: * 691: * <p>The cipher will be initialized for encryption, decryption, key 692: * wrapping, or key unwrapping, depending upon whether the 693: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 694: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 695: * respectively.</p> 696: * 697: * <p>If this cipher requires any random bytes (for example for an 698: * initilization vector) than the {@link java.security.SecureRandom} 699: * with the highest priority is used as the source of these bytes.</p> 700: * 701: * <p>A call to any of the <code>init</code> methods overrides the 702: * state of the instance, and is equivalent to creating a new instance 703: * and calling its <code>init</code> method.</p> 704: * 705: * @param opmode The operation mode to use. 706: * @param key The key. 707: * @throws java.security.InvalidKeyException If the underlying cipher 708: * instance rejects the given key. 709: */ 710: public final void init(int opmode, Key key) throws InvalidKeyException 711: { 712: if (cipherSpi != null) 713: { 714: cipherSpi.engineInit(opmode, key, new SecureRandom()); 715: } 716: state = opmode; 717: } 718: 719: /** 720: * <p>Initialize this cipher with the public key from the given 721: * certificate and the specified source of randomness.</p> 722: * 723: * <p>The cipher will be initialized for encryption, decryption, key 724: * wrapping, or key unwrapping, depending upon whether the 725: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 726: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 727: * respectively.</p> 728: * 729: * <p>As per the Java 1.4 specification, if <code>cert</code> is an 730: * instance of an {@link java.security.cert.X509Certificate} and its 731: * <i>key usage</i> extension field is incompatible with 732: * <code>opmode</code> then an {@link 733: * java.security.InvalidKeyException} is thrown.</p> 734: * 735: * <p>If this cipher requires any random bytes (for example for an 736: * initilization vector) than the {@link java.security.SecureRandom} 737: * with the highest priority is used as the source of these bytes.</p> 738: * 739: * <p>A call to any of the <code>init</code> methods overrides the 740: * state of the instance, and is equivalent to creating a new instance 741: * and calling its <code>init</code> method.</p> 742: * 743: * @param opmode The operation mode to use. 744: * @param certificate The certificate. 745: * @param random The source of randomness. 746: * @throws java.security.InvalidKeyException If the underlying cipher 747: * instance rejects the certificate's public key, or if the 748: * public key cannot be used as described above. 749: */ 750: public final void 751: init(int opmode, Certificate certificate, SecureRandom random) 752: throws InvalidKeyException 753: { 754: if (certificate instanceof X509Certificate) 755: { 756: boolean[] keyInfo = ((X509Certificate) certificate).getKeyUsage(); 757: if (keyInfo != null) 758: { 759: switch (opmode) 760: { 761: case DECRYPT_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[7]) 768: { 769: throw new InvalidKeyException( 770: "the certificate's key can only be used for encryption"); 771: } 772: break; 773: 774: case ENCRYPT_MODE: 775: if (!keyInfo[3]) 776: { 777: throw new InvalidKeyException( 778: "the certificate's key cannot be used for transforming data"); 779: } 780: if (keyInfo[8]) 781: { 782: throw new InvalidKeyException( 783: "the certificate's key can only be used for decryption"); 784: } 785: break; 786: 787: case UNWRAP_MODE: 788: if (!keyInfo[2] || keyInfo[7]) 789: { 790: throw new InvalidKeyException( 791: "the certificate's key cannot be used for key unwrapping"); 792: } 793: break; 794: 795: case WRAP_MODE: 796: if (!keyInfo[2] || keyInfo[8]) 797: { 798: throw new InvalidKeyException( 799: "the certificate's key cannot be used for key wrapping"); 800: } 801: break; 802: } 803: } 804: } 805: init(opmode, certificate.getPublicKey(), random); 806: } 807: 808: /** 809: * <p>Initialize this cipher with the supplied key and source of 810: * randomness.</p> 811: * 812: * <p>The cipher will be initialized for encryption, decryption, key 813: * wrapping, or key unwrapping, depending upon whether the 814: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 815: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 816: * respectively.</p> 817: * 818: * <p>A call to any of the <code>init</code> methods overrides the 819: * state of the instance, and is equivalent to creating a new instance 820: * and calling its <code>init</code> method.</p> 821: * 822: * @param opmode The operation mode to use. 823: * @param key The key. 824: * @param random The source of randomness to use. 825: * @throws java.security.InvalidKeyException If the underlying cipher 826: * instance rejects the given key. 827: */ 828: public final void init(int opmode, Key key, SecureRandom random) 829: throws InvalidKeyException 830: { 831: if (cipherSpi != null) 832: { 833: cipherSpi.engineInit(opmode, key, random); 834: } 835: state = opmode; 836: } 837: 838: /** 839: * <p>Initialize this cipher with the supplied key and parameters.</p> 840: * 841: * <p>The cipher will be initialized for encryption, decryption, key 842: * wrapping, or key unwrapping, depending upon whether the 843: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 844: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 845: * respectively.</p> 846: * 847: * <p>If this cipher requires any random bytes (for example for an 848: * initilization vector) then the {@link java.security.SecureRandom} 849: * with the highest priority is used as the source of these bytes.</p> 850: * 851: * <p>A call to any of the <code>init</code> methods overrides the 852: * state of the instance, and is equivalent to creating a new instance 853: * and calling its <code>init</code> method.</p> 854: * 855: * @param opmode The operation mode to use. 856: * @param key The key. 857: * @param params The algorithm parameters to initialize this instance 858: * with. 859: * @throws java.security.InvalidKeyException If the underlying cipher 860: * instance rejects the given key. 861: * @throws java.security.InvalidAlgorithmParameterException If the 862: * supplied parameters are inappropriate for this cipher. 863: */ 864: public final void init(int opmode, Key key, AlgorithmParameters params) 865: throws InvalidKeyException, InvalidAlgorithmParameterException 866: { 867: init(opmode, key, params, new SecureRandom()); 868: } 869: 870: /** 871: * <p>Initialize this cipher with the supplied key and parameters.</p> 872: * 873: * <p>The cipher will be initialized for encryption, decryption, key 874: * wrapping, or key unwrapping, depending upon whether the 875: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 876: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 877: * respectively.</p> 878: * 879: * <p>If this cipher requires any random bytes (for example for an 880: * initilization vector) then the {@link java.security.SecureRandom} 881: * with the highest priority is used as the source of these bytes.</p> 882: * 883: * <p>A call to any of the <code>init</code> methods overrides the 884: * state of the instance, and is equivalent to creating a new instance 885: * and calling its <code>init</code> method.</p> 886: * 887: * @param opmode The operation mode to use. 888: * @param key The key. 889: * @param params The algorithm parameters to initialize this instance 890: * with. 891: * @throws java.security.InvalidKeyException If the underlying cipher 892: * instance rejects the given key. 893: * @throws java.security.InvalidAlgorithmParameterException If the 894: * supplied parameters are inappropriate for this cipher. 895: */ 896: public final void init(int opmode, Key key, AlgorithmParameterSpec params) 897: throws InvalidKeyException, InvalidAlgorithmParameterException 898: { 899: init(opmode, key, params, new SecureRandom()); 900: } 901: 902: /** 903: * <p>Initialize this cipher with the supplied key, parameters, and 904: * source of randomness.</p> 905: * 906: * <p>The cipher will be initialized for encryption, decryption, key 907: * wrapping, or key unwrapping, depending upon whether the 908: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 909: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 910: * respectively.</p> 911: * 912: * <p>A call to any of the <code>init</code> methods overrides the 913: * state of the instance, and is equivalent to creating a new instance 914: * and calling its <code>init</code> method.</p> 915: * 916: * @param opmode The operation mode to use. 917: * @param key The key. 918: * @param params The algorithm parameters to initialize this instance 919: * with. 920: * @param random The source of randomness to use. 921: * @throws java.security.InvalidKeyException If the underlying cipher 922: * instance rejects the given key. 923: * @throws java.security.InvalidAlgorithmParameterException If the 924: * supplied parameters are inappropriate for this cipher. 925: */ 926: public final void init(int opmode, Key key, AlgorithmParameters params, 927: SecureRandom random) 928: throws InvalidKeyException, InvalidAlgorithmParameterException 929: { 930: if (cipherSpi != null) 931: { 932: cipherSpi.engineInit(opmode, key, params, random); 933: } 934: state = opmode; 935: } 936: 937: /** 938: * <p>Initialize this cipher with the supplied key, parameters, and 939: * source of randomness.</p> 940: * 941: * <p>The cipher will be initialized for encryption, decryption, key 942: * wrapping, or key unwrapping, depending upon whether the 943: * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link 944: * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, 945: * respectively.</p> 946: * 947: * <p>A call to any of the <code>init</code> methods overrides the 948: * state of the instance, and is equivalent to creating a new instance 949: * and calling its <code>init</code> method.</p> 950: * 951: * @param opmode The operation mode to use. 952: * @param key The key. 953: * @param params The algorithm parameters to initialize this instance 954: * with. 955: * @param random The source of randomness to use. 956: * @throws java.security.InvalidKeyException If the underlying cipher 957: * instance rejects the given key. 958: * @throws java.security.InvalidAlgorithmParameterException If the 959: * supplied parameters are inappropriate for this cipher. 960: */ 961: public final void init(int opmode, Key key, AlgorithmParameterSpec params, 962: SecureRandom random) 963: throws InvalidKeyException, InvalidAlgorithmParameterException 964: { 965: if (cipherSpi != null) 966: { 967: cipherSpi.engineInit(opmode, key, params, random); 968: } 969: state = opmode; 970: } 971: 972: /** 973: * Unwrap a previously-wrapped key. 974: * 975: * @param wrappedKey The wrapped key. 976: * @param wrappedKeyAlgorithm The algorithm with which the key was 977: * wrapped. 978: * @param wrappedKeyType The type of key (public, private, or 979: * secret) that this wrapped key respresents. 980: * @return The unwrapped key. 981: * @throws java.lang.IllegalStateException If this instance has not be 982: * initialized for unwrapping. 983: * @throws java.security.InvalidKeyException If <code>wrappedKey</code> 984: * is not a wrapped key, if the algorithm cannot unwrap this 985: * key, or if the unwrapped key's type differs from the 986: * specified type. 987: * @throws java.security.NoSuchAlgorithmException If 988: * <code>wrappedKeyAlgorithm</code> is not a valid algorithm 989: * name. 990: */ 991: public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, 992: int wrappedKeyType) 993: throws IllegalStateException, InvalidKeyException, NoSuchAlgorithmException 994: { 995: if (cipherSpi == null) 996: { 997: return null; 998: } 999: if (state != UNWRAP_MODE) 1000: { 1001: throw new IllegalStateException("instance is not for unwrapping"); 1002: } 1003: return cipherSpi.engineUnwrap(wrappedKey, wrappedKeyAlgorithm, 1004: wrappedKeyType); 1005: } 1006: 1007: /** 1008: * Continue a multi-part transformation on an entire byte array, 1009: * returning the transformed bytes. 1010: * 1011: * @param input The input bytes. 1012: * @return The transformed bytes. 1013: * @throws java.lang.IllegalStateException If this cipher was not 1014: * initialized for encryption or decryption. 1015: */ 1016: public final byte[] update(byte[] input) throws IllegalStateException 1017: { 1018: return update(input, 0, input.length); 1019: } 1020: 1021: /** 1022: * Continue a multi-part transformation on part of a byte array, 1023: * returning the transformed bytes. 1024: * 1025: * @param input The input bytes. 1026: * @param inputOffset The index in the input to start. 1027: * @param inputLength The number of bytes to transform. 1028: * @return The transformed bytes. 1029: * @throws java.lang.IllegalStateException If this cipher was not 1030: * initialized for encryption or decryption. 1031: */ 1032: public final byte[] update(byte[] input, int inputOffset, int inputLength) 1033: throws IllegalStateException 1034: { 1035: if (cipherSpi == null) 1036: { 1037: byte[] b = new byte[inputLength]; 1038: System.arraycopy(input, inputOffset, b, 0, inputLength); 1039: return b; 1040: } 1041: if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 1042: { 1043: throw new IllegalStateException( 1044: "cipher is not for encrypting or decrypting"); 1045: } 1046: return cipherSpi.engineUpdate(input, inputOffset, inputLength); 1047: } 1048: 1049: /** 1050: * Continue a multi-part transformation on part of a byte array, 1051: * placing the transformed bytes into the given array. 1052: * 1053: * @param input The input bytes. 1054: * @param inputOffset The index in the input to start. 1055: * @param inputLength The number of bytes to transform. 1056: * @param output The output byte array. 1057: * @return The number of transformed bytes. 1058: * @throws java.lang.IllegalStateException If this cipher was not 1059: * initialized for encryption or decryption. 1060: * @throws javax.security.ShortBufferException If there is not enough 1061: * room in the output array to hold the transformed bytes. 1062: */ 1063: public final int update(byte[] input, int inputOffset, int inputLength, 1064: byte[] output) 1065: throws IllegalStateException, ShortBufferException 1066: { 1067: return update(input, inputOffset, inputLength, output, 0); 1068: } 1069: 1070: /** 1071: * Continue a multi-part transformation on part of a byte array, 1072: * placing the transformed bytes into the given array. 1073: * 1074: * @param input The input bytes. 1075: * @param inputOffset The index in the input to start. 1076: * @param inputLength The number of bytes to transform. 1077: * @param output The output byte array. 1078: * @param outputOffset The index in the output array to start. 1079: * @return The number of transformed bytes. 1080: * @throws java.lang.IllegalStateException If this cipher was not 1081: * initialized for encryption or decryption. 1082: * @throws javax.security.ShortBufferException If there is not enough 1083: * room in the output array to hold the transformed bytes. 1084: */ 1085: public final int update(byte[] input, int inputOffset, int inputLength, 1086: byte[] output, int outputOffset) 1087: throws IllegalStateException, ShortBufferException 1088: { 1089: if (cipherSpi == null) 1090: { 1091: if (inputLength > output.length - outputOffset) 1092: { 1093: throw new ShortBufferException(); 1094: } 1095: System.arraycopy(input, inputOffset, output, outputOffset, inputLength); 1096: return inputLength; 1097: } 1098: if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 1099: { 1100: throw new IllegalStateException( 1101: "cipher is not for encrypting or decrypting"); 1102: } 1103: return cipherSpi.engineUpdate(input, inputOffset, inputLength, 1104: output, outputOffset); 1105: } 1106: 1107: /** 1108: * Continue a multi-part transformation on a byte buffer, storing 1109: * the transformed bytes into another buffer. 1110: * 1111: * @param input The input buffer. 1112: * @param output The output buffer. 1113: * @return The number of bytes stored in <i>output</i>. 1114: * @throws IllegalArgumentException If the two buffers are the same 1115: * object. 1116: * @throws IllegalStateException If this cipher was not initialized 1117: * for encrypting or decrypting. 1118: * @throws ReadOnlyBufferException If the output buffer is not 1119: * writable. 1120: * @throws ShortBufferException If the output buffer does not have 1121: * enough available space for the transformed bytes. 1122: * @since 1.5 1123: */ 1124: public final int update (ByteBuffer input, ByteBuffer output) 1125: throws ReadOnlyBufferException, ShortBufferException 1126: { 1127: if (input == output) 1128: throw new IllegalArgumentException 1129: ("input and output buffers must be different"); 1130: if (state != ENCRYPT_MODE && state != DECRYPT_MODE) 1131: throw new IllegalStateException 1132: ("not initialized for encryption or decryption"); 1133: return cipherSpi.engineUpdate (input, output); 1134: } 1135: 1136: /** 1137: * Wrap a key. 1138: * 1139: * @param key The key to wrap. 1140: * @return The wrapped key. 1141: * @throws java.lang.IllegalStateException If this instance was not 1142: * initialized for key wrapping. 1143: * @throws javax.crypto.IllegalBlockSizeException If this instance has 1144: * no padding and the key is not a multiple of the block size. 1145: * @throws java.security.InvalidKeyException If this instance cannot 1146: * wrap this key. 1147: */ 1148: public final byte[] wrap(Key key) 1149: throws IllegalStateException, IllegalBlockSizeException, InvalidKeyException 1150: { 1151: if (cipherSpi == null) 1152: { 1153: return null; 1154: } 1155: if (state != WRAP_MODE) 1156: { 1157: throw new IllegalStateException("instance is not for key wrapping"); 1158: } 1159: return cipherSpi.engineWrap(key); 1160: } 1161: }