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