jdk/src/share/classes/com/sun/crypto/provider/BlowfishCipher.java
changeset 2 90ce3da70b43
child 3353 ddbd63234844
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 1998-2007 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package com.sun.crypto.provider;
       
    27 
       
    28 import java.security.*;
       
    29 import java.security.spec.*;
       
    30 import sun.security.util.*;
       
    31 import javax.crypto.*;
       
    32 import javax.crypto.spec.*;
       
    33 import javax.crypto.BadPaddingException;
       
    34 
       
    35 /**
       
    36  * This class implements the Blowfish algorithm in its various modes
       
    37  * (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>, <code>CBC</code>,
       
    38  * <code>PCBC</code>) and padding schemes (<code>PKCS5Padding</code>,
       
    39  * <code>NoPadding</code>, <code>ISO10126Padding</code>).
       
    40  *
       
    41  * <p> Blowfish is a 64-bit block cipher with a variable-length key.
       
    42  *
       
    43  * @author Jan Luehe
       
    44  *
       
    45  *
       
    46  * @see BlowfishCrypt
       
    47  * @see CipherBlockChaining
       
    48  * @see ElectronicCodeBook
       
    49  * @see CipherFeedback
       
    50  * @see OutputFeedback
       
    51  */
       
    52 
       
    53 public final class BlowfishCipher extends CipherSpi {
       
    54 
       
    55     /*
       
    56      * internal CipherCore object which does the real work.
       
    57      */
       
    58     private CipherCore core = null;
       
    59 
       
    60     /**
       
    61      * Creates an instance of Blowfish cipher with default ECB mode and
       
    62      * PKCS5Padding.
       
    63      *
       
    64      * @exception SecurityException if this constructor fails to verify
       
    65      * its own integrity
       
    66      */
       
    67     public BlowfishCipher() {
       
    68         SunJCE.ensureIntegrity(getClass());
       
    69         core = new CipherCore(new BlowfishCrypt(),
       
    70                               BlowfishConstants.BLOWFISH_BLOCK_SIZE);
       
    71     }
       
    72 
       
    73     /**
       
    74      * Sets the mode of this cipher.
       
    75      *
       
    76      * @param mode the cipher mode
       
    77      *
       
    78      * @exception NoSuchAlgorithmException if the requested cipher mode does
       
    79      * not exist
       
    80      */
       
    81     protected void engineSetMode(String mode)
       
    82         throws NoSuchAlgorithmException {
       
    83         core.setMode(mode);
       
    84     }
       
    85 
       
    86     /**
       
    87      * Sets the padding mechanism of this cipher.
       
    88      *
       
    89      * @param padding the padding mechanism
       
    90      *
       
    91      * @exception NoSuchPaddingException if the requested padding mechanism
       
    92      * does not exist
       
    93      */
       
    94     protected void engineSetPadding(String paddingScheme)
       
    95         throws NoSuchPaddingException {
       
    96         core.setPadding(paddingScheme);
       
    97     }
       
    98 
       
    99     /**
       
   100      * Returns the block size (in bytes).
       
   101      *
       
   102      * @return the block size (in bytes), or 0 if the underlying algorithm is
       
   103      * not a block cipher
       
   104      */
       
   105     protected int engineGetBlockSize() {
       
   106         return BlowfishConstants.BLOWFISH_BLOCK_SIZE;
       
   107     }
       
   108 
       
   109     /**
       
   110      * Returns the length in bytes that an output buffer would need to be in
       
   111      * order to hold the result of the next <code>update</code> or
       
   112      * <code>doFinal</code> operation, given the input length
       
   113      * <code>inputLen</code> (in bytes).
       
   114      *
       
   115      * <p>This call takes into account any unprocessed (buffered) data from a
       
   116      * previous <code>update</code> call, and padding.
       
   117      *
       
   118      * <p>The actual output length of the next <code>update</code> or
       
   119      * <code>doFinal</code> call may be smaller than the length returned by
       
   120      * this method.
       
   121      *
       
   122      * @param inputLen the input length (in bytes)
       
   123      *
       
   124      * @return the required output buffer size (in bytes)
       
   125      */
       
   126     protected int engineGetOutputSize(int inputLen) {
       
   127         return core.getOutputSize(inputLen);
       
   128     }
       
   129 
       
   130     /**
       
   131      * Returns the initialization vector (IV) in a new buffer.
       
   132      *
       
   133      * <p>This is useful in the case where a random IV has been created
       
   134      * (see <a href = "#init">init</a>),
       
   135      * or in the context of password-based encryption or
       
   136      * decryption, where the IV is derived from a user-supplied password.
       
   137      *
       
   138      * @return the initialization vector in a new buffer, or null if the
       
   139      * underlying algorithm does not use an IV, or if the IV has not yet
       
   140      * been set.
       
   141      */
       
   142     protected byte[] engineGetIV() {
       
   143         return core.getIV();
       
   144     }
       
   145 
       
   146     /**
       
   147      * Returns the parameters used with this cipher.
       
   148      *
       
   149      * <p>The returned parameters may be the same that were used to initialize
       
   150      * this cipher, or may contain the default set of parameters or a set of
       
   151      * randomly generated parameters used by the underlying cipher
       
   152      * implementation (provided that the underlying cipher implementation
       
   153      * uses a default set of parameters or creates new parameters if it needs
       
   154      * parameters but was not initialized with any).
       
   155      *
       
   156      * @return the parameters used with this cipher, or null if this cipher
       
   157      * does not use any parameters.
       
   158      */
       
   159     protected AlgorithmParameters engineGetParameters() {
       
   160         return core.getParameters("Blowfish");
       
   161     }
       
   162 
       
   163     /**
       
   164      * Initializes this cipher with a key and a source of randomness.
       
   165      *
       
   166      * <p>The cipher is initialized for one of the following four operations:
       
   167      * encryption, decryption, key wrapping or key unwrapping, depending on
       
   168      * the value of <code>opmode</code>.
       
   169      *
       
   170      * <p>If this cipher requires an initialization vector (IV), it will get
       
   171      * it from <code>random</code>.
       
   172      * This behaviour should only be used in encryption or key wrapping
       
   173      * mode, however.
       
   174      * When initializing a cipher that requires an IV for decryption or
       
   175      * key unwrapping, the IV
       
   176      * (same IV that was used for encryption or key wrapping) must be provided
       
   177      * explicitly as a
       
   178      * parameter, in order to get the correct result.
       
   179      *
       
   180      * <p>This method also cleans existing buffer and other related state
       
   181      * information.
       
   182      *
       
   183      * @param opmode the operation mode of this cipher (this is one of
       
   184      * the following:
       
   185      * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
       
   186      * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
       
   187      * @param key the secret key
       
   188      * @param random the source of randomness
       
   189      *
       
   190      * @exception InvalidKeyException if the given key is inappropriate for
       
   191      * initializing this cipher
       
   192      */
       
   193     protected void engineInit(int opmode, Key key, SecureRandom random)
       
   194         throws InvalidKeyException {
       
   195         core.init(opmode, key, random);
       
   196     }
       
   197 
       
   198     /**
       
   199      * Initializes this cipher with a key, a set of
       
   200      * algorithm parameters, and a source of randomness.
       
   201      *
       
   202      * <p>The cipher is initialized for one of the following four operations:
       
   203      * encryption, decryption, key wrapping or key unwrapping, depending on
       
   204      * the value of <code>opmode</code>.
       
   205      *
       
   206      * <p>If this cipher (including its underlying feedback or padding scheme)
       
   207      * requires any random bytes, it will get them from <code>random</code>.
       
   208      *
       
   209      * @param opmode the operation mode of this cipher (this is one of
       
   210      * the following:
       
   211      * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
       
   212      * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
       
   213      * @param key the encryption key
       
   214      * @param params the algorithm parameters
       
   215      * @param random the source of randomness
       
   216      *
       
   217      * @exception InvalidKeyException if the given key is inappropriate for
       
   218      * initializing this cipher
       
   219      * @exception InvalidAlgorithmParameterException if the given algorithm
       
   220      * parameters are inappropriate for this cipher
       
   221      */
       
   222     protected void engineInit(int opmode, Key key,
       
   223                               AlgorithmParameterSpec params,
       
   224                               SecureRandom random)
       
   225         throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   226         core.init(opmode, key, params, random);
       
   227     }
       
   228 
       
   229     protected void engineInit(int opmode, Key key,
       
   230                               AlgorithmParameters params,
       
   231                               SecureRandom random)
       
   232         throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   233         core.init(opmode, key, params, random);
       
   234     }
       
   235 
       
   236     /**
       
   237      * Continues a multiple-part encryption or decryption operation
       
   238      * (depending on how this cipher was initialized), processing another data
       
   239      * part.
       
   240      *
       
   241      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
       
   242      * buffer, starting at <code>inputOffset</code>, are processed, and the
       
   243      * result is stored in a new buffer.
       
   244      *
       
   245      * @param input the input buffer
       
   246      * @param inputOffset the offset in <code>input</code> where the input
       
   247      * starts
       
   248      * @param inputLen the input length
       
   249      *
       
   250      * @return the new buffer with the result
       
   251      *
       
   252      * @exception IllegalStateException if this cipher is in a wrong state
       
   253      * (e.g., has not been initialized)
       
   254      */
       
   255     protected byte[] engineUpdate(byte[] input, int inputOffset,
       
   256                                   int inputLen) {
       
   257         return core.update(input, inputOffset, inputLen);
       
   258     }
       
   259 
       
   260     /**
       
   261      * Continues a multiple-part encryption or decryption operation
       
   262      * (depending on how this cipher was initialized), processing another data
       
   263      * part.
       
   264      *
       
   265      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
       
   266      * buffer, starting at <code>inputOffset</code>, are processed, and the
       
   267      * result is stored in the <code>output</code> buffer, starting at
       
   268      * <code>outputOffset</code>.
       
   269      *
       
   270      * @param input the input buffer
       
   271      * @param inputOffset the offset in <code>input</code> where the input
       
   272      * starts
       
   273      * @param inputLen the input length
       
   274      * @param output the buffer for the result
       
   275      * @param outputOffset the offset in <code>output</code> where the result
       
   276      * is stored
       
   277      *
       
   278      * @return the number of bytes stored in <code>output</code>
       
   279      *
       
   280      * @exception ShortBufferException if the given output buffer is too small
       
   281      * to hold the result
       
   282      */
       
   283     protected int engineUpdate(byte[] input, int inputOffset, int inputLen,
       
   284                                byte[] output, int outputOffset)
       
   285         throws ShortBufferException {
       
   286         return core.update(input, inputOffset, inputLen, output,
       
   287                            outputOffset);
       
   288     }
       
   289 
       
   290     /**
       
   291      * Encrypts or decrypts data in a single-part operation,
       
   292      * or finishes a multiple-part operation.
       
   293      * The data is encrypted or decrypted, depending on how this cipher was
       
   294      * initialized.
       
   295      *
       
   296      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
       
   297      * buffer, starting at <code>inputOffset</code>, and any input bytes that
       
   298      * may have been buffered during a previous <code>update</code> operation,
       
   299      * are processed, with padding (if requested) being applied.
       
   300      * The result is stored in a new buffer.
       
   301      *
       
   302      * <p>The cipher is reset to its initial state (uninitialized) after this
       
   303      * call.
       
   304      *
       
   305      * @param input the input buffer
       
   306      * @param inputOffset the offset in <code>input</code> where the input
       
   307      * starts
       
   308      * @param inputLen the input length
       
   309      *
       
   310      * @return the new buffer with the result
       
   311      *
       
   312      * @exception IllegalBlockSizeException if this cipher is a block cipher,
       
   313      * no padding has been requested (only in encryption mode), and the total
       
   314      * input length of the data processed by this cipher is not a multiple of
       
   315      * block size
       
   316      * @exception BadPaddingException if this cipher is in decryption mode,
       
   317      * and (un)padding has been requested, but the decrypted data is not
       
   318      * bounded by the appropriate padding bytes
       
   319      */
       
   320     protected byte[] engineDoFinal(byte[] input, int inputOffset,
       
   321                                    int inputLen)
       
   322         throws IllegalBlockSizeException, BadPaddingException {
       
   323         return core.doFinal(input, inputOffset, inputLen);
       
   324     }
       
   325 
       
   326     /**
       
   327      * Encrypts or decrypts data in a single-part operation,
       
   328      * or finishes a multiple-part operation.
       
   329      * The data is encrypted or decrypted, depending on how this cipher was
       
   330      * initialized.
       
   331      *
       
   332      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
       
   333      * buffer, starting at <code>inputOffset</code>, and any input bytes that
       
   334      * may have been buffered during a previous <code>update</code> operation,
       
   335      * are processed, with padding (if requested) being applied.
       
   336      * The result is stored in the <code>output</code> buffer, starting at
       
   337      * <code>outputOffset</code>.
       
   338      *
       
   339      * <p>The cipher is reset to its initial state (uninitialized) after this
       
   340      * call.
       
   341      *
       
   342      * @param input the input buffer
       
   343      * @param inputOffset the offset in <code>input</code> where the input
       
   344      * starts
       
   345      * @param inputLen the input length
       
   346      * @param output the buffer for the result
       
   347      * @param outputOffset the offset in <code>output</code> where the result
       
   348      * is stored
       
   349      *
       
   350      * @return the number of bytes stored in <code>output</code>
       
   351      *
       
   352      * @exception IllegalBlockSizeException if this cipher is a block cipher,
       
   353      * no padding has been requested (only in encryption mode), and the total
       
   354      * input length of the data processed by this cipher is not a multiple of
       
   355      * block size
       
   356      * @exception ShortBufferException if the given output buffer is too small
       
   357      * to hold the result
       
   358      * @exception BadPaddingException if this cipher is in decryption mode,
       
   359      * and (un)padding has been requested, but the decrypted data is not
       
   360      * bounded by the appropriate padding bytes
       
   361      */
       
   362     protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,
       
   363                                 byte[] output, int outputOffset)
       
   364         throws IllegalBlockSizeException, ShortBufferException,
       
   365                BadPaddingException {
       
   366         return core.doFinal(input, inputOffset, inputLen, output,
       
   367                             outputOffset);
       
   368     }
       
   369 
       
   370     /**
       
   371      *  Returns the key size of the given key object.
       
   372      *
       
   373      * @param key the key object.
       
   374      *
       
   375      * @return the key size of the given key object.
       
   376      *
       
   377      * @exception InvalidKeyException if <code>key</code> is invalid.
       
   378      */
       
   379     protected int engineGetKeySize(Key key) throws InvalidKeyException {
       
   380         return (key.getEncoded().length * 8);
       
   381     }
       
   382 
       
   383     /**
       
   384      * Wrap a key.
       
   385      *
       
   386      * @param key the key to be wrapped.
       
   387      *
       
   388      * @return the wrapped key.
       
   389      *
       
   390      * @exception IllegalBlockSizeException if this cipher is a block
       
   391      * cipher, no padding has been requested, and the length of the
       
   392      * encoding of the key to be wrapped is not a
       
   393      * multiple of the block size.
       
   394      *
       
   395      * @exception InvalidKeyException if it is impossible or unsafe to
       
   396      * wrap the key with this cipher (e.g., a hardware protected key is
       
   397      * being passed to a software only cipher).
       
   398      */
       
   399     protected byte[] engineWrap(Key key)
       
   400         throws IllegalBlockSizeException, InvalidKeyException {
       
   401         return core.wrap(key);
       
   402     }
       
   403 
       
   404     /**
       
   405      * Unwrap a previously wrapped key.
       
   406      *
       
   407      * @param wrappedKey the key to be unwrapped.
       
   408      *
       
   409      * @param wrappedKeyAlgorithm the algorithm the wrapped key is for.
       
   410      *
       
   411      * @param wrappedKeyType the type of the wrapped key.
       
   412      * This is one of <code>Cipher.SECRET_KEY</code>,
       
   413      * <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.
       
   414      *
       
   415      * @return the unwrapped key.
       
   416      *
       
   417      * @exception NoSuchAlgorithmException if no installed providers
       
   418      * can create keys of type <code>wrappedKeyType</code> for the
       
   419      * <code>wrappedKeyAlgorithm</code>.
       
   420      *
       
   421      * @exception InvalidKeyException if <code>wrappedKey</code> does not
       
   422      * represent a wrapped key of type <code>wrappedKeyType</code> for
       
   423      * the <code>wrappedKeyAlgorithm</code>.
       
   424      */
       
   425     protected Key engineUnwrap(byte[] wrappedKey,
       
   426                                      String wrappedKeyAlgorithm,
       
   427                                      int wrappedKeyType)
       
   428         throws InvalidKeyException, NoSuchAlgorithmException {
       
   429         return core.unwrap(wrappedKey, wrappedKeyAlgorithm,
       
   430                            wrappedKeyType);
       
   431     }
       
   432 }