001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: * NOTE:
027: * Because of various external restrictions (i.e. US export
028: * regulations, etc.), the actual source code can not be provided
029: * at this time. This file represents the skeleton of the source
030: * file, so that javadocs of the API can be created.
031: */
032:
033: package javax.crypto;
034:
035: import java.security.*;
036: import java.security.spec.*;
037:
038: import javax.crypto.spec.*;
039:
040: import com.sun.satsa.crypto.*;
041:
042: /**
043: * This class provides the functionality of a cryptographic cipher for
044: * encryption and decryption. It forms the core of the Java Cryptographic
045: * Extension (JCE) framework.
046: *
047: * <p>In order to create a Cipher object, the application calls the
048: * Cipher's <code>getInstance</code> method, and passes the name of the
049: * requested <i>transformation</i> to it.
050: *
051: * <p>A <i>transformation</i> is a string that describes the operation (or
052: * set of operations) to be performed on the given input, to produce some
053: * output. A transformation always includes the name of a cryptographic
054: * algorithm (e.g., <i>DES</i>), and may be followed by a feedback mode and
055: * padding scheme.
056: *
057: * <p> A transformation is of the form:<p>
058: *
059: * <ul>
060: * <li>"<i>algorithm/mode/padding</i>" or
061: * <p>
062: * <li>"<i>algorithm</i>"
063: * </ul>
064: *
065: * <P> (in the latter case,
066: * provider-specific default values for the mode and padding scheme are used).
067: * For example, the following is a valid transformation:<p>
068: *
069: * <pre>
070: * Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>");
071: * </pre>
072: *
073: * <p>When requesting a block cipher in stream cipher mode (e.g.,
074: * <code>DES</code> in <code>CFB</code> or <code>OFB</code> mode), the user may
075: * optionally specify the number of bits to be
076: * processed at a time, by appending this number to the mode name as shown in
077: * the "<i>DES/CFB8/NoPadding</i>" and "<i>DES/OFB32/PKCS5Padding</i>"
078: * transformations. If no such number is specified, a provider-specific default
079: * is used.
080: *
081: *
082: * @version 1.108, 04/03/02
083: *
084: */
085: public class Cipher {
086:
087: /**
088: * Constant used to initialize cipher to encryption mode.
089: */
090: public static final int ENCRYPT_MODE = 1;
091:
092: /**
093: * Constant used to initialize cipher to decryption mode.
094: */
095: public static final int DECRYPT_MODE = 2;
096:
097: /** Cipher implementation object. */
098: private com.sun.midp.crypto.Cipher cipher;
099:
100: /**
101: * Creates a Cipher object.
102: * @param cipher cipher implementation
103: * of algorithm is being used
104: */
105: private Cipher(com.sun.midp.crypto.Cipher cipher) {
106: this .cipher = cipher;
107: }
108:
109: /**
110: * Generates a <code>Cipher</code> object that implements the specified
111: * transformation.
112: *
113: * @param transformation the name of the transformation, e.g.,
114: * <i>DES/CBC/PKCS5Padding</i>.
115: * See Appendix A in the
116: * <a href="../../../guide/security/jce/JCERefGuide.html#AppA">
117: * Java Cryptography Extension Reference Guide</a>
118: * for information about standard transformation names.
119: *
120: * @return a cipher that implements the requested transformation
121: *
122: * @exception NoSuchAlgorithmException if the specified transformation is
123: * not available
124: * @exception NoSuchPaddingException if <code>transformation</code>
125: * contains a padding scheme that is not available.
126: */
127: public static final Cipher getInstance(String transformation)
128: throws NoSuchAlgorithmException, NoSuchPaddingException {
129:
130: try {
131: return new Cipher(com.sun.midp.crypto.Cipher
132: .getInstance(transformation));
133: } catch (com.sun.midp.crypto.NoSuchAlgorithmException e) {
134: throw new NoSuchAlgorithmException(e.getMessage());
135: } catch (com.sun.midp.crypto.NoSuchPaddingException e) {
136: throw new NoSuchPaddingException(e.getMessage());
137: }
138: }
139:
140: /**
141: * Initializes this cipher with a key.
142: *
143: * <p>The cipher is initialized for one of the following operations:
144: * encryption, decryption, depending
145: * on the value of <code>opmode</code>.
146: *
147: * <p>If this cipher requires any algorithm parameters that cannot be
148: * derived from the given <code>key</code>, the underlying cipher
149: * implementation is supposed to generate the required parameters itself
150: * (using provider-specific default or random values) if it is being
151: * initialized for encryption, and raise an
152: * <code>InvalidKeyException</code> if it is being
153: * initialized for decryption.
154: *
155: * <p>Note that when a Cipher object is initialized, it loses all
156: * previously-acquired state. In other words, initializing a Cipher is
157: * equivalent to creating a new instance of that Cipher and initializing
158: * it.
159: *
160: * @param opmode the operation mode of this cipher (this is one of
161: * the following:
162: * <code>ENCRYPT_MODE</code> or <code>DECRYPT_MODE</code>)
163: * @param key the key
164: *
165: * @exception InvalidKeyException if the given key is inappropriate for
166: * initializing this cipher, or if this cipher is being initialized for
167: * decryption and requires algorithm parameters that cannot be
168: * determined from the given key, or if the given key has a keysize that
169: * exceeds the maximum allowable keysize.
170: */
171: public final void init(int opmode, Key key)
172: throws InvalidKeyException {
173:
174: try {
175: init(opmode, key, null);
176: } catch (InvalidAlgorithmParameterException e) {
177: throw new InvalidKeyException();
178: }
179: }
180:
181: /**
182: * Initializes this cipher with a key and a set of algorithm
183: * parameters.
184: *
185: * <p>The cipher is initialized for one of the following operations:
186: * encryption or decryption depending
187: * on the value of <code>opmode</code>.
188: *
189: * <p>If this cipher requires any algorithm parameters and
190: * <code>params</code> is null, the underlying cipher implementation is
191: * supposed to generate the required parameters itself (using
192: * provider-specific default or random values) if it is being
193: * initialized for encryption, and raise an
194: * <code>InvalidAlgorithmParameterException</code> if it is being
195: * initialized for decryption.
196: *
197: * <p>Note that when a Cipher object is initialized, it loses all
198: * previously-acquired state. In other words, initializing a Cipher is
199: * equivalent to creating a new instance of that Cipher and initializing
200: * it.
201: *
202: * @param opmode the operation mode of this cipher (this is one of the
203: * following:
204: * <code>ENCRYPT_MODE</code> or <code>DECRYPT_MODE</code>)
205: * @param key the encryption key
206: * @param params the algorithm parameters
207: *
208: * @exception InvalidKeyException if the given key is inappropriate for
209: * initializing this cipher, or its keysize exceeds the maximum allowable
210: * keysize.
211: * @exception InvalidAlgorithmParameterException if the given algorithm
212: * parameters are inappropriate for this cipher,
213: * or this cipher is being initialized for decryption and requires
214: * algorithm parameters and <code>params</code> is null, or the given
215: * algorithm parameters imply a cryptographic strength that would exceed
216: * the legal limits.
217: */
218: public final void init(int opmode, Key key,
219: AlgorithmParameterSpec params) throws InvalidKeyException,
220: InvalidAlgorithmParameterException {
221:
222: com.sun.midp.crypto.Key cipherKey;
223: com.sun.midp.crypto.CryptoParameter cryptoParameter;
224:
225: if (opmode == DECRYPT_MODE) {
226: opmode = com.sun.midp.crypto.Cipher.DECRYPT_MODE;
227: } else if (opmode == ENCRYPT_MODE) {
228: opmode = com.sun.midp.crypto.Cipher.ENCRYPT_MODE;
229: } else {
230: throw new IllegalArgumentException("Wrong operation mode");
231: }
232:
233: if (key instanceof SecretKeySpec) {
234: SecretKeySpec temp = (SecretKeySpec) key;
235: byte[] secret = key.getEncoded();
236:
237: cipherKey = new com.sun.midp.crypto.SecretKey(secret, 0,
238: secret.length, key.getAlgorithm());
239: } else if (key instanceof RSAPublicKey) {
240: RSAPublicKey temp = (RSAPublicKey) key;
241:
242: cipherKey = temp.getKey();
243: } else {
244: throw new InvalidKeyException();
245: }
246:
247: if (params == null) {
248: cryptoParameter = null;
249: } else if (params instanceof IvParameterSpec) {
250: byte[] iv = ((IvParameterSpec) params).getIV();
251:
252: cryptoParameter = new com.sun.midp.crypto.IvParameter(iv,
253: 0, iv.length);
254: } else {
255: throw new InvalidAlgorithmParameterException();
256: }
257:
258: try {
259: cipher.init(opmode, cipherKey, cryptoParameter);
260: } catch (com.sun.midp.crypto.InvalidKeyException e) {
261: throw new InvalidKeyException(e.getMessage());
262: } catch (com.sun.midp.crypto.InvalidAlgorithmParameterException e) {
263: throw new InvalidAlgorithmParameterException(e.getMessage());
264: }
265: }
266:
267: /**
268: * Continues a multiple-part encryption or decryption operation
269: * (depending on how this cipher was initialized), processing another data
270: * part.
271: *
272: * <p>The first <code>inputLen</code> bytes in the <code>input</code>
273: * buffer, starting at <code>inputOffset</code> inclusive, are processed,
274: * and the result is stored in the <code>output</code> buffer, starting at
275: * <code>outputOffset</code> inclusive.
276: *
277: * <p>If the <code>output</code> buffer is too small to hold the result,
278: * a <code>ShortBufferException</code> is thrown. In this case, repeat this
279: * call with a larger output buffer.
280: *
281: * <p>If <code>inputLen</code> is zero, this method returns
282: * a length of zero.
283: *
284: * <p>Note: this method should be copy-safe, which means the
285: * <code>input</code> and <code>output</code> buffers can reference
286: * the same byte array and no unprocessed input data is overwritten
287: * when the result is copied into the output buffer.
288: *
289: * @param input the input buffer
290: * @param inputOffset the offset in <code>input</code> where the input
291: * starts
292: * @param inputLen the input length
293: * @param output the buffer for the result
294: * @param outputOffset the offset in <code>output</code> where the result
295: * is stored
296: *
297: * @return the number of bytes stored in <code>output</code>
298: *
299: * @exception IllegalStateException if this cipher is in a wrong state
300: * (e.g., has not been initialized)
301: * @exception ShortBufferException if the given output buffer is too small
302: * to hold the result
303: */
304: public final int update(byte[] input, int inputOffset,
305: int inputLen, byte[] output, int outputOffset)
306: throws IllegalStateException, ShortBufferException {
307:
308: try {
309: return cipher.update(input, inputOffset, inputLen, output,
310: outputOffset);
311: } catch (com.sun.midp.crypto.ShortBufferException e) {
312: throw new ShortBufferException(e.getMessage());
313: }
314: }
315:
316: /**
317: * Encrypts or decrypts data in a single-part operation, or finishes a
318: * multiple-part operation. The data is encrypted or decrypted,
319: * depending on how this cipher was initialized.
320: *
321: * <p>The first <code>inputLen</code> bytes in the <code>input</code>
322: * buffer, starting at <code>inputOffset</code> inclusive, and any input
323: * bytes that may have been buffered during a previous
324: * <code>update</code> operation, are processed, with padding
325: * (if requested) being applied.
326: * The result is stored in the <code>output</code> buffer, starting at
327: * <code>outputOffset</code> inclusive.
328: *
329: * <p>If the <code>output</code> buffer is too small to hold the result,
330: * a <code>ShortBufferException</code> is thrown. In this case, repeat this
331: * call with a larger output buffer.
332: *
333: * <p>Upon finishing, this method resets this cipher object to the state
334: * it was in when previously initialized via a call to <code>init</code>.
335: * That is, the object is reset and available to encrypt or decrypt
336: * (depending on the operation mode that was specified in the call to
337: * <code>init</code>) more data.
338: *
339: * <p>Note: if any exception is thrown, this cipher object may need to
340: * be reset before it can be used again.
341: *
342: * <p>Note: this method should be copy-safe, which means the
343: * <code>input</code> and <code>output</code> buffers can reference
344: * the same byte array and no unprocessed input data is overwritten
345: * when the result is copied into the output buffer.
346: *
347: * @param input the input buffer
348: * @param inputOffset the offset in <code>input</code> where the input
349: * starts
350: * @param inputLen the input length
351: * @param output the buffer for the result
352: * @param outputOffset the offset in <code>output</code> where the result
353: * is stored
354: *
355: * @return the number of bytes stored in <code>output</code>
356: *
357: * @exception IllegalStateException if this cipher is in a wrong state
358: * (e.g., has not been initialized)
359: * @exception IllegalBlockSizeException if this cipher is a block cipher,
360: * no padding has been requested (only in encryption mode), and the total
361: * input length of the data processed by this cipher is not a multiple of
362: * block size
363: * @exception ShortBufferException if the given output buffer is too small
364: * to hold the result
365: * @exception BadPaddingException if this cipher is in decryption mode,
366: * and (un)padding has been requested, but the decrypted data is not
367: * bounded by the appropriate padding bytes
368: */
369: public final int doFinal(byte[] input, int inputOffset,
370: int inputLen, byte[] output, int outputOffset)
371: throws IllegalStateException, ShortBufferException,
372: IllegalBlockSizeException, BadPaddingException {
373:
374: try {
375: return cipher.doFinal(input, inputOffset, inputLen, output,
376: outputOffset);
377: } catch (com.sun.midp.crypto.ShortBufferException e) {
378: throw new ShortBufferException(e.getMessage());
379: } catch (com.sun.midp.crypto.IllegalBlockSizeException e) {
380: throw new IllegalBlockSizeException(e.getMessage());
381: } catch (com.sun.midp.crypto.BadPaddingException e) {
382: throw new BadPaddingException(e.getMessage());
383: }
384: }
385:
386: /**
387: * Returns the initialization vector (IV) in a new buffer.
388: * This is useful in the case where a random IV was created.
389: * @return the initialization vector in a new buffer,
390: * or <code>null</code> if the underlying algorithm does
391: * not use an IV, or if the IV has not yet been set.
392: */
393: public final byte[] getIV() {
394: return cipher.getIV();
395: }
396: }
|