Path: blob/master/src/java.base/share/classes/com/sun/crypto/provider/DESCipher.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.*;32import javax.crypto.BadPaddingException;3334/**35* This class implements the DES algorithm in its various modes36* (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>, <code>CBC</code>,37* <code>PCBC</code>) and padding schemes (<code>PKCS5Padding</code>,38* <code>NoPadding</code>, <code>ISO10126Padding</code>).39*40* @author Gigi Ankeny41* @author Jan Luehe42* @see DESCrypt43* @see CipherBlockChaining44* @see ElectronicCodeBook45* @see CipherFeedback46* @see OutputFeedback47*/4849public final class DESCipher extends CipherSpi {5051/*52* internal CipherCore object which does the real work.53*/54private CipherCore core = null;5556/**57* Creates an instance of DES cipher with default ECB mode and58* PKCS5Padding.59*/60public DESCipher() {61core = new CipherCore(new DESCrypt(), DESConstants.DES_BLOCK_SIZE);62}6364/**65* Sets the mode of this cipher.66*67* @param mode the cipher mode68*69* @exception NoSuchAlgorithmException if the requested cipher mode does70* not exist71*/72protected void engineSetMode(String mode)73throws NoSuchAlgorithmException {74core.setMode(mode);75}7677/**78* Sets the padding mechanism of this cipher.79*80* @param paddingScheme the padding mechanism81*82* @exception NoSuchPaddingException if the requested padding mechanism83* does not exist84*/85protected void engineSetPadding(String paddingScheme)86throws NoSuchPaddingException {87core.setPadding(paddingScheme);88}8990/**91* Returns the block size (in bytes).92*93* @return the block size (in bytes), or 0 if the underlying algorithm is94* not a block cipher95*/96protected int engineGetBlockSize() {97return DESConstants.DES_BLOCK_SIZE;98}99100/**101* Returns the length in bytes that an output buffer would need to be in102* order to hold the result of the next <code>update</code> or103* <code>doFinal</code> operation, given the input length104* <code>inputLen</code> (in bytes).105*106* <p>This call takes into account any unprocessed (buffered) data from a107* previous <code>update</code> call, and padding.108*109* <p>The actual output length of the next <code>update</code> or110* <code>doFinal</code> call may be smaller than the length returned by111* this method.112*113* @param inputLen the input length (in bytes)114*115* @return the required output buffer size (in bytes)116*/117protected int engineGetOutputSize(int inputLen) {118return core.getOutputSize(inputLen);119}120121/**122* Returns the initialization vector (IV) in a new buffer.123*124* <p>This is useful in the case where a random IV has been created125* (see <a href = "#init">init</a>),126* or in the context of password-based encryption or127* decryption, where the IV is derived from a user-provided password.128*129* @return the initialization vector in a new buffer, or null if the130* underlying algorithm does not use an IV, or if the IV has not yet131* been set.132*/133protected byte[] engineGetIV() {134return core.getIV();135}136137/**138* Returns the parameters used with this cipher.139*140* <p>The returned parameters may be the same that were used to initialize141* this cipher, or may contain the default set of parameters or a set of142* randomly generated parameters used by the underlying cipher143* implementation (provided that the underlying cipher implementation144* uses a default set of parameters or creates new parameters if it needs145* parameters but was not initialized with any).146*147* @return the parameters used with this cipher, or null if this cipher148* does not use any parameters.149*/150protected AlgorithmParameters engineGetParameters() {151return core.getParameters("DES");152}153154/**155* Initializes this cipher with a key and a source of randomness.156*157* <p>The cipher is initialized for one of the following four operations:158* encryption, decryption, key wrapping or key unwrapping, depending on159* the value of <code>opmode</code>.160*161* <p>If this cipher requires an initialization vector (IV), it will get162* it from <code>random</code>.163* This behaviour should only be used in encryption or key wrapping164* mode, however.165* When initializing a cipher that requires an IV for decryption or166* key unwrapping, the IV167* (same IV that was used for encryption or key wrapping) must be provided168* explicitly as a169* parameter, in order to get the correct result.170*171* <p>This method also cleans existing buffer and other related state172* information.173*174* @param opmode the operation mode of this cipher (this is one of175* the following:176* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,177* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)178* @param key the secret key179* @param random the source of randomness180*181* @exception InvalidKeyException if the given key is inappropriate for182* initializing this cipher183*/184protected void engineInit(int opmode, Key key, SecureRandom random)185throws InvalidKeyException {186core.init(opmode, key, random);187}188189/**190* Initializes this cipher with a key, a set of191* algorithm parameters, and a source of randomness.192*193* <p>The cipher is initialized for one of the following four operations:194* encryption, decryption, key wrapping or key unwrapping, depending on195* the value of <code>opmode</code>.196*197* <p>If this cipher (including its underlying feedback or padding scheme)198* requires any random bytes, it will get them from <code>random</code>.199*200* @param opmode the operation mode of this cipher (this is one of201* the following:202* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,203* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)204* @param key the encryption key205* @param params the algorithm parameters206* @param random the source of randomness207*208* @exception InvalidKeyException if the given key is inappropriate for209* initializing this cipher210* @exception InvalidAlgorithmParameterException if the given algorithm211* parameters are inappropriate for this cipher212*/213protected void engineInit(int opmode, Key key,214AlgorithmParameterSpec params,215SecureRandom random)216throws InvalidKeyException, InvalidAlgorithmParameterException {217core.init(opmode, key, params, random);218}219220protected void engineInit(int opmode, Key key,221AlgorithmParameters params,222SecureRandom random)223throws InvalidKeyException, InvalidAlgorithmParameterException {224core.init(opmode, key, params, random);225}226227/**228* Continues a multiple-part encryption or decryption operation229* (depending on how this cipher was initialized), processing another data230* part.231*232* <p>The first <code>inputLen</code> bytes in the <code>input</code>233* buffer, starting at <code>inputOffset</code>, are processed, and the234* result is stored in a new buffer.235*236* @param input the input buffer237* @param inputOffset the offset in <code>input</code> where the input238* starts239* @param inputLen the input length240*241* @return the new buffer with the result242*243* @exception IllegalStateException if this cipher is in a wrong state244* (e.g., has not been initialized)245*/246protected byte[] engineUpdate(byte[] input, int inputOffset,247int inputLen) {248return core.update(input, inputOffset, inputLen);249}250251/**252* Continues a multiple-part encryption or decryption operation253* (depending on how this cipher was initialized), processing another data254* part.255*256* <p>The first <code>inputLen</code> bytes in the <code>input</code>257* buffer, starting at <code>inputOffset</code>, are processed, and the258* result is stored in the <code>output</code> buffer, starting at259* <code>outputOffset</code>.260*261* @param input the input buffer262* @param inputOffset the offset in <code>input</code> where the input263* starts264* @param inputLen the input length265* @param output the buffer for the result266* @param outputOffset the offset in <code>output</code> where the result267* is stored268*269* @return the number of bytes stored in <code>output</code>270*271* @exception ShortBufferException if the given output buffer is too small272* to hold the result273*/274protected int engineUpdate(byte[] input, int inputOffset, int inputLen,275byte[] output, int outputOffset)276throws ShortBufferException {277return core.update(input, inputOffset, inputLen, output,278outputOffset);279}280281/**282* Encrypts or decrypts data in a single-part operation,283* or finishes a multiple-part operation.284* The data is encrypted or decrypted, depending on how this cipher was285* initialized.286*287* <p>The first <code>inputLen</code> bytes in the <code>input</code>288* buffer, starting at <code>inputOffset</code>, and any input bytes that289* may have been buffered during a previous <code>update</code> operation,290* are processed, with padding (if requested) being applied.291* The result is stored in a new buffer.292*293* <p>The cipher is reset to its initial state (uninitialized) after this294* call.295*296* @param input the input buffer297* @param inputOffset the offset in <code>input</code> where the input298* starts299* @param inputLen the input length300*301* @return the new buffer with the result302*303* @exception IllegalBlockSizeException if this cipher is a block cipher,304* no padding has been requested (only in encryption mode), and the total305* input length of the data processed by this cipher is not a multiple of306* block size307* @exception BadPaddingException if this cipher is in decryption mode,308* and (un)padding has been requested, but the decrypted data is not309* bounded by the appropriate padding bytes310*/311protected byte[] engineDoFinal(byte[] input, int inputOffset,312int inputLen)313throws IllegalBlockSizeException, BadPaddingException {314return core.doFinal(input, inputOffset, inputLen);315}316317/**318* Encrypts or decrypts data in a single-part operation,319* or finishes a multiple-part operation.320* The data is encrypted or decrypted, depending on how this cipher was321* initialized.322*323* <p>The first <code>inputLen</code> bytes in the <code>input</code>324* buffer, starting at <code>inputOffset</code>, and any input bytes that325* may have been buffered during a previous <code>update</code> operation,326* are processed, with padding (if requested) being applied.327* The result is stored in the <code>output</code> buffer, starting at328* <code>outputOffset</code>.329*330* <p>The cipher is reset to its initial state (uninitialized) after this331* call.332*333* @param input the input buffer334* @param inputOffset the offset in <code>input</code> where the input335* starts336* @param inputLen the input length337* @param output the buffer for the result338* @param outputOffset the offset in <code>output</code> where the result339* is stored340*341* @return the number of bytes stored in <code>output</code>342*343* @exception IllegalBlockSizeException if this cipher is a block cipher,344* no padding has been requested (only in encryption mode), and the total345* input length of the data processed by this cipher is not a multiple of346* block size347* @exception ShortBufferException if the given output buffer is too small348* to hold the result349* @exception BadPaddingException if this cipher is in decryption mode,350* and (un)padding has been requested, but the decrypted data is not351* bounded by the appropriate padding bytes352*/353protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,354byte[] output, int outputOffset)355throws IllegalBlockSizeException, ShortBufferException,356BadPaddingException {357return core.doFinal(input, inputOffset, inputLen, output,358outputOffset);359}360361/**362* Returns the key size of the given key object.363*364* @param key the key object.365*366* @return the key size of the given key object.367*368* @exception InvalidKeyException if <code>key</code> is invalid.369*/370protected int engineGetKeySize(Key key) throws InvalidKeyException {371byte[] encoded = key.getEncoded();372Arrays.fill(encoded, (byte)0);373if (encoded.length != 8) {374throw new InvalidKeyException("Invalid key length: " +375encoded.length + " bytes");376}377return 56;378}379380/**381* Wrap a key.382*383* @param key the key to be wrapped.384*385* @return the wrapped key.386*387* @exception IllegalBlockSizeException if this cipher is a block388* cipher, no padding has been requested, and the length of the389* encoding of the key to be wrapped is not a390* multiple of the block size.391*392* @exception InvalidKeyException if it is impossible or unsafe to393* wrap the key with this cipher (e.g., a hardware protected key is394* being passed to a software only cipher).395*/396protected byte[] engineWrap(Key key)397throws IllegalBlockSizeException, InvalidKeyException {398return core.wrap(key);399}400401/**402* Unwrap a previously wrapped key.403*404* @param wrappedKey the key to be unwrapped.405*406* @param wrappedKeyAlgorithm the algorithm the wrapped key is for.407*408* @param wrappedKeyType the type of the wrapped key.409* This is one of <code>Cipher.SECRET_KEY</code>,410* <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.411*412* @return the unwrapped key.413*414* @exception NoSuchAlgorithmException if no installed providers415* can create keys of type <code>wrappedKeyType</code> for the416* <code>wrappedKeyAlgorithm</code>.417*418* @exception InvalidKeyException if <code>wrappedKey</code> does not419* represent a wrapped key of type <code>wrappedKeyType</code> for420* the <code>wrappedKeyAlgorithm</code>.421*/422protected Key engineUnwrap(byte[] wrappedKey,423String wrappedKeyAlgorithm,424int wrappedKeyType)425throws InvalidKeyException, NoSuchAlgorithmException {426return core.unwrap(wrappedKey, wrappedKeyAlgorithm,427wrappedKeyType);428}429}430431432