Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/crypto/provider/BlowfishCipher.java
38922 views
/*1* Copyright (c) 1998, 2017, 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 sun.security.util.*;30import javax.crypto.*;31import javax.crypto.spec.*;32import javax.crypto.BadPaddingException;3334/**35* This class implements the Blowfish 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* <p> Blowfish is a 64-bit block cipher with a variable-length key.41*42* @author Jan Luehe43*44*45* @see BlowfishCrypt46* @see CipherBlockChaining47* @see ElectronicCodeBook48* @see CipherFeedback49* @see OutputFeedback50*/5152public final class BlowfishCipher extends CipherSpi {5354/*55* internal CipherCore object which does the real work.56*/57private CipherCore core = null;5859/**60* Creates an instance of Blowfish cipher with default ECB mode and61* PKCS5Padding.62*/63public BlowfishCipher() {64core = new CipherCore(new BlowfishCrypt(),65BlowfishConstants.BLOWFISH_BLOCK_SIZE);66}6768/**69* Sets the mode of this cipher.70*71* @param mode the cipher mode72*73* @exception NoSuchAlgorithmException if the requested cipher mode does74* not exist75*/76protected void engineSetMode(String mode)77throws NoSuchAlgorithmException {78core.setMode(mode);79}8081/**82* Sets the padding mechanism of this cipher.83*84* @param paddingScheme the padding mechanism85*86* @exception NoSuchPaddingException if the requested padding mechanism87* does not exist88*/89protected void engineSetPadding(String paddingScheme)90throws NoSuchPaddingException {91core.setPadding(paddingScheme);92}9394/**95* Returns the block size (in bytes).96*97* @return the block size (in bytes), or 0 if the underlying algorithm is98* not a block cipher99*/100protected int engineGetBlockSize() {101return BlowfishConstants.BLOWFISH_BLOCK_SIZE;102}103104/**105* Returns the length in bytes that an output buffer would need to be in106* order to hold the result of the next <code>update</code> or107* <code>doFinal</code> operation, given the input length108* <code>inputLen</code> (in bytes).109*110* <p>This call takes into account any unprocessed (buffered) data from a111* previous <code>update</code> call, and padding.112*113* <p>The actual output length of the next <code>update</code> or114* <code>doFinal</code> call may be smaller than the length returned by115* this method.116*117* @param inputLen the input length (in bytes)118*119* @return the required output buffer size (in bytes)120*/121protected int engineGetOutputSize(int inputLen) {122return core.getOutputSize(inputLen);123}124125/**126* Returns the initialization vector (IV) in a new buffer.127*128* <p>This is useful in the case where a random IV has been created129* (see <a href = "#init">init</a>),130* or in the context of password-based encryption or131* decryption, where the IV is derived from a user-supplied password.132*133* @return the initialization vector in a new buffer, or null if the134* underlying algorithm does not use an IV, or if the IV has not yet135* been set.136*/137protected byte[] engineGetIV() {138return core.getIV();139}140141/**142* Returns the parameters used with this cipher.143*144* <p>The returned parameters may be the same that were used to initialize145* this cipher, or may contain the default set of parameters or a set of146* randomly generated parameters used by the underlying cipher147* implementation (provided that the underlying cipher implementation148* uses a default set of parameters or creates new parameters if it needs149* parameters but was not initialized with any).150*151* @return the parameters used with this cipher, or null if this cipher152* does not use any parameters.153*/154protected AlgorithmParameters engineGetParameters() {155return core.getParameters("Blowfish");156}157158/**159* Initializes this cipher with a key and a source of randomness.160*161* <p>The cipher is initialized for one of the following four operations:162* encryption, decryption, key wrapping or key unwrapping, depending on163* the value of <code>opmode</code>.164*165* <p>If this cipher requires an initialization vector (IV), it will get166* it from <code>random</code>.167* This behaviour should only be used in encryption or key wrapping168* mode, however.169* When initializing a cipher that requires an IV for decryption or170* key unwrapping, the IV171* (same IV that was used for encryption or key wrapping) must be provided172* explicitly as a173* parameter, in order to get the correct result.174*175* <p>This method also cleans existing buffer and other related state176* information.177*178* @param opmode the operation mode of this cipher (this is one of179* the following:180* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,181* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)182* @param key the secret key183* @param random the source of randomness184*185* @exception InvalidKeyException if the given key is inappropriate for186* initializing this cipher187*/188protected void engineInit(int opmode, Key key, SecureRandom random)189throws InvalidKeyException {190core.init(opmode, key, random);191}192193/**194* Initializes this cipher with a key, a set of195* algorithm parameters, and a source of randomness.196*197* <p>The cipher is initialized for one of the following four operations:198* encryption, decryption, key wrapping or key unwrapping, depending on199* 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 of205* 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 key209* @param params the algorithm parameters210* @param random the source of randomness211*212* @exception InvalidKeyException if the given key is inappropriate for213* initializing this cipher214* @exception InvalidAlgorithmParameterException if the given algorithm215* parameters are inappropriate for this cipher216*/217protected void engineInit(int opmode, Key key,218AlgorithmParameterSpec params,219SecureRandom random)220throws InvalidKeyException, InvalidAlgorithmParameterException {221core.init(opmode, key, params, random);222}223224protected void engineInit(int opmode, Key key,225AlgorithmParameters params,226SecureRandom random)227throws InvalidKeyException, InvalidAlgorithmParameterException {228core.init(opmode, key, params, random);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 a new buffer.239*240* @param input the input buffer241* @param inputOffset the offset in <code>input</code> where the input242* starts243* @param inputLen the input length244*245* @return the new buffer with the result246*247* @exception IllegalStateException if this cipher is in a wrong state248* (e.g., has not been initialized)249*/250protected byte[] engineUpdate(byte[] input, int inputOffset,251int inputLen) {252return core.update(input, inputOffset, inputLen);253}254255/**256* Continues a multiple-part encryption or decryption operation257* (depending on how this cipher was initialized), processing another data258* part.259*260* <p>The first <code>inputLen</code> bytes in the <code>input</code>261* buffer, starting at <code>inputOffset</code>, are processed, and the262* result is stored in the <code>output</code> buffer, starting at263* <code>outputOffset</code>.264*265* @param input the input buffer266* @param inputOffset the offset in <code>input</code> where the input267* starts268* @param inputLen the input length269* @param output the buffer for the result270* @param outputOffset the offset in <code>output</code> where the result271* is stored272*273* @return the number of bytes stored in <code>output</code>274*275* @exception ShortBufferException if the given output buffer is too small276* to hold the result277*/278protected int engineUpdate(byte[] input, int inputOffset, int inputLen,279byte[] output, int outputOffset)280throws ShortBufferException {281return core.update(input, inputOffset, inputLen, output,282outputOffset);283}284285/**286* Encrypts or decrypts data in a single-part operation,287* or finishes a multiple-part operation.288* The data is encrypted or decrypted, depending on how this cipher was289* initialized.290*291* <p>The first <code>inputLen</code> bytes in the <code>input</code>292* buffer, starting at <code>inputOffset</code>, and any input bytes that293* may have been buffered during a previous <code>update</code> operation,294* are processed, with padding (if requested) being applied.295* The result is stored in a new buffer.296*297* <p>The cipher is reset to its initial state (uninitialized) after this298* call.299*300* @param input the input buffer301* @param inputOffset the offset in <code>input</code> where the input302* starts303* @param inputLen the input length304*305* @return the new buffer with the result306*307* @exception IllegalBlockSizeException if this cipher is a block cipher,308* no padding has been requested (only in encryption mode), and the total309* input length of the data processed by this cipher is not a multiple of310* block size311* @exception BadPaddingException if this cipher is in decryption mode,312* and (un)padding has been requested, but the decrypted data is not313* bounded by the appropriate padding bytes314*/315protected byte[] engineDoFinal(byte[] input, int inputOffset,316int inputLen)317throws IllegalBlockSizeException, BadPaddingException {318return core.doFinal(input, inputOffset, inputLen);319}320321/**322* Encrypts or decrypts data in a single-part operation,323* or finishes a multiple-part operation.324* The data is encrypted or decrypted, depending on how this cipher was325* initialized.326*327* <p>The first <code>inputLen</code> bytes in the <code>input</code>328* buffer, starting at <code>inputOffset</code>, and any input bytes that329* may have been buffered during a previous <code>update</code> operation,330* are processed, with padding (if requested) being applied.331* The result is stored in the <code>output</code> buffer, starting at332* <code>outputOffset</code>.333*334* <p>The cipher is reset to its initial state (uninitialized) after this335* call.336*337* @param input the input buffer338* @param inputOffset the offset in <code>input</code> where the input339* starts340* @param inputLen the input length341* @param output the buffer for the result342* @param outputOffset the offset in <code>output</code> where the result343* is stored344*345* @return the number of bytes stored in <code>output</code>346*347* @exception IllegalBlockSizeException if this cipher is a block cipher,348* no padding has been requested (only in encryption mode), and the total349* input length of the data processed by this cipher is not a multiple of350* block size351* @exception ShortBufferException if the given output buffer is too small352* to hold the result353* @exception BadPaddingException if this cipher is in decryption mode,354* and (un)padding has been requested, but the decrypted data is not355* bounded by the appropriate padding bytes356*/357protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,358byte[] output, int outputOffset)359throws IllegalBlockSizeException, ShortBufferException,360BadPaddingException {361return core.doFinal(input, inputOffset, inputLen, output,362outputOffset);363}364365/**366* Returns the key size of the given key object.367*368* @param key the key object.369*370* @return the key size of the given key object.371*372* @exception InvalidKeyException if <code>key</code> is invalid.373*/374protected int engineGetKeySize(Key key) throws InvalidKeyException {375return Math.multiplyExact(key.getEncoded().length, 8);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