All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax.crypto.CipherSpi Maven / Gradle / Ivy

/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package javax.crypto;

import java.nio.ByteBuffer;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;

/**
 * This class defines the Service Provider Interface (SPI) for
 * cryptographic ciphers.
 * 

* Implementers of cryptographic ciphers must implement all the abstract methods * for every cipher they implement. {@code CipherSpi} instances are created * along with ciphers when the {@link Cipher#getInstance} method is called. A * {@code Cipher} is referenced by a transformation, which is a string * that describes the operation (or set of operations), always consisting of the * cipher's name and optionally followed by a mode and a padding, in the form: *

    *
  • "algorithm"
  • or *
  • "algorithm/mode/padding"
  • *
* The following behavior should be implemented for obtaining {@code Cipher} * instances. *

* When one of the {@link Cipher#getInstance} factory methods is called with a * transformation that is only an algorithm, check if the provider * defines a {@code CipherSpi} for "algorithm", if so: return it, otherwise * throw a {@link NoSuchAlgorithmException}. *

* The following rules apply when a transformation is of the form * "algorithm/mode/padding": *

    * 1. The Provider has a {@code CipherSpi} subclass registered for * "algorithm/mode/padding": return it, otherwise go to step 2. *
*
    * 2. The Provider has a {@code CipherSpi} subclass registered for * "algorithm/mode": instantiate it, call * {@link CipherSpi#engineSetPadding(String) engineSetPadding(String)} for the * padding name and return it, otherwise go to step 3. *
*
    * 3. The Provider has a {@code CipherSpi} subclass registered for * "algorithm//padding": instantiate it, call * {@link CipherSpi#engineSetMode(String) engineSetMode(String)} for the mode * name and return it, otherwise go to step 4. *
*
    * 4. The Provider has a {@code CipherSpi} subclass registered for "algorithm": * instantiate it, call {@link CipherSpi#engineSetMode(String) * engineSetMode(String)} for the mode name , call * {@link CipherSpi#engineSetPadding(String) engineSetPadding(String)} for the * padding name and return it, otherwise throw a * {@link NoSuchAlgorithmException}. *
* * @see Cipher */ public abstract class CipherSpi { /** * Creates a new {@code CipherSpi} instance. */ public CipherSpi() { } /** * Sets the mode for this cipher. * * @param mode * the name of the cipher mode. * @throws NoSuchAlgorithmException * if the specified cipher mode is not supported by this * provider. */ protected abstract void engineSetMode(String mode) throws NoSuchAlgorithmException; /** * Sets the padding method for this cipher. * * @param padding * the name of the padding method. * @throws NoSuchPaddingException * if the specified padding method is not supported by this * cipher. */ protected abstract void engineSetPadding(String padding) throws NoSuchPaddingException; /** * Returns the block size of this cipher (in bytes) * * @return the block size of this cipher, or zero if this cipher is not a * block cipher. */ protected abstract int engineGetBlockSize(); /** * Returns the size for a buffer (in bytes), that the next call to {@code * update} of {@code doFinal} would return, taking into account any buffered * data from previous {@code update} calls and padding. *

* The actual output length of the next call to {@code update} or {@code * doFinal} may be smaller than the length returned by this method. * * @param inputLen * the length of the input (in bytes). * @return the size for a buffer (in bytes). */ protected abstract int engineGetOutputSize(int inputLen); /** * Returns the Initialization Vector (IV) that was used to initialize this * cipher or {@code null} if none was used. * * @return the Initialization Vector (IV), or {@code null} if none was used. */ protected abstract byte[] engineGetIV(); /** * Returns the parameters that where used to create this cipher instance. *

* These may be a the same parameters that were used to create this cipher * instance, or may be a combination of default and random parameters, * depending on the underlying cipher implementation. * * @return the parameters that where used to create this cipher instance, or * {@code null} if this cipher instance does not have any parameters * at all. */ protected abstract AlgorithmParameters engineGetParameters(); /** * Initializes this cipher instance with the specified key and a source of * randomness. *

* The cipher will be initialized for the specified operation (one of: * encryption, decryption, key wrapping or key unwrapping) depending on * {@code opmode}. *

* If this cipher instance needs any algorithm parameters or random values * that the specified key cannot provide, the underlying implementation of * this cipher is supposed to generate the required parameters (using its * provider or random values). Random values will be generated using {@code * random}; *

* When a cipher instance is initialized by a call to any of the {@code * init} methods, the state of the instance is overridden, means it is * equivalent to creating a new instance and calling it {@code init} method. * * @param opmode * the operation this cipher instance should be initialized for * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code * WRAP_MODE} or {@code UNWRAP_MODE}). * @param key * the input key for the operation. * @param random * the source of randomness to use. * @throws InvalidKeyException * if the specified key cannot be used to initialize this cipher * instance. */ protected abstract void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException; /** * Initializes this cipher instance with the specified key, algorithm * parameters and a source of randomness. *

* The cipher will be initialized for the specified operation (one of: * encryption, decryption, key wrapping or key unwrapping) depending on * {@code opmode}. *

* If this cipher instance needs any algorithm parameters and {@code params} * is {@code null}, the underlying implementation of this cipher is supposed * to generate the required parameters (using its provider or random * values). Random values are generated using {@code random}. *

* When a cipher instance is initialized by a call to any of the {@code * init} methods, the state of the instance is overridden, means it is * equivalent to creating a new instance and calling it {@code init} method. * * @param opmode * the operation this cipher instance should be initialized for * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code * WRAP_MODE} or {@code UNWRAP_MODE}). * @param key * the input key for the operation. * @param params * the algorithm parameters. * @param random * the source of randomness to use. * @throws InvalidKeyException * if the specified key cannot be used to initialize this cipher * instance. * @throws InvalidAlgorithmParameterException * it the specified parameters are inappropriate for this * cipher. */ protected abstract void engineInit(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException; /** * Initializes this cipher instance with the specified key, algorithm * parameters and a source of randomness. *

* The cipher will be initialized for the specified operation (one of: * encryption, decryption, key wrapping or key unwrapping) depending on * {@code opmode}. *

* If this cipher instance needs any algorithm parameters and {@code params} * is {@code null}, the underlying implementation of this cipher is supposed * to generate the required parameters (using its provider or random * values). Random values are generated using {@code random}. *

* When a cipher instance is initialized by a call to any of the {@code * init} methods, the state of the instance is overridden, means it is * equivalent to creating a new instance and calling it {@code init} method. * * @param opmode * the operation this cipher instance should be initialized for * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code * WRAP_MODE} or {@code UNWRAP_MODE}). * @param key * the input key for the operation. * @param params * the algorithm parameters. * @param random * the source of randomness to use. * @throws InvalidKeyException * if the specified key cannot be used to initialize this cipher * instance. * @throws InvalidAlgorithmParameterException * if the specified parameters are inappropriate for this * cipher. */ protected abstract void engineInit(int opmode, Key key, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException; /** * Continues a multi-part transformation (encryption or decryption). The * transformed bytes are returned. * * @param input * the input bytes to transform. * @param inputOffset * the offset in the input to start. * @param inputLen * the length of the input to transform. * @return the transformed bytes in a new buffer, or {@code null} if the * input has zero length. * @throws IllegalStateException * if this cipher instance is not initialized for encryption or * decryption. * @throws IllegalArgumentException * if the input is null, or if {@code inputOffset} and {@code * inputLen} do not specify a valid chunk in the input buffer. */ protected abstract byte[] engineUpdate(byte[] input, int inputOffset, int inputLen); /** * Continues a multi-part transformation (encryption or decryption). The * transformed bytes are stored in the {@code output} buffer. *

* If the size of the {@code output} buffer is too small to hold the result, * a {@code ShortBufferException} is thrown. Use * {@link Cipher#getOutputSize getOutputSize} to check for the size of the * output buffer. * * @param input * the input bytes to transform. * @param inputOffset * the offset in the input to start. * @param inputLen * the length of the input to transform. * @param output * the output buffer. * @param outputOffset * the offset in the output buffer. * @return the number of bytes placed in output. * @throws ShortBufferException * if the size of the {@code output} buffer is too small. */ protected abstract int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException; /** * Continues a multi-part transformation (encryption or decryption). The * {@code input.remaining()} bytes starting at {@code input.position()} are * transformed and stored in the {@code output} buffer. *

* If the {@code output.remaining()} is too small to hold the transformed * bytes a {@code ShortBufferException} is thrown. Use * {@link Cipher#getOutputSize getOutputSize} to check for the size of the * output buffer. * * @param input * the input buffer to transform. * @param output * the output buffer to store the result within. * @return the number of bytes stored in the output buffer. * @throws ShortBufferException * if the size of the {@code output} buffer is too small. */ protected int engineUpdate(ByteBuffer input, ByteBuffer output) throws ShortBufferException { if (input == null) { throw new NullPointerException("input == null"); } if (output == null) { throw new NullPointerException("output == null"); } int position = input.position(); int limit = input.limit(); if ((limit - position) <= 0) { return 0; } byte[] bInput; byte[] bOutput; if (input.hasArray()) { bInput = input.array(); int offset = input.arrayOffset(); bOutput = engineUpdate(bInput, offset + position, limit - position); input.position(limit); } else { bInput = new byte[limit - position]; input.get(bInput); bOutput = engineUpdate(bInput, 0, limit - position); } if (bOutput == null) { return 0; } if (output.remaining() < bOutput.length) { throw new ShortBufferException("output buffer too small"); } try { output.put(bOutput); } catch (java.nio.BufferOverflowException e) { throw new ShortBufferException("output buffer too small"); } return bOutput.length; } /** * Continues a multi-part transformation (encryption or decryption) with * Authenticated Additional Data (AAD). AAD may only be added after the * {@code Cipher} is initialized and before any data is passed to the * instance. *

* This is only usable with cipher modes that support Authenticated * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM). * * @param input bytes of AAD to use with the cipher * @param inputOffset offset within bytes of additional data to add to cipher * @param inputLen length of bytes of additional data to add to cipher * @throws IllegalStateException * if this cipher instance is not initialized for encryption or * decryption. * @throws IllegalArgumentException * if {@code input} is {@code null}, or if {@code inputOffset} and * {@code inputLen} do not specify a valid chunk in the input * buffer. * @throws UnsupportedOperationException if the cipher does not support AEAD * @since 1.7 */ protected void engineUpdateAAD(byte[] input, int inputOffset, int inputLen) { throw new UnsupportedOperationException( "This cipher does not support Authenticated Encryption with Additional Data"); } /** * Continues a multi-part transformation (encryption or decryption). The * {@code input.remaining()} bytes starting at {@code input.position()} are * used for the Additional Authenticated Data (AAD). AAD may only be added * after the {@code Cipher} is initialized and before any data is passed to * the instance. *

* This is only usable with cipher modes that support Authenticated * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM). * * @param input the input buffer to transform. * @since 1.7 */ protected void engineUpdateAAD(ByteBuffer input) { if (input == null) { throw new NullPointerException("input == null"); } int position = input.position(); int limit = input.limit(); if ((limit - position) <= 0) { return; } byte[] bInput; if (input.hasArray()) { bInput = input.array(); int offset = input.arrayOffset(); engineUpdateAAD(bInput, offset + position, limit - position); input.position(limit); } else { int len = limit - position; bInput = new byte[len]; input.get(bInput); engineUpdateAAD(bInput, 0, len); } } /** * Finishes a multi-part transformation (encryption or decryption). *

* Processes the {@code inputLen} bytes in {@code input} buffer at {@code * inputOffset}, and any bytes that have been buffered in previous {@code * update} calls. * * @param input * the input buffer. * @param inputOffset * the offset in the input buffer. * @param inputLen * the length of the input. * @return the final bytes from the transformation. * @throws IllegalBlockSizeException * if the size of the resulting bytes is not a multiple of the * cipher block size. * @throws BadPaddingException * if the padding of the data does not match the padding scheme. */ protected abstract byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen) throws IllegalBlockSizeException, BadPaddingException; /** * Finishes a multi-part transformation (encryption or decryption). *

* Processes the {@code inputLen} bytes in {@code input} buffer at * {@code inputOffset}, and any bytes that have been buffered in previous * {@code update} calls. * * @param input * the input buffer. * @param inputOffset * the offset in the input buffer. * @param inputLen * the length of the input. * @param output * the output buffer for the transformed bytes. * @param outputOffset * the offset in the output buffer. * @return the number of bytes placed in the output buffer. * @throws ShortBufferException * if the size of the {@code output} buffer is too small. * @throws IllegalBlockSizeException * if the size of the resulting bytes is not a multiple of the * cipher block size. * @throws BadPaddingException * if the padding of the data does not match the padding scheme. */ protected abstract int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException; /** * Finishes a multi-part transformation (encryption or decryption). *

* Processes the {@code input.remaining()} bytes in {@code input} buffer at * {@code input.position()}, and any bytes that have been buffered in * previous {@code update} calls. The transformed bytes are placed into * {@code output} buffer. * * @param input * the input buffer. * @param output * the output buffer. * @return the number of bytes placed into the output buffer. * @throws ShortBufferException * if the size of the {@code output} buffer is too small. * @throws IllegalBlockSizeException * if the size of the resulting bytes is not a multiple of the * cipher block size. * @throws BadPaddingException * if the padding of the data does not match the padding scheme. * @throws IllegalArgumentException * if the input buffer and the output buffer are the same * object. * @throws IllegalStateException * if this cipher instance is not initialized for encryption or * decryption. */ protected int engineDoFinal(ByteBuffer input, ByteBuffer output) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { if (input == null) { throw new NullPointerException("input == null"); } if (output == null) { throw new NullPointerException("output == null"); } int position = input.position(); int limit = input.limit(); if ((limit - position) <= 0) { return 0; } byte[] bInput; byte[] bOutput; if (input.hasArray()) { bInput = input.array(); int offset = input.arrayOffset(); bOutput = engineDoFinal(bInput, offset + position, limit - position); input.position(limit); } else { bInput = new byte[limit - position]; input.get(bInput); bOutput = engineDoFinal(bInput, 0, limit - position); } if (output.remaining() < bOutput.length) { throw new ShortBufferException("output buffer too small"); } try { output.put(bOutput); } catch (java.nio.BufferOverflowException e) { throw new ShortBufferException("output buffer too small"); } return bOutput.length; } /** * Wraps a key using this cipher instance. This method has been added to * this class (for backwards compatibility, it cannot be abstract). If this * method is not overridden, it throws an {@code * UnsupportedOperationException}. * * @param key * the key to wrap. * @return the wrapped key * @throws IllegalBlockSizeException * if the size of the resulting bytes is not a multiple of the * cipher block size. * @throws InvalidKeyException * if this cipher instance cannot wrap this key. */ protected byte[] engineWrap(Key key) throws IllegalBlockSizeException, InvalidKeyException { throw new UnsupportedOperationException(); } /** * Unwraps a key using this cipher instance. *

* This method has been added to this class (for backwards compatibility, it * cannot be abstract). If this method is not overridden, it throws an * {@code UnsupportedOperationException}. * * @param wrappedKey * the wrapped key to unwrap. * @param wrappedKeyAlgorithm * the algorithm for the wrapped key. * @param wrappedKeyType * the type of the wrapped key (one of: {@code SECRET_KEY}, * {@code PRIVATE_KEY} or {@code PUBLIC_KEY}) * @return the unwrapped key. * @throws InvalidKeyException * if the {@code wrappedKey} cannot be unwrapped to a key of * type {@code wrappedKeyType} for the {@code * wrappedKeyAlgorithm}. * @throws NoSuchAlgorithmException * if no provider can be found that can create a key of type * {@code wrappedKeyType} for the {@code wrappedKeyAlgorithm}. */ protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException { throw new UnsupportedOperationException(); } /** * Returns the size of a specified key object in bits. This method has been * added to this class (for backwards compatibility, it cannot be abstract). * If this method is not overridden, it throws an {@code * UnsupportedOperationException}. * * @param key * the key to get the size for. * @return the size of a specified key object in bits. * @throws InvalidKeyException * if the size of the key cannot be determined by this * implementation. */ protected int engineGetKeySize(Key key) throws InvalidKeyException { throw new UnsupportedOperationException(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy