Path: blob/master/src/java.base/share/classes/com/sun/crypto/provider/DESedeCipher.java
41161 views
/*1* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.crypto.provider;2627import java.security.*;28import java.security.spec.*;29import java.util.Arrays;30import javax.crypto.*;31import javax.crypto.spec.*;3233/**34* This class implements the DESede algorithm (DES-EDE, tripleDES) in35* its various modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>,36* <code>CBC</code>, <code>PCBC</code>) and padding schemes37* (<code>PKCS5Padding</code>, <code>NoPadding</code>,38* <code>ISO10126Padding</code>).39*40* @author Gigi Ankeny41*42*43* @see DESCipher44*/4546public final class DESedeCipher extends CipherSpi {4748/*49* internal CipherCore object which does the real work.50*/51private CipherCore core = null;5253/**54* Creates an instance of DESede cipher with default ECB mode and55* PKCS5Padding.56*/57public DESedeCipher() {58core = new CipherCore(new DESedeCrypt(), DESConstants.DES_BLOCK_SIZE);59}6061/**62* Sets the mode of this cipher.63*64* @param mode the cipher mode65*66* @exception NoSuchAlgorithmException if the requested cipher mode does67* not exist68*/69protected void engineSetMode(String mode)70throws NoSuchAlgorithmException {71core.setMode(mode);72}7374/**75* Sets the padding mechanism of this cipher.76*77* @param paddingScheme the padding mechanism78*79* @exception NoSuchPaddingException if the requested padding mechanism80* does not exist81*/82protected void engineSetPadding(String paddingScheme)83throws NoSuchPaddingException {84core.setPadding(paddingScheme);85}8687/**88* Returns the block size (in bytes).89*90* @return the block size (in bytes), or 0 if the underlying algorithm is91* not a block cipher92*/93protected int engineGetBlockSize() {94return DESConstants.DES_BLOCK_SIZE;95}9697/**98* Returns the length in bytes that an output buffer would need to be in99* order to hold the result of the next <code>update</code> or100* <code>doFinal</code> operation, given the input length101* <code>inputLen</code> (in bytes).102*103* <p>This call takes into account any unprocessed (buffered) data from a104* previous <code>update</code> call, and padding.105*106* <p>The actual output length of the next <code>update</code> or107* <code>doFinal</code> call may be smaller than the length returned by108* this method.109*110* @param inputLen the input length (in bytes)111*112* @return the required output buffer size (in bytes)113*/114protected int engineGetOutputSize(int inputLen) {115return core.getOutputSize(inputLen);116}117118/**119* Returns the initialization vector (IV) in a new buffer.120*121* <p>This is useful in the case where a random IV has been created122* (see <a href = "#init">init</a>),123* or in the context of password-based encryption or124* decryption, where the IV is derived from a user-provided password.125*126* @return the initialization vector in a new buffer, or null if the127* underlying algorithm does not use an IV, or if the IV has not yet128* been set.129*/130protected byte[] engineGetIV() {131return core.getIV();132}133134/**135* Initializes this cipher with a key and a source of randomness.136*137* <p>The cipher is initialized for one of the following four operations:138* encryption, decryption, key wrapping or key unwrapping, depending on139* the value of <code>opmode</code>.140*141* <p>If this cipher requires an initialization vector (IV), it will get142* it from <code>random</code>.143* This behaviour should only be used in encryption or key wrapping144* mode, however.145* When initializing a cipher that requires an IV for decryption or146* key unwrapping, the IV147* (same IV that was used for encryption or key wrapping) must be provided148* explicitly as a149* parameter, in order to get the correct result.150*151* <p>This method also cleans existing buffer and other related state152* information.153*154* @param opmode the operation mode of this cipher (this is one of155* the following:156* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,157* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)158* @param key the secret key159* @param random the source of randomness160*161* @exception InvalidKeyException if the given key is inappropriate for162* initializing this cipher163*/164protected void engineInit(int opmode, Key key, SecureRandom random)165throws InvalidKeyException {166core.init(opmode, key, random);167}168169/**170* Initializes this cipher with a key, a set of171* algorithm parameters, and a source of randomness.172*173* <p>The cipher is initialized for one of the following four operations:174* encryption, decryption, key wrapping or key unwrapping, depending on175* the value of <code>opmode</code>.176*177* <p>If this cipher (including its underlying feedback or padding scheme)178* requires any random bytes, it will get them from <code>random</code>.179*180* @param opmode the operation mode of this cipher (this is one of181* the following:182* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,183* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)184* @param key the encryption key185* @param params the algorithm parameters186* @param random the source of randomness187*188* @exception InvalidKeyException if the given key is inappropriate for189* initializing this cipher190* @exception InvalidAlgorithmParameterException if the given algorithm191* parameters are inappropriate for this cipher192*/193protected void engineInit(int opmode, Key key,194AlgorithmParameterSpec params,195SecureRandom random)196throws InvalidKeyException, InvalidAlgorithmParameterException {197core.init(opmode, key, params, random);198}199200protected void engineInit(int opmode, Key key,201AlgorithmParameters params,202SecureRandom random)203throws InvalidKeyException, InvalidAlgorithmParameterException {204core.init(opmode, key, params, random);205}206207/**208* Continues a multiple-part encryption or decryption operation209* (depending on how this cipher was initialized), processing another data210* part.211*212* <p>The first <code>inputLen</code> bytes in the <code>input</code>213* buffer, starting at <code>inputOffset</code>, are processed, and the214* result is stored in a new buffer.215*216* @param input the input buffer217* @param inputOffset the offset in <code>input</code> where the input218* starts219* @param inputLen the input length220*221* @return the new buffer with the result222*223* @exception IllegalStateException if this cipher is in a wrong state224* (e.g., has not been initialized)225*/226protected byte[] engineUpdate(byte[] input, int inputOffset,227int inputLen) {228return core.update(input, inputOffset, inputLen);229}230231/**232* Continues a multiple-part encryption or decryption operation233* (depending on how this cipher was initialized), processing another data234* 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 the238* result is stored in the <code>output</code> buffer, starting at239* <code>outputOffset</code>.240*241* @param input the input buffer242* @param inputOffset the offset in <code>input</code> where the input243* starts244* @param inputLen the input length245* @param output the buffer for the result246* @param outputOffset the offset in <code>output</code> where the result247* is stored248*249* @return the number of bytes stored in <code>output</code>250*251* @exception ShortBufferException if the given output buffer is too small252* to hold the result253*/254protected int engineUpdate(byte[] input, int inputOffset, int inputLen,255byte[] output, int outputOffset)256throws ShortBufferException {257return core.update(input, inputOffset, inputLen, output,258outputOffset);259}260261/**262* Encrypts or decrypts data in a single-part operation,263* or finishes a multiple-part operation.264* The data is encrypted or decrypted, depending on how this cipher was265* initialized.266*267* <p>The first <code>inputLen</code> bytes in the <code>input</code>268* buffer, starting at <code>inputOffset</code>, and any input bytes that269* may have been buffered during a previous <code>update</code> operation,270* are processed, with padding (if requested) being applied.271* The result is stored in a new buffer.272*273* <p>The cipher is reset to its initial state (uninitialized) after this274* call.275*276* @param input the input buffer277* @param inputOffset the offset in <code>input</code> where the input278* starts279* @param inputLen the input length280*281* @return the new buffer with the result282*283* @exception IllegalBlockSizeException if this cipher is a block cipher,284* no padding has been requested (only in encryption mode), and the total285* input length of the data processed by this cipher is not a multiple of286* block size287* @exception BadPaddingException if this cipher is in decryption mode,288* and (un)padding has been requested, but the decrypted data is not289* bounded by the appropriate padding bytes290*/291protected byte[] engineDoFinal(byte[] input, int inputOffset,292int inputLen)293throws IllegalBlockSizeException, BadPaddingException {294return core.doFinal(input, inputOffset, inputLen);295}296297/**298* Encrypts or decrypts data in a single-part operation,299* or finishes a multiple-part operation.300* The data is encrypted or decrypted, depending on how this cipher was301* initialized.302*303* <p>The first <code>inputLen</code> bytes in the <code>input</code>304* buffer, starting at <code>inputOffset</code>, and any input bytes that305* may have been buffered during a previous <code>update</code> operation,306* are processed, with padding (if requested) being applied.307* The result is stored in the <code>output</code> buffer, starting at308* <code>outputOffset</code>.309*310* <p>The cipher is reset to its initial state (uninitialized) after this311* call.312*313* @param input the input buffer314* @param inputOffset the offset in <code>input</code> where the input315* starts316* @param inputLen the input length317* @param output the buffer for the result318* @param outputOffset the offset in <code>output</code> where the result319* is stored320*321* @return the number of bytes stored in <code>output</code>322*323* @exception IllegalBlockSizeException if this cipher is a block cipher,324* no padding has been requested (only in encryption mode), and the total325* input length of the data processed by this cipher is not a multiple of326* block size327* @exception ShortBufferException if the given output buffer is too small328* to hold the result329* @exception BadPaddingException if this cipher is in decryption mode,330* and (un)padding has been requested, but the decrypted data is not331* bounded by the appropriate padding bytes332*/333protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,334byte[] output, int outputOffset)335throws IllegalBlockSizeException, ShortBufferException,336BadPaddingException {337return core.doFinal(input, inputOffset, inputLen, output,338outputOffset);339}340341/**342* Returns the parameters used with this cipher.343*344* <p>The returned parameters may be the same that were used to initialize345* this cipher, or may contain the default set of parameters or a set of346* randomly generated parameters used by the underlying cipher347* implementation (provided that the underlying cipher implementation348* uses a default set of parameters or creates new parameters if it needs349* parameters but was not initialized with any).350*351* @return the parameters used with this cipher, or null if this cipher352* does not use any parameters.353*/354protected AlgorithmParameters engineGetParameters() {355return core.getParameters("DESede");356}357358/**359* Returns the key size of the given key object.360*361* @param key the key object.362*363* @return the "effective" key size of the given key object.364*365* @exception InvalidKeyException if <code>key</code> is invalid.366*/367protected int engineGetKeySize(Key key) throws InvalidKeyException {368byte[] encoded = key.getEncoded();369Arrays.fill(encoded, (byte)0);370if (encoded.length != 24) {371throw new InvalidKeyException("Invalid key length: " +372encoded.length + " bytes");373}374// Return the effective key length375return 112;376}377378/**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 block386* cipher, no padding has been requested, and the length of the387* encoding of the key to be wrapped is not a388* multiple of the block size.389*390* @exception InvalidKeyException if it is impossible or unsafe to391* wrap the key with this cipher (e.g., a hardware protected key is392* being passed to a software only cipher).393*/394protected byte[] engineWrap(Key key)395throws IllegalBlockSizeException, InvalidKeyException {396return core.wrap(key);397}398399/**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 providers413* can create keys of type <code>wrappedKeyType</code> for the414* <code>wrappedKeyAlgorithm</code>.415*416* @exception InvalidKeyException if <code>wrappedKey</code> does not417* represent a wrapped key of type <code>wrappedKeyType</code> for418* the <code>wrappedKeyAlgorithm</code>.419*/420protected Key engineUnwrap(byte[] wrappedKey,421String wrappedKeyAlgorithm,422int wrappedKeyType)423throws InvalidKeyException, NoSuchAlgorithmException {424return core.unwrap(wrappedKey, wrappedKeyAlgorithm,425wrappedKeyType);426}427}428429430