Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/crypto/provider/DESedeCipher.java
38922 views
/*1* Copyright (c) 1997, 2010, 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 javax.crypto.*;30import javax.crypto.spec.*;3132/**33* This class implements the DESede algorithm (DES-EDE, tripleDES) in34* its various modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>,35* <code>CBC</code>, <code>PCBC</code>) and padding schemes36* (<code>PKCS5Padding</code>, <code>NoPadding</code>,37* <code>ISO10126Padding</code>).38*39* @author Gigi Ankeny40*41*42* @see DESCipher43*/4445public final class DESedeCipher extends CipherSpi {4647/*48* internal CipherCore object which does the real work.49*/50private CipherCore core = null;5152/**53* Creates an instance of DESede cipher with default ECB mode and54* PKCS5Padding.55*/56public DESedeCipher() {57core = new CipherCore(new DESedeCrypt(), DESConstants.DES_BLOCK_SIZE);58}5960/**61* Sets the mode of this cipher.62*63* @param mode the cipher mode64*65* @exception NoSuchAlgorithmException if the requested cipher mode does66* not exist67*/68protected void engineSetMode(String mode)69throws NoSuchAlgorithmException {70core.setMode(mode);71}7273/**74* Sets the padding mechanism of this cipher.75*76* @param paddingScheme the padding mechanism77*78* @exception NoSuchPaddingException if the requested padding mechanism79* does not exist80*/81protected void engineSetPadding(String paddingScheme)82throws NoSuchPaddingException {83core.setPadding(paddingScheme);84}8586/**87* Returns the block size (in bytes).88*89* @return the block size (in bytes), or 0 if the underlying algorithm is90* not a block cipher91*/92protected int engineGetBlockSize() {93return DESConstants.DES_BLOCK_SIZE;94}9596/**97* Returns the length in bytes that an output buffer would need to be in98* order to hold the result of the next <code>update</code> or99* <code>doFinal</code> operation, given the input length100* <code>inputLen</code> (in bytes).101*102* <p>This call takes into account any unprocessed (buffered) data from a103* previous <code>update</code> call, and padding.104*105* <p>The actual output length of the next <code>update</code> or106* <code>doFinal</code> call may be smaller than the length returned by107* this method.108*109* @param inputLen the input length (in bytes)110*111* @return the required output buffer size (in bytes)112*/113protected int engineGetOutputSize(int inputLen) {114return core.getOutputSize(inputLen);115}116117/**118* Returns the initialization vector (IV) in a new buffer.119*120* <p>This is useful in the case where a random IV has been created121* (see <a href = "#init">init</a>),122* or in the context of password-based encryption or123* decryption, where the IV is derived from a user-provided password.124*125* @return the initialization vector in a new buffer, or null if the126* underlying algorithm does not use an IV, or if the IV has not yet127* been set.128*/129protected byte[] engineGetIV() {130return core.getIV();131}132133/**134* Initializes this cipher with a key and a source of randomness.135*136* <p>The cipher is initialized for one of the following four operations:137* encryption, decryption, key wrapping or key unwrapping, depending on138* the value of <code>opmode</code>.139*140* <p>If this cipher requires an initialization vector (IV), it will get141* it from <code>random</code>.142* This behaviour should only be used in encryption or key wrapping143* mode, however.144* When initializing a cipher that requires an IV for decryption or145* key unwrapping, the IV146* (same IV that was used for encryption or key wrapping) must be provided147* explicitly as a148* parameter, in order to get the correct result.149*150* <p>This method also cleans existing buffer and other related state151* information.152*153* @param opmode the operation mode of this cipher (this is one of154* the following:155* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,156* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)157* @param key the secret key158* @param random the source of randomness159*160* @exception InvalidKeyException if the given key is inappropriate for161* initializing this cipher162*/163protected void engineInit(int opmode, Key key, SecureRandom random)164throws InvalidKeyException {165core.init(opmode, key, random);166}167168/**169* Initializes this cipher with a key, a set of170* algorithm parameters, and a source of randomness.171*172* <p>The cipher is initialized for one of the following four operations:173* encryption, decryption, key wrapping or key unwrapping, depending on174* the value of <code>opmode</code>.175*176* <p>If this cipher (including its underlying feedback or padding scheme)177* requires any random bytes, it will get them from <code>random</code>.178*179* @param opmode the operation mode of this cipher (this is one of180* the following:181* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,182* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)183* @param key the encryption key184* @param params the algorithm parameters185* @param random the source of randomness186*187* @exception InvalidKeyException if the given key is inappropriate for188* initializing this cipher189* @exception InvalidAlgorithmParameterException if the given algorithm190* parameters are inappropriate for this cipher191*/192protected void engineInit(int opmode, Key key,193AlgorithmParameterSpec params,194SecureRandom random)195throws InvalidKeyException, InvalidAlgorithmParameterException {196core.init(opmode, key, params, random);197}198199protected void engineInit(int opmode, Key key,200AlgorithmParameters params,201SecureRandom random)202throws InvalidKeyException, InvalidAlgorithmParameterException {203core.init(opmode, key, params, random);204}205206/**207* Continues a multiple-part encryption or decryption operation208* (depending on how this cipher was initialized), processing another data209* part.210*211* <p>The first <code>inputLen</code> bytes in the <code>input</code>212* buffer, starting at <code>inputOffset</code>, are processed, and the213* result is stored in a new buffer.214*215* @param input the input buffer216* @param inputOffset the offset in <code>input</code> where the input217* starts218* @param inputLen the input length219*220* @return the new buffer with the result221*222* @exception IllegalStateException if this cipher is in a wrong state223* (e.g., has not been initialized)224*/225protected byte[] engineUpdate(byte[] input, int inputOffset,226int inputLen) {227return core.update(input, inputOffset, inputLen);228}229230/**231* Continues a multiple-part encryption or decryption operation232* (depending on how this cipher was initialized), processing another data233* part.234*235* <p>The first <code>inputLen</code> bytes in the <code>input</code>236* buffer, starting at <code>inputOffset</code>, are processed, and the237* result is stored in the <code>output</code> buffer, starting at238* <code>outputOffset</code>.239*240* @param input the input buffer241* @param inputOffset the offset in <code>input</code> where the input242* starts243* @param inputLen the input length244* @param output the buffer for the result245* @param outputOffset the offset in <code>output</code> where the result246* is stored247*248* @return the number of bytes stored in <code>output</code>249*250* @exception ShortBufferException if the given output buffer is too small251* to hold the result252*/253protected int engineUpdate(byte[] input, int inputOffset, int inputLen,254byte[] output, int outputOffset)255throws ShortBufferException {256return core.update(input, inputOffset, inputLen, output,257outputOffset);258}259260/**261* Encrypts or decrypts data in a single-part operation,262* or finishes a multiple-part operation.263* The data is encrypted or decrypted, depending on how this cipher was264* initialized.265*266* <p>The first <code>inputLen</code> bytes in the <code>input</code>267* buffer, starting at <code>inputOffset</code>, and any input bytes that268* may have been buffered during a previous <code>update</code> operation,269* are processed, with padding (if requested) being applied.270* The result is stored in a new buffer.271*272* <p>The cipher is reset to its initial state (uninitialized) after this273* call.274*275* @param input the input buffer276* @param inputOffset the offset in <code>input</code> where the input277* starts278* @param inputLen the input length279*280* @return the new buffer with the result281*282* @exception IllegalBlockSizeException if this cipher is a block cipher,283* no padding has been requested (only in encryption mode), and the total284* input length of the data processed by this cipher is not a multiple of285* block size286* @exception BadPaddingException if this cipher is in decryption mode,287* and (un)padding has been requested, but the decrypted data is not288* bounded by the appropriate padding bytes289*/290protected byte[] engineDoFinal(byte[] input, int inputOffset,291int inputLen)292throws IllegalBlockSizeException, BadPaddingException {293return core.doFinal(input, inputOffset, inputLen);294}295296/**297* Encrypts or decrypts data in a single-part operation,298* or finishes a multiple-part operation.299* The data is encrypted or decrypted, depending on how this cipher was300* initialized.301*302* <p>The first <code>inputLen</code> bytes in the <code>input</code>303* buffer, starting at <code>inputOffset</code>, and any input bytes that304* may have been buffered during a previous <code>update</code> operation,305* are processed, with padding (if requested) being applied.306* The result is stored in the <code>output</code> buffer, starting at307* <code>outputOffset</code>.308*309* <p>The cipher is reset to its initial state (uninitialized) after this310* call.311*312* @param input the input buffer313* @param inputOffset the offset in <code>input</code> where the input314* starts315* @param inputLen the input length316* @param output the buffer for the result317* @param outputOffset the offset in <code>output</code> where the result318* is stored319*320* @return the number of bytes stored in <code>output</code>321*322* @exception IllegalBlockSizeException if this cipher is a block cipher,323* no padding has been requested (only in encryption mode), and the total324* input length of the data processed by this cipher is not a multiple of325* block size326* @exception ShortBufferException if the given output buffer is too small327* to hold the result328* @exception BadPaddingException if this cipher is in decryption mode,329* and (un)padding has been requested, but the decrypted data is not330* bounded by the appropriate padding bytes331*/332protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,333byte[] output, int outputOffset)334throws IllegalBlockSizeException, ShortBufferException,335BadPaddingException {336return core.doFinal(input, inputOffset, inputLen, output,337outputOffset);338}339340/**341* Returns the parameters used with this cipher.342*343* <p>The returned parameters may be the same that were used to initialize344* this cipher, or may contain the default set of parameters or a set of345* randomly generated parameters used by the underlying cipher346* implementation (provided that the underlying cipher implementation347* uses a default set of parameters or creates new parameters if it needs348* parameters but was not initialized with any).349*350* @return the parameters used with this cipher, or null if this cipher351* does not use any parameters.352*/353protected AlgorithmParameters engineGetParameters() {354return core.getParameters("DESede");355}356357/**358* Returns the key size of the given key object.359*360* @param key the key object.361*362* @return the "effective" key size of the given key object.363*364* @exception InvalidKeyException if <code>key</code> is invalid.365*/366protected int engineGetKeySize(Key key) throws InvalidKeyException {367byte[] encoded = key.getEncoded();368if (encoded.length != 24) {369throw new InvalidKeyException("Invalid key length: " +370encoded.length + " bytes");371}372// Return the effective key length373return 112;374}375376/**377* Wrap a key.378*379* @param key the key to be wrapped.380*381* @return the wrapped key.382*383* @exception IllegalBlockSizeException if this cipher is a block384* cipher, no padding has been requested, and the length of the385* encoding of the key to be wrapped is not a386* multiple of the block size.387*388* @exception InvalidKeyException if it is impossible or unsafe to389* wrap the key with this cipher (e.g., a hardware protected key is390* being passed to a software only cipher).391*/392protected byte[] engineWrap(Key key)393throws IllegalBlockSizeException, InvalidKeyException {394return core.wrap(key);395}396397/**398* Unwrap a previously wrapped key.399*400* @param wrappedKey the key to be unwrapped.401*402* @param wrappedKeyAlgorithm the algorithm the wrapped key is for.403*404* @param wrappedKeyType the type of the wrapped key.405* This is one of <code>Cipher.SECRET_KEY</code>,406* <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.407*408* @return the unwrapped key.409*410* @exception NoSuchAlgorithmException if no installed providers411* can create keys of type <code>wrappedKeyType</code> for the412* <code>wrappedKeyAlgorithm</code>.413*414* @exception InvalidKeyException if <code>wrappedKey</code> does not415* represent a wrapped key of type <code>wrappedKeyType</code> for416* the <code>wrappedKeyAlgorithm</code>.417*/418protected Key engineUnwrap(byte[] wrappedKey,419String wrappedKeyAlgorithm,420int wrappedKeyType)421throws InvalidKeyException, NoSuchAlgorithmException {422return core.unwrap(wrappedKey, wrappedKeyAlgorithm,423wrappedKeyType);424}425}426427428