src/java.base/share/classes/com/sun/crypto/provider/PBEWithMD5AndDESCipher.java
changeset 47216 71c04702a3d5
parent 32003 acb12269398a
child 59024 b046ba510bbc
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package com.sun.crypto.provider;
       
    27 
       
    28 import java.io.UnsupportedEncodingException;
       
    29 import java.security.*;
       
    30 import java.security.spec.*;
       
    31 import javax.crypto.*;
       
    32 import javax.crypto.spec.*;
       
    33 
       
    34 /**
       
    35  * This class represents password-based encryption as defined by the PKCS #5
       
    36  * standard.
       
    37  * The particular algorithm implemented is pbeWithMD5AndDES-CBC.
       
    38  * Padding is done as described in PKCS #5.
       
    39  *
       
    40  * @author Jan Luehe
       
    41  *
       
    42  *
       
    43  * @see javax.crypto.Cipher
       
    44  */
       
    45 public final class PBEWithMD5AndDESCipher extends CipherSpi {
       
    46 
       
    47     // the encapsulated DES cipher
       
    48     private PBES1Core core;
       
    49 
       
    50     /**
       
    51      * Creates an instance of this cipher, and initializes its mode (CBC) and
       
    52      * padding (PKCS5).
       
    53      *
       
    54      * @exception NoSuchAlgorithmException if the required cipher mode (CBC) is
       
    55      * unavailable
       
    56      * @exception NoSuchPaddingException if the required padding mechanism
       
    57      * (PKCS5Padding) is unavailable
       
    58      */
       
    59     public PBEWithMD5AndDESCipher()
       
    60         throws NoSuchAlgorithmException, NoSuchPaddingException {
       
    61         core = new PBES1Core("DES");
       
    62     }
       
    63 
       
    64     /**
       
    65      * Sets the mode of this cipher. This algorithm can only be run in CBC
       
    66      * mode.
       
    67      *
       
    68      * @param mode the cipher mode
       
    69      *
       
    70      * @exception NoSuchAlgorithmException if the requested cipher mode is
       
    71      * invalid
       
    72      */
       
    73     protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
       
    74         if ((mode != null) && (!mode.equalsIgnoreCase("CBC"))) {
       
    75             throw new NoSuchAlgorithmException("Invalid cipher mode: " + mode);
       
    76         }
       
    77     }
       
    78 
       
    79      /**
       
    80      * Sets the padding mechanism of this cipher. This algorithm only uses
       
    81      * PKCS #5 padding.
       
    82      *
       
    83      * @param paddingScheme the padding mechanism
       
    84      *
       
    85      * @exception NoSuchPaddingException if the requested padding mechanism
       
    86      * is invalid
       
    87      */
       
    88     protected void engineSetPadding(String paddingScheme)
       
    89         throws NoSuchPaddingException
       
    90     {
       
    91         if ((paddingScheme != null) &&
       
    92             (!paddingScheme.equalsIgnoreCase("PKCS5Padding"))) {
       
    93             throw new NoSuchPaddingException("Invalid padding scheme: " +
       
    94                                              paddingScheme);
       
    95         }
       
    96     }
       
    97 
       
    98     /**
       
    99      * Returns the block size (in bytes).
       
   100      *
       
   101      * @return the block size (in bytes)
       
   102      */
       
   103     protected int engineGetBlockSize() {
       
   104         return core.getBlockSize();
       
   105     }
       
   106 
       
   107     /**
       
   108      * Returns the length in bytes that an output buffer would need to be in
       
   109      * order to hold the result of the next <code>update</code> or
       
   110      * <code>doFinal</code> operation, given the input length
       
   111      * <code>inputLen</code> (in bytes).
       
   112      *
       
   113      * <p>This call takes into account any unprocessed (buffered) data from a
       
   114      * previous <code>update</code> call, and padding.
       
   115      *
       
   116      * <p>The actual output length of the next <code>update</code> or
       
   117      * <code>doFinal</code> call may be smaller than the length returned by
       
   118      * this method.
       
   119      *
       
   120      * @param inputLen the input length (in bytes)
       
   121      *
       
   122      * @return the required output buffer size (in bytes)
       
   123      *
       
   124      */
       
   125     protected int engineGetOutputSize(int inputLen) {
       
   126         return core.getOutputSize(inputLen);
       
   127     }
       
   128 
       
   129     /**
       
   130      * Returns the initialization vector (IV) in a new buffer.
       
   131      *
       
   132      * <p> This is useful in the case where a random IV has been created
       
   133      * (see <a href = "#init">init</a>),
       
   134      * or in the context of password-based encryption or
       
   135      * decryption, where the IV is derived from a user-supplied password.
       
   136      *
       
   137      * @return the initialization vector in a new buffer, or null if the
       
   138      * underlying algorithm does not use an IV, or if the IV has not yet
       
   139      * been set.
       
   140      */
       
   141     protected byte[] engineGetIV() {
       
   142         return core.getIV();
       
   143     }
       
   144 
       
   145     /**
       
   146      * Returns the parameters used with this cipher.
       
   147      *
       
   148      * <p>The returned parameters may be the same that were used to initialize
       
   149      * this cipher, or may contain the default set of parameters or a set of
       
   150      * randomly generated parameters used by the underlying cipher
       
   151      * implementation (provided that the underlying cipher implementation
       
   152      * uses a default set of parameters or creates new parameters if it needs
       
   153      * parameters but was not initialized with any).
       
   154      *
       
   155      * @return the parameters used with this cipher, or null if this cipher
       
   156      * does not use any parameters.
       
   157      */
       
   158     protected AlgorithmParameters engineGetParameters() {
       
   159         return core.getParameters();
       
   160     }
       
   161 
       
   162     /**
       
   163      * Initializes this cipher with a key and a source
       
   164      * of randomness.
       
   165      * The cipher is initialized for one of the following four operations:
       
   166      * encryption, decryption, key wrapping or key unwrapping, depending on
       
   167      * the value of <code>opmode</code>.
       
   168      *
       
   169      * <p>If this cipher (including its underlying feedback or padding scheme)
       
   170      * requires any random bytes, it will get them from <code>random</code>.
       
   171      *
       
   172      * @param opmode the operation mode of this cipher (this is one of
       
   173      * the following:
       
   174      * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>),
       
   175      * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
       
   176      * @param key the encryption key
       
   177      * @param random the source of randomness
       
   178      *
       
   179      * @exception InvalidKeyException if the given key is inappropriate for
       
   180      * initializing this cipher
       
   181      */
       
   182     protected void engineInit(int opmode, Key key, SecureRandom random)
       
   183         throws InvalidKeyException {
       
   184         try {
       
   185             engineInit(opmode, key, (AlgorithmParameterSpec) null, random);
       
   186         } catch (InvalidAlgorithmParameterException ie) {
       
   187             InvalidKeyException ike =
       
   188                 new InvalidKeyException("requires PBE parameters");
       
   189             ike.initCause(ie);
       
   190             throw ike;
       
   191         }
       
   192     }
       
   193 
       
   194     /**
       
   195      * Initializes this cipher with a key, a set of
       
   196      * algorithm parameters, and a source of randomness.
       
   197      * The cipher is initialized for one of the following four operations:
       
   198      * encryption, decryption, key wrapping or key unwrapping, depending on
       
   199      * the value of <code>opmode</code>.
       
   200      *
       
   201      * <p>If this cipher (including its underlying feedback or padding scheme)
       
   202      * requires any random bytes, it will get them from <code>random</code>.
       
   203      *
       
   204      * @param opmode the operation mode of this cipher (this is one of
       
   205      * the following:
       
   206      * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>),
       
   207      * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
       
   208      * @param key the encryption key
       
   209      * @param params the algorithm parameters
       
   210      * @param random the source of randomness
       
   211      *
       
   212      * @exception InvalidKeyException if the given key is inappropriate for
       
   213      * initializing this cipher
       
   214      * @exception InvalidAlgorithmParameterException if the given algorithm
       
   215      * parameters are inappropriate for this cipher
       
   216      */
       
   217     protected void engineInit(int opmode, Key key,
       
   218                               AlgorithmParameterSpec params,
       
   219                               SecureRandom random)
       
   220         throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   221         core.init(opmode, key, params, random);
       
   222     }
       
   223 
       
   224     protected void engineInit(int opmode, Key key,
       
   225                               AlgorithmParameters params,
       
   226                               SecureRandom random)
       
   227         throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   228         core.init(opmode, key, params, random);
       
   229     }
       
   230 
       
   231     /**
       
   232      * Continues a multiple-part encryption or decryption operation
       
   233      * (depending on how this cipher was initialized), processing another data
       
   234      * part.
       
   235      *
       
   236      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
       
   237      * buffer, starting at <code>inputOffset</code>, are processed, and the
       
   238      * result is stored in a new buffer.
       
   239      *
       
   240      * @param input the input buffer
       
   241      * @param inputOffset the offset in <code>input</code> where the input
       
   242      * starts
       
   243      * @param inputLen the input length
       
   244      *
       
   245      * @return the new buffer with the result
       
   246      *
       
   247      */
       
   248     protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen)
       
   249     {
       
   250         return core.update(input, inputOffset, inputLen);
       
   251     }
       
   252 
       
   253     /**
       
   254      * Continues a multiple-part encryption or decryption operation
       
   255      * (depending on how this cipher was initialized), processing another data
       
   256      * part.
       
   257      *
       
   258      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
       
   259      * buffer, starting at <code>inputOffset</code>, are processed, and the
       
   260      * result is stored in the <code>output</code> buffer, starting at
       
   261      * <code>outputOffset</code>.
       
   262      *
       
   263      * @param input the input buffer
       
   264      * @param inputOffset the offset in <code>input</code> where the input
       
   265      * starts
       
   266      * @param inputLen the input length
       
   267      * @param output the buffer for the result
       
   268      * @param outputOffset the offset in <code>output</code> where the result
       
   269      * is stored
       
   270      *
       
   271      * @return the number of bytes stored in <code>output</code>
       
   272      *
       
   273      * @exception ShortBufferException if the given output buffer is too small
       
   274      * to hold the result
       
   275      */
       
   276     protected int engineUpdate(byte[] input, int inputOffset, int inputLen,
       
   277                                byte[] output, int outputOffset)
       
   278         throws ShortBufferException
       
   279     {
       
   280         return core.update(input, inputOffset, inputLen,
       
   281                            output, outputOffset);
       
   282     }
       
   283 
       
   284     /**
       
   285      * Encrypts or decrypts data in a single-part operation,
       
   286      * or finishes a multiple-part operation.
       
   287      * The data is encrypted or decrypted, depending on how this cipher was
       
   288      * initialized.
       
   289      *
       
   290      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
       
   291      * buffer, starting at <code>inputOffset</code>, and any input bytes that
       
   292      * may have been buffered during a previous <code>update</code> operation,
       
   293      * are processed, with padding (if requested) being applied.
       
   294      * The result is stored in a new buffer.
       
   295      *
       
   296      * <p>The cipher is reset to its initial state (uninitialized) after this
       
   297      * call.
       
   298      *
       
   299      * @param input the input buffer
       
   300      * @param inputOffset the offset in <code>input</code> where the input
       
   301      * starts
       
   302      * @param inputLen the input length
       
   303      *
       
   304      * @return the new buffer with the result
       
   305      *
       
   306      * @exception IllegalBlockSizeException if this cipher is a block cipher,
       
   307      * no padding has been requested (only in encryption mode), and the total
       
   308      * input length of the data processed by this cipher is not a multiple of
       
   309      * block size
       
   310      * @exception BadPaddingException if decrypting and padding is chosen,
       
   311      * but the last input data does not have proper padding bytes.
       
   312      */
       
   313     protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
       
   314         throws IllegalBlockSizeException, BadPaddingException
       
   315     {
       
   316         return core.doFinal(input, inputOffset, inputLen);
       
   317     }
       
   318 
       
   319     /**
       
   320      * Encrypts or decrypts data in a single-part operation,
       
   321      * or finishes a multiple-part operation.
       
   322      * The data is encrypted or decrypted, depending on how this cipher was
       
   323      * initialized.
       
   324      *
       
   325      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
       
   326      * buffer, starting at <code>inputOffset</code>, and any input bytes that
       
   327      * may have been buffered during a previous <code>update</code> operation,
       
   328      * are processed, with padding (if requested) being applied.
       
   329      * The result is stored in the <code>output</code> buffer, starting at
       
   330      * <code>outputOffset</code>.
       
   331      *
       
   332      * <p>The cipher is reset to its initial state (uninitialized) after this
       
   333      * call.
       
   334      *
       
   335      * @param input the input buffer
       
   336      * @param inputOffset the offset in <code>input</code> where the input
       
   337      * starts
       
   338      * @param inputLen the input length
       
   339      * @param output the buffer for the result
       
   340      * @param outputOffset the offset in <code>output</code> where the result
       
   341      * is stored
       
   342      *
       
   343      * @return the number of bytes stored in <code>output</code>
       
   344      *
       
   345      * @exception IllegalBlockSizeException if this cipher is a block cipher,
       
   346      * no padding has been requested (only in encryption mode), and the total
       
   347      * input length of the data processed by this cipher is not a multiple of
       
   348      * block size
       
   349      * @exception ShortBufferException if the given output buffer is too small
       
   350      * to hold the result
       
   351      * @exception BadPaddingException if decrypting and padding is chosen,
       
   352      * but the last input data does not have proper padding bytes.
       
   353      */
       
   354     protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,
       
   355                                 byte[] output, int outputOffset)
       
   356         throws ShortBufferException, IllegalBlockSizeException,
       
   357                BadPaddingException
       
   358     {
       
   359         return core.doFinal(input, inputOffset, inputLen,
       
   360                             output, outputOffset);
       
   361     }
       
   362 
       
   363     /**
       
   364      *  Returns the key size of the given key object.
       
   365      *
       
   366      * @param key the key object.
       
   367      *
       
   368      * @return the key size of the given key object.
       
   369      *
       
   370      * @exception InvalidKeyException if <code>key</code> is invalid.
       
   371      */
       
   372     protected int engineGetKeySize(Key key) throws InvalidKeyException {
       
   373         // Always returns 56 since the encryption key
       
   374         // is a DES key.
       
   375         return 56;
       
   376     }
       
   377 
       
   378     /**
       
   379      * Wrap a key.
       
   380      *
       
   381      * @param key the key to be wrapped.
       
   382      *
       
   383      * @return the wrapped key.
       
   384      *
       
   385      * @exception IllegalBlockSizeException if this cipher is a block
       
   386      * cipher, no padding has been requested, and the length of the
       
   387      * encoding of the key to be wrapped is not a
       
   388      * multiple of the block size.
       
   389      *
       
   390      * @exception InvalidKeyException if it is impossible or unsafe to
       
   391      * wrap the key with this cipher (e.g., a hardware protected key is
       
   392      * being passed to a software only cipher).
       
   393      */
       
   394     protected byte[] engineWrap(Key key)
       
   395         throws IllegalBlockSizeException, InvalidKeyException {
       
   396         return core.wrap(key);
       
   397     }
       
   398 
       
   399     /**
       
   400      * Unwrap a previously wrapped key.
       
   401      *
       
   402      * @param wrappedKey the key to be unwrapped.
       
   403      *
       
   404      * @param wrappedKeyAlgorithm the algorithm the wrapped key is for.
       
   405      *
       
   406      * @param wrappedKeyType the type of the wrapped key.
       
   407      * This is one of <code>Cipher.SECRET_KEY</code>,
       
   408      * <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.
       
   409      *
       
   410      * @return the unwrapped key.
       
   411      *
       
   412      * @exception NoSuchAlgorithmException if no installed providers
       
   413      * can create keys of type <code>wrappedKeyType</code> for the
       
   414      * <code>wrappedKeyAlgorithm</code>.
       
   415      *
       
   416      * @exception InvalidKeyException if <code>wrappedKey</code> does not
       
   417      * represent a wrapped key of type <code>wrappedKeyType</code> for
       
   418      * the <code>wrappedKeyAlgorithm</code>.
       
   419      */
       
   420     protected Key engineUnwrap(byte[] wrappedKey,
       
   421                                String wrappedKeyAlgorithm,
       
   422                                int wrappedKeyType)
       
   423         throws InvalidKeyException, NoSuchAlgorithmException {
       
   424         byte[] encodedKey;
       
   425 
       
   426         return core.unwrap(wrappedKey, wrappedKeyAlgorithm,
       
   427                            wrappedKeyType);
       
   428     }
       
   429 }