/* * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */ /* * NOTE: * Because of various external restrictions (i.e. US export * regulations, etc.), the actual source code can not be provided * at this time. This file represents the skeleton of the source * file, so that javadocs of the API can be created. */ package javax.crypto; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.spec.*; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import com.sun.satsa.crypto.RSAPublicKey; /** * This class provides the functionality of a cryptographic cipher for * encryption and decryption. It forms the core of the Java Cryptographic * Extension (JCE) framework. * * <p>In order to create a Cipher object, the application calls the * Cipher's <code>getInstance</code> method, and passes the name of the * requested <i>transformation</i> to it. * * <p>A <i>transformation</i> is a string that describes the operation (or * set of operations) to be performed on the given input, to produce some * output. A transformation always includes the name of a cryptographic * algorithm (e.g., <i>DES</i>), and may be followed by a feedback mode and * padding scheme. * * <p> A transformation is of the form:<p> * * <ul> * <li>"<i>algorithm/mode/padding</i>" or * <p> * <li>"<i>algorithm</i>" * </ul> * * <P> (in the latter case, * provider-specific default values for the mode and padding scheme are used). * For example, the following is a valid transformation:<p> * * <pre> * Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>"); * </pre> * * <p>When requesting a block cipher in stream cipher mode (e.g., * <code>DES</code> in <code>CFB</code> or <code>OFB</code> mode), the user may * optionally specify the number of bits to be * processed at a time, by appending this number to the mode name as shown in * the "<i>DES/CFB8/NoPadding</i>" and "<i>DES/OFB32/PKCS5Padding</i>" * transformations. If no such number is specified, a provider-specific default * is used. * * * @version 1.108, 04/03/02 * */ public class Cipher { /** * Constant used to initialize cipher to encryption mode. */ public static final int ENCRYPT_MODE = 1; /** * Constant used to initialize cipher to decryption mode. */ public static final int DECRYPT_MODE = 2; /** Cipher implementation object. */ private com.sun.j2me.crypto.Cipher cipher; /** * Creates a Cipher object. * @param cipher cipher implementation * of algorithm is being used */ private Cipher(com.sun.j2me.crypto.Cipher cipher) { this.cipher = cipher; } /** * Generates a <code>Cipher</code> object that implements the specified * transformation. * * @param transformation the name of the transformation, e.g., * <i>DES/CBC/PKCS5Padding</i>. * See Appendix A in the * <a href="../../../guide/security/jce/JCERefGuide.html#AppA"> * Java Cryptography Extension Reference Guide</a> * for information about standard transformation names. * * @return a cipher that implements the requested transformation * * @exception NoSuchAlgorithmException if the specified transformation is * not available * @exception NoSuchPaddingException if <code>transformation</code> * contains a padding scheme that is not available. */ public static final Cipher getInstance(String transformation) throws NoSuchAlgorithmException, NoSuchPaddingException { try { return new Cipher( com.sun.j2me.crypto.Cipher.getNewInstance(transformation)); } catch (com.sun.j2me.crypto.NoSuchAlgorithmException e) { throw new NoSuchAlgorithmException(e.getMessage()); } catch (com.sun.j2me.crypto.NoSuchPaddingException e) { throw new NoSuchPaddingException(e.getMessage()); } } /** * Initializes this cipher with a key. * * <p>The cipher is initialized for one of the following operations: * encryption, decryption, depending * on the value of <code>opmode</code>. * * <p>If this cipher requires any algorithm parameters that cannot be * derived from the given <code>key</code>, the underlying cipher * implementation is supposed to generate the required parameters itself * (using provider-specific default or random values) if it is being * initialized for encryption, and raise an * <code>InvalidKeyException</code> if it is being * initialized for decryption. * * <p>Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @param opmode the operation mode of this cipher (this is one of * the following: * <code>ENCRYPT_MODE</code> or <code>DECRYPT_MODE</code>) * @param key the key * * @exception InvalidKeyException if the given key is inappropriate for * initializing this cipher, or if this cipher is being initialized for * decryption and requires algorithm parameters that cannot be * determined from the given key, or if the given key has a keysize that * exceeds the maximum allowable keysize. */ public final void init(int opmode, Key key) throws InvalidKeyException { try { init(opmode, key, null); } catch (InvalidAlgorithmParameterException e) { throw new InvalidKeyException(); } } /** * Initializes this cipher with a key and a set of algorithm * parameters. * * <p>The cipher is initialized for one of the following operations: * encryption or decryption depending * on the value of <code>opmode</code>. * * <p>If this cipher requires any algorithm parameters and * <code>params</code> is null, the underlying cipher implementation is * supposed to generate the required parameters itself (using * provider-specific default or random values) if it is being * initialized for encryption, and raise an * <code>InvalidAlgorithmParameterException</code> if it is being * initialized for decryption. * * <p>Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @param opmode the operation mode of this cipher (this is one of the * following: * <code>ENCRYPT_MODE</code> or <code>DECRYPT_MODE</code>) * @param key the encryption key * @param params the algorithm parameters * * @exception InvalidKeyException if the given key is inappropriate for * initializing this cipher, or its keysize exceeds the maximum allowable * keysize. * @exception InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this cipher, * or this cipher is being initialized for decryption and requires * algorithm parameters and <code>params</code> is null, or the given * algorithm parameters imply a cryptographic strength that would exceed * the legal limits. */ public final void init(int opmode, Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException { com.sun.j2me.crypto.Key cipherKey; com.sun.j2me.crypto.CryptoParameter cryptoParameter; if (opmode == DECRYPT_MODE) { opmode = com.sun.j2me.crypto.Cipher.DECRYPT_MODE; } else if (opmode == ENCRYPT_MODE) { opmode = com.sun.j2me.crypto.Cipher.ENCRYPT_MODE; } else { throw new IllegalArgumentException("Wrong operation mode"); } if (key instanceof SecretKeySpec) { SecretKeySpec temp = (SecretKeySpec)key; byte[] secret = key.getEncoded(); cipherKey = new com.sun.j2me.crypto.SecretKey( secret, 0, secret.length, key.getAlgorithm()); } else if (key instanceof RSAPublicKey) { RSAPublicKey temp = (RSAPublicKey)key; cipherKey = temp.getKey(); } else { throw new InvalidKeyException(); } if (params == null) { cryptoParameter = null; } else if (params instanceof IvParameterSpec) { byte[] iv = ((IvParameterSpec)params).getIV(); cryptoParameter = new com.sun.j2me.crypto.IvParameter( iv, 0, iv.length); } else { throw new InvalidAlgorithmParameterException(); } try { cipher.init(opmode, cipherKey.getKey(), cryptoParameter); } catch (com.sun.j2me.crypto.InvalidKeyException e) { throw new InvalidKeyException(e.getMessage()); } catch (com.sun.j2me.crypto.InvalidAlgorithmParameterException e) { throw new InvalidAlgorithmParameterException(e.getMessage()); } } /** * Continues a multiple-part encryption or decryption operation * (depending on how this cipher was initialized), processing another data * part. * * <p>The first <code>inputLen</code> bytes in the <code>input</code> * buffer, starting at <code>inputOffset</code> inclusive, are processed, * and the result is stored in the <code>output</code> buffer, starting at * <code>outputOffset</code> inclusive. * * <p>If the <code>output</code> buffer is too small to hold the result, * a <code>ShortBufferException</code> is thrown. In this case, repeat this * call with a larger output buffer. * * <p>If <code>inputLen</code> is zero, this method returns * a length of zero. * * <p>Note: this method should be copy-safe, which means the * <code>input</code> and <code>output</code> buffers can reference * the same byte array and no unprocessed input data is overwritten * when the result is copied into the output buffer. * * @param input the input buffer * @param inputOffset the offset in <code>input</code> where the input * starts * @param inputLen the input length * @param output the buffer for the result * @param outputOffset the offset in <code>output</code> where the result * is stored * * @return the number of bytes stored in <code>output</code> * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception ShortBufferException if the given output buffer is too small * to hold the result */ public final int update(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws IllegalStateException, ShortBufferException { try { return cipher.update(input, inputOffset, inputLen, output, outputOffset); } catch (com.sun.j2me.crypto.ShortBufferException e) { throw new ShortBufferException(e.getMessage()); } } /** * Encrypts or decrypts data in a single-part operation, or finishes a * multiple-part operation. The data is encrypted or decrypted, * depending on how this cipher was initialized. * * <p>The first <code>inputLen</code> bytes in the <code>input</code> * buffer, starting at <code>inputOffset</code> inclusive, and any input * bytes that may have been buffered during a previous * <code>update</code> operation, are processed, with padding * (if requested) being applied. * The result is stored in the <code>output</code> buffer, starting at * <code>outputOffset</code> inclusive. * * <p>If the <code>output</code> buffer is too small to hold the result, * a <code>ShortBufferException</code> is thrown. In this case, repeat this * call with a larger output buffer. * * <p>Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to <code>init</code>. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * <code>init</code>) more data. * * <p>Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * * <p>Note: this method should be copy-safe, which means the * <code>input</code> and <code>output</code> buffers can reference * the same byte array and no unprocessed input data is overwritten * when the result is copied into the output buffer. * * @param input the input buffer * @param inputOffset the offset in <code>input</code> where the input * starts * @param inputLen the input length * @param output the buffer for the result * @param outputOffset the offset in <code>output</code> where the result * is stored * * @return the number of bytes stored in <code>output</code> * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception IllegalBlockSizeException if this cipher is a block cipher, * no padding has been requested (only in encryption mode), and the total * input length of the data processed by this cipher is not a multiple of * block size * @exception ShortBufferException if the given output buffer is too small * to hold the result * @exception BadPaddingException if this cipher is in decryption mode, * and (un)padding has been requested, but the decrypted data is not * bounded by the appropriate padding bytes */ public final int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws IllegalStateException, ShortBufferException, IllegalBlockSizeException, BadPaddingException { try { return cipher.doFinal(input, inputOffset, inputLen, output, outputOffset); } catch (com.sun.j2me.crypto.ShortBufferException e) { throw new ShortBufferException(e.getMessage()); } catch (com.sun.j2me.crypto.IllegalBlockSizeException e) { throw new IllegalBlockSizeException(e.getMessage()); } catch (com.sun.j2me.crypto.BadPaddingException e) { throw new BadPaddingException(e.getMessage()); } } /** * Returns the initialization vector (IV) in a new buffer. * This is useful in the case where a random IV was created. * @return the initialization vector in a new buffer, * or <code>null</code> if the underlying algorithm does * not use an IV, or if the IV has not yet been set. */ public final byte[] getIV() { return cipher.getIV(); } }