| /* |
| * 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.InvalidParameterException; |
| import java.security.Key; |
| import java.security.NoSuchAlgorithmException; |
| import java.security.NoSuchProviderException; |
| import java.security.Provider; |
| import java.security.Provider.Service; |
| import java.security.ProviderException; |
| import java.security.SecureRandom; |
| import java.security.Security; |
| import java.security.cert.Certificate; |
| import java.security.cert.X509Certificate; |
| import java.security.spec.AlgorithmParameterSpec; |
| import java.util.ArrayList; |
| import java.util.Locale; |
| import java.util.Set; |
| import org.apache.harmony.crypto.internal.NullCipherSpi; |
| import org.apache.harmony.security.fortress.Engine; |
| |
| /** |
| * This class provides access to implementations of cryptographic ciphers for |
| * encryption and decryption. Cipher classes can not be instantiated directly, |
| * one has to call the Cipher's {@code getInstance} method with the name of a |
| * requested transformation, optionally with a provider. A transformation |
| * specifies an operation (or a set of operations) as a string in the form: |
| * <ul> |
| * <li><i>"algorithm/mode/padding"</i></li> or |
| * <li><i>"algorithm"</i></li> |
| * </ul> |
| * <i>algorithm</i> is the name of a cryptographic algorithm, <i>mode</i> is the |
| * name of a feedback mode and <i>padding</i> is the name of a padding scheme. |
| * If <i>mode</i> and/or <i>padding</i> values are omitted, provider specific |
| * default values will be used. |
| * <p> |
| * A valid transformation would be: |
| * <ul> |
| * {@code Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");} |
| * </ul> |
| * When a block cipher is requested in stream cipher mode, the number of bits |
| * to be processed at a time can be optionally specified by appending it to the |
| * mode name. e.g. <i>"AES/CFB8/NoPadding"</i>. If no number is specified, a |
| * provider specific default value is used. |
| */ |
| public class Cipher { |
| |
| /** |
| * Constant for decryption operation mode. |
| */ |
| public static final int DECRYPT_MODE = 2; |
| |
| /** |
| * Constant for encryption operation mode. |
| */ |
| public static final int ENCRYPT_MODE = 1; |
| |
| /** |
| * Constant indicating that the key to be unwrapped is a private key. |
| */ |
| public static final int PRIVATE_KEY = 2; |
| |
| /** |
| * Constant indicating that the key to be unwrapped is a public key. |
| */ |
| public static final int PUBLIC_KEY = 1; |
| |
| /** |
| * Constant indicating that the key to be unwrapped is a secret key. |
| */ |
| public static final int SECRET_KEY = 3; |
| |
| /** |
| * Constant for key unwrapping operation mode. |
| */ |
| public static final int UNWRAP_MODE = 4; |
| |
| /** |
| * Constant for key wrapping operation mode. |
| */ |
| public static final int WRAP_MODE = 3; |
| |
| private int mode; |
| |
| /** Items that need to be set on the Cipher instance. */ |
| private enum NeedToSet { |
| NONE, MODE, PADDING, BOTH, |
| }; |
| |
| /** |
| * The service name. |
| */ |
| private static final String SERVICE = "Cipher"; |
| |
| /** |
| * Used to access common engine functionality. |
| */ |
| private static final Engine ENGINE = new Engine(SERVICE); |
| |
| /** The attribute used for supported paddings. */ |
| private static final String ATTRIBUTE_PADDINGS = "SupportedPaddings"; |
| |
| /** The attribute used for supported modes. */ |
| private static final String ATTRIBUTE_MODES = "SupportedModes"; |
| |
| /** |
| * The provider. |
| */ |
| private Provider provider; |
| |
| /** |
| * The provider specified when instance created. |
| */ |
| private final Provider specifiedProvider; |
| |
| /** |
| * The SPI implementation. |
| */ |
| private CipherSpi spiImpl; |
| |
| /** |
| * The SPI implementation. |
| */ |
| private final CipherSpi specifiedSpi; |
| |
| /** |
| * The transformation. |
| */ |
| private final String transformation; |
| |
| /** |
| * The transformation split into parts. |
| */ |
| private final String[] transformParts; |
| |
| /** |
| * Lock held while the SPI is initializing. |
| */ |
| private final Object initLock = new Object(); |
| |
| private static SecureRandom secureRandom; |
| |
| /** |
| * Creates a new Cipher instance. |
| * |
| * @param cipherSpi |
| * the implementation delegate of the cipher. |
| * @param provider |
| * the provider of the implementation of this cipher. |
| * @param transformation |
| * the name of the transformation that this cipher performs. |
| * @throws NullPointerException |
| * if either cipherSpi is {@code null} or provider is {@code |
| * null} and {@code cipherSpi} is a {@code NullCipherSpi}. |
| */ |
| protected Cipher(CipherSpi cipherSpi, Provider provider, String transformation) { |
| if (cipherSpi == null) { |
| throw new NullPointerException("cipherSpi == null"); |
| } |
| if (!(cipherSpi instanceof NullCipherSpi) && provider == null) { |
| throw new NullPointerException("provider == null"); |
| } |
| this.specifiedProvider = provider; |
| this.specifiedSpi = cipherSpi; |
| this.transformation = transformation; |
| this.transformParts = null; |
| } |
| |
| private Cipher(String transformation, String[] transformParts, Provider provider) { |
| this.transformation = transformation; |
| this.transformParts = transformParts; |
| this.specifiedProvider = provider; |
| this.specifiedSpi = null; |
| } |
| |
| |
| /** |
| * Creates a new Cipher for the specified transformation. The installed |
| * providers are searched in order for an implementation of the specified |
| * transformation. The first found provider providing the transformation is |
| * used to create the cipher. If no provider is found an exception is |
| * thrown. |
| * |
| * @param transformation |
| * the name of the transformation to create a cipher for. |
| * @return a cipher for the requested transformation. |
| * @throws NoSuchAlgorithmException |
| * if no installed provider can provide the |
| * <i>transformation</i>, or it is {@code null}, empty or in an |
| * invalid format. |
| * @throws NoSuchPaddingException |
| * if no installed provider can provide the padding scheme in |
| * the <i>transformation</i>. |
| */ |
| public static final Cipher getInstance(String transformation) |
| throws NoSuchAlgorithmException, NoSuchPaddingException { |
| return getCipher(transformation, null); |
| } |
| |
| /** |
| * Creates a new cipher for the specified transformation provided by the |
| * specified provider. |
| * |
| * @param transformation |
| * the name of the transformation to create a cipher for. |
| * @param provider |
| * the name of the provider to ask for the transformation. |
| * @return a cipher for the requested transformation. |
| * @throws NoSuchAlgorithmException |
| * if the specified provider can not provide the |
| * <i>transformation</i>, or it is {@code null}, empty or in an |
| * invalid format. |
| * @throws NoSuchProviderException |
| * if no provider with the specified name can be found. |
| * @throws NoSuchPaddingException |
| * if the requested padding scheme in the <i>transformation</i> |
| * is not available. |
| * @throws IllegalArgumentException |
| * if the specified provider is {@code null}. |
| */ |
| public static final Cipher getInstance(String transformation, |
| String provider) throws NoSuchAlgorithmException, |
| NoSuchProviderException, NoSuchPaddingException { |
| |
| if (provider == null) { |
| throw new IllegalArgumentException("provider == null"); |
| } |
| |
| Provider p = Security.getProvider(provider); |
| if (p == null) { |
| throw new NoSuchProviderException("Provider not available: " + provider); |
| } |
| return getInstance(transformation, p); |
| } |
| |
| /** |
| * Creates a new cipher for the specified transformation. The |
| * {@code provider} supplied does not have to be registered. |
| * |
| * @param transformation |
| * the name of the transformation to create a cipher for. |
| * @param provider |
| * the provider to ask for the transformation. |
| * @return a cipher for the requested transformation. |
| * @throws NoSuchAlgorithmException |
| * if the specified provider can not provide the |
| * <i>transformation</i>, or it is {@code null}, empty or in an |
| * invalid format. |
| * @throws NoSuchPaddingException |
| * if the requested padding scheme in the <i>transformation</i> |
| * is not available. |
| * @throws IllegalArgumentException |
| * if the provider is {@code null}. |
| */ |
| public static final Cipher getInstance(String transformation, |
| Provider provider) throws NoSuchAlgorithmException, |
| NoSuchPaddingException { |
| if (provider == null) { |
| throw new IllegalArgumentException("provider == null"); |
| } |
| return getCipher(transformation, provider); |
| } |
| |
| private static NoSuchAlgorithmException invalidTransformation(String transformation) |
| throws NoSuchAlgorithmException { |
| throw new NoSuchAlgorithmException("Invalid transformation: " + transformation); |
| } |
| |
| /** |
| * Create a Cipher instance but don't choose a CipherSpi until we have more |
| * information. |
| */ |
| private static Cipher getCipher(String transformation, Provider provider) |
| throws NoSuchAlgorithmException, NoSuchPaddingException { |
| if (transformation == null || transformation.isEmpty()) { |
| throw invalidTransformation(transformation); |
| } |
| |
| String[] transformParts = checkTransformation(transformation); |
| |
| if (tryCombinations(null /* key */, provider, transformParts) == null) { |
| if (provider == null) { |
| throw new NoSuchAlgorithmException("No provider found for " + transformation); |
| } else { |
| throw new NoSuchAlgorithmException("Provider " + provider.getName() |
| + " does not provide " + transformation); |
| } |
| } |
| return new Cipher(transformation, transformParts, provider); |
| } |
| |
| private static String[] checkTransformation(String transformation) |
| throws NoSuchAlgorithmException { |
| // ignore an extra prefix / characters such as in |
| // "/DES/CBC/PKCS5Padding" http://b/3387688 |
| if (transformation.startsWith("/")) { |
| transformation = transformation.substring(1); |
| } |
| // 'transformation' should be of the form "algorithm/mode/padding". |
| String[] pieces = transformation.split("/"); |
| if (pieces.length > 3) { |
| throw invalidTransformation(transformation); |
| } |
| // Empty or missing pieces are represented by null. |
| String[] result = new String[3]; |
| for (int i = 0; i < pieces.length; ++i) { |
| String piece = pieces[i].trim(); |
| if (!piece.isEmpty()) { |
| result[i] = piece; |
| } |
| } |
| // You MUST specify an algorithm. |
| if (result[0] == null) { |
| throw invalidTransformation(transformation); |
| } |
| if (!(result[1] == null && result[2] == null) && (result[1] == null || result[2] == null)) { |
| throw invalidTransformation(transformation); |
| } |
| return result; |
| } |
| |
| /** |
| * Makes sure a CipherSpi that matches this type is selected. |
| * |
| * If {@code key != null} then it assumes that a suitable provider exists for this instance |
| * (used by {@link #init}. |
| * |
| * @throws InvalidKeyException if the specified key cannot be used to |
| * initialize this cipher. |
| */ |
| private CipherSpi getSpi(Key key) throws InvalidKeyException { |
| if (specifiedSpi != null) { |
| return specifiedSpi; |
| } |
| |
| synchronized (initLock) { |
| // This is not only a matter of performance. Many methods like update, doFinal, etc. |
| // call {@code #getSpi()} (ie, {@code #getSpi(null /* key */)}) and without this |
| // shortcut they would override an spi that was chosen using the key. |
| if (spiImpl != null && key == null) { |
| return spiImpl; |
| } |
| |
| final Engine.SpiAndProvider sap = tryCombinations( |
| key, specifiedProvider, transformParts); |
| |
| if (sap == null) { |
| if (key == null) { |
| throw new ProviderException("No provider for " + transformation); |
| } |
| // Since the key is not null, a suitable provider exists, |
| // and it is an InvalidKeyException. |
| throw new InvalidKeyException( |
| "No provider offers " + transformation + " for " + key.getAlgorithm() |
| + " key of class " + key.getClass().getName() |
| + " and export format " + key.getFormat()); |
| } |
| |
| spiImpl = (CipherSpi) sap.spi; |
| provider = sap.provider; |
| |
| return spiImpl; |
| } |
| } |
| |
| /** |
| * Convenience call when the Key is not available. |
| */ |
| private CipherSpi getSpi() { |
| try { |
| return getSpi(null); |
| } catch (InvalidKeyException e) { |
| throw new IllegalStateException("InvalidKeyException thrown when key == null", e); |
| } |
| } |
| |
| /** |
| * Returns the {@code CipherSpi} backing this {@code Cipher} or {@code null} if no |
| * {@code CipherSpi} is backing this {@code Cipher}. |
| * |
| * @hide |
| */ |
| public CipherSpi getCurrentSpi() { |
| if (specifiedSpi != null) { |
| return specifiedSpi; |
| } |
| |
| synchronized (initLock) { |
| return spiImpl; |
| } |
| } |
| |
| /** |
| * Try all combinations of mode strings: |
| * |
| * <pre> |
| * [cipher]/[mode]/[padding] |
| * [cipher]/[mode] |
| * [cipher]//[padding] |
| * [cipher] |
| * </pre> |
| */ |
| private static Engine.SpiAndProvider tryCombinations(Key key, Provider provider, |
| String[] transformParts) { |
| Engine.SpiAndProvider sap = null; |
| |
| if (transformParts[1] != null && transformParts[2] != null) { |
| sap = tryTransform(key, provider, transformParts[0] + "/" + transformParts[1] + "/" |
| + transformParts[2], transformParts, NeedToSet.NONE); |
| if (sap != null) { |
| return sap; |
| } |
| } |
| |
| if (transformParts[1] != null) { |
| sap = tryTransform(key, provider, transformParts[0] + "/" + transformParts[1], |
| transformParts, NeedToSet.PADDING); |
| if (sap != null) { |
| return sap; |
| } |
| } |
| |
| if (transformParts[2] != null) { |
| sap = tryTransform(key, provider, transformParts[0] + "//" + transformParts[2], |
| transformParts, NeedToSet.MODE); |
| if (sap != null) { |
| return sap; |
| } |
| } |
| |
| return tryTransform(key, provider, transformParts[0], transformParts, NeedToSet.BOTH); |
| } |
| |
| private static Engine.SpiAndProvider tryTransform(Key key, Provider provider, String transform, |
| String[] transformParts, NeedToSet type) { |
| if (provider != null) { |
| Provider.Service service = provider.getService(SERVICE, transform); |
| if (service == null) { |
| return null; |
| } |
| return tryTransformWithProvider(transformParts, type, service); |
| } |
| ArrayList<Provider.Service> services = ENGINE.getServices(transform); |
| if (services == null || services.isEmpty()) { |
| return null; |
| } |
| for (Provider.Service service : services) { |
| if (key == null || service.supportsParameter(key)) { |
| Engine.SpiAndProvider sap = tryTransformWithProvider(transformParts, type, service); |
| if (sap != null) { |
| return sap; |
| } |
| } |
| } |
| return null; |
| } |
| |
| private static Engine.SpiAndProvider tryTransformWithProvider(String[] transformParts, |
| NeedToSet type, Provider.Service service) { |
| try { |
| /* |
| * Check to see if the Cipher even supports the attributes before |
| * trying to instantiate it. |
| */ |
| if (!matchAttribute(service, ATTRIBUTE_MODES, transformParts[1]) |
| || !matchAttribute(service, ATTRIBUTE_PADDINGS, transformParts[2])) { |
| return null; |
| } |
| |
| Engine.SpiAndProvider sap = ENGINE.getInstance(service, null); |
| if (sap.spi == null || sap.provider == null) { |
| return null; |
| } |
| if (!(sap.spi instanceof CipherSpi)) { |
| return null; |
| } |
| CipherSpi spi = (CipherSpi) sap.spi; |
| if (((type == NeedToSet.MODE) || (type == NeedToSet.BOTH)) |
| && (transformParts[1] != null)) { |
| spi.engineSetMode(transformParts[1]); |
| } |
| if (((type == NeedToSet.PADDING) || (type == NeedToSet.BOTH)) |
| && (transformParts[2] != null)) { |
| spi.engineSetPadding(transformParts[2]); |
| } |
| return sap; |
| } catch (NoSuchAlgorithmException ignored) { |
| } catch (NoSuchPaddingException ignored) { |
| } |
| return null; |
| } |
| |
| /** |
| * If the attribute listed exists, check that it matches the regular |
| * expression. |
| */ |
| private static boolean matchAttribute(Service service, String attr, String value) { |
| if (value == null) { |
| return true; |
| } |
| final String pattern = service.getAttribute(attr); |
| if (pattern == null) { |
| return true; |
| } |
| final String valueUc = value.toUpperCase(Locale.US); |
| return valueUc.matches(pattern.toUpperCase(Locale.US)); |
| } |
| |
| /** |
| * Returns the provider of this cipher instance. |
| * |
| * @return the provider of this cipher instance. |
| */ |
| public final Provider getProvider() { |
| getSpi(); |
| return provider; |
| } |
| |
| /** |
| * Returns the name of the algorithm of this cipher instance. |
| * <p> |
| * This is the name of the <i>transformation</i> argument used in the |
| * {@code getInstance} call creating this object. |
| * |
| * @return the name of the algorithm of this cipher instance. |
| */ |
| public final String getAlgorithm() { |
| return transformation; |
| } |
| |
| /** |
| * Returns this ciphers block size (in bytes). |
| * |
| * @return this ciphers block size. |
| */ |
| public final int getBlockSize() { |
| return getSpi().engineGetBlockSize(); |
| } |
| |
| /** |
| * Returns the length in bytes an output buffer needs to be when this cipher |
| * is updated with {@code inputLen} bytes. |
| * |
| * @param inputLen |
| * the number of bytes of the input. |
| * @return the output buffer length for the input length. |
| * @throws IllegalStateException |
| * if this cipher instance is in an invalid state. |
| */ |
| public final int getOutputSize(int inputLen) { |
| if (mode == 0) { |
| throw new IllegalStateException("Cipher has not yet been initialized"); |
| } |
| return getSpi().engineGetOutputSize(inputLen); |
| } |
| |
| /** |
| * Returns the <i>initialization vector</i> for this cipher instance. |
| * |
| * @return the <i>initialization vector</i> for this cipher instance. |
| */ |
| public final byte[] getIV() { |
| return getSpi().engineGetIV(); |
| } |
| |
| /** |
| * Returns the parameters that where used to create this cipher instance. |
| * <p> |
| * 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. |
| */ |
| public final AlgorithmParameters getParameters() { |
| return getSpi().engineGetParameters(); |
| } |
| |
| /** |
| * Returns the exemption mechanism associated with this cipher. |
| * |
| * @return currently {@code null} |
| */ |
| public final ExemptionMechanism getExemptionMechanism() { |
| //FIXME implement getExemptionMechanism |
| |
| // try { |
| // return ExemptionMechanism.getInstance(transformation, provider); |
| // } catch (NoSuchAlgorithmException e) { |
| return null; |
| // } |
| |
| } |
| |
| private void checkMode(int mode) { |
| if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE && mode != UNWRAP_MODE |
| && mode != WRAP_MODE) { |
| throw new InvalidParameterException("Invalid mode: " + mode); |
| } |
| } |
| |
| /** |
| * Initializes this cipher instance with the specified key. |
| * <p> |
| * The cipher is initialized for the specified operational mode (one of: |
| * encryption, decryption, key wrapping or key unwrapping) depending on |
| * {@code opmode}. |
| * <p> |
| * If this cipher instance needs any algorithm parameters or random values |
| * that the specified key can not provide, the underlying implementation of |
| * this cipher is supposed to generate the required parameters (using its |
| * provider or random values). |
| * <p> |
| * When a cipher instance is initialized by a call to any of the {@code |
| * init} methods, the state of the instance is overridden, meaning that it |
| * is equivalent to creating a new instance and calling its {@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. |
| * @throws InvalidKeyException |
| * if the specified key can not be used to initialize this |
| * cipher instance. |
| */ |
| public final void init(int opmode, Key key) throws InvalidKeyException { |
| if (secureRandom == null) { |
| // In theory it might be thread-unsafe but in the given case it's OK |
| // since it does not matter which SecureRandom instance is passed |
| // to the init() |
| secureRandom = new SecureRandom(); |
| } |
| init(opmode, key, secureRandom); |
| } |
| |
| /** |
| * Initializes this cipher instance with the specified key and a source of |
| * randomness. |
| * <p> |
| * The cipher is initialized for the specified operational mode (one of: |
| * encryption, decryption, key wrapping or key unwrapping) depending on |
| * {@code opmode}. |
| * <p> |
| * If this cipher instance needs any algorithm parameters or random values |
| * that the specified key can not provide, 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}; |
| * <p> |
| * 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 can not be used to initialize this |
| * cipher instance. |
| * @throws InvalidParameterException |
| * if the specified opmode is invalid. |
| */ |
| public final void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException { |
| checkMode(opmode); |
| // FIXME InvalidKeyException |
| // if keysize exceeds the maximum allowable keysize |
| // (jurisdiction policy files) |
| getSpi(key).engineInit(opmode, key, random); |
| mode = opmode; |
| } |
| |
| /** |
| * Initializes this cipher instance with the specified key and algorithm |
| * parameters. |
| * <p> |
| * The cipher is initialized for the specified operational mode (one of: |
| * encryption, decryption, key wrapping or key unwrapping). |
| * <p> |
| * 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). |
| * <p> |
| * 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. |
| * @throws InvalidKeyException |
| * if the specified key can not be used to initialize this |
| * cipher instance. |
| * @throws InvalidAlgorithmParameterException |
| * it the specified parameters are inappropriate for this |
| * cipher. |
| */ |
| public final void init(int opmode, Key key, AlgorithmParameterSpec params) |
| throws InvalidKeyException, InvalidAlgorithmParameterException { |
| if (secureRandom == null) { |
| secureRandom = new SecureRandom(); |
| } |
| init(opmode, key, params, secureRandom); |
| } |
| |
| /** |
| * Initializes this cipher instance with the specified key, algorithm |
| * parameters and a source of randomness. |
| * <p> |
| * The cipher is initialized for the specified operational mode (one of: |
| * encryption, decryption, key wrapping or key unwrapping) depending on |
| * {@code opmode}. |
| * <p> |
| * 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}; |
| * <p> |
| * When a cipher instance is initialized by a call to any of the {@code |
| * init} methods, the state of the instance is overridden, meaning that 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 can not be used to initialize this |
| * cipher instance. |
| * @throws InvalidAlgorithmParameterException |
| * it the specified parameters are inappropriate for this |
| * cipher. |
| * @throws InvalidParameterException |
| * if the specified {@code opmode} is invalid. |
| */ |
| public final void init(int opmode, Key key, AlgorithmParameterSpec params, |
| SecureRandom random) throws InvalidKeyException, |
| InvalidAlgorithmParameterException { |
| checkMode(opmode); |
| // FIXME InvalidKeyException |
| // if keysize exceeds the maximum allowable keysize |
| // (jurisdiction policy files) |
| // FIXME InvalidAlgorithmParameterException |
| // cryptographic strength exceed the legal limits |
| // (jurisdiction policy files) |
| getSpi(key).engineInit(opmode, key, params, random); |
| mode = opmode; |
| } |
| |
| /** |
| * Initializes this cipher instance with the specified key and algorithm |
| * parameters. |
| * <p> |
| * The cipher is initialized for the specified operation (one of: |
| * encryption, decryption, key wrapping or key unwrapping) depending on |
| * {@code opmode}. |
| * <p> |
| * 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). |
| * <p> |
| * When a cipher instance is initialized by a call to any of the {@code |
| * init} methods, the state of the instance is overridden, meaning that 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. |
| * @throws InvalidKeyException |
| * if the specified key can not be used to initialize this |
| * cipher instance. |
| * @throws InvalidAlgorithmParameterException |
| * it the specified parameters are inappropriate for this |
| * cipher. |
| */ |
| public final void init(int opmode, Key key, AlgorithmParameters params) |
| throws InvalidKeyException, InvalidAlgorithmParameterException { |
| if (secureRandom == null) { |
| secureRandom = new SecureRandom(); |
| } |
| init(opmode, key, params, secureRandom); |
| } |
| |
| /** |
| * Initializes this cipher instance with the specified key, algorithm |
| * parameters and a source of randomness. |
| * <p> |
| * The cipher will be initialized for the specified operation (one of: |
| * encryption, decryption, key wrapping or key unwrapping) depending on |
| * {@code opmode}. |
| * <p> |
| * 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}. |
| * <p> |
| * 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 can not be used to initialize this |
| * cipher instance. |
| * @throws InvalidAlgorithmParameterException |
| * if the specified parameters are inappropriate for this |
| * cipher. |
| * @throws InvalidParameterException |
| * if the specified {@code opmode} is invalid. |
| */ |
| public final void init(int opmode, Key key, AlgorithmParameters params, |
| SecureRandom random) throws InvalidKeyException, |
| InvalidAlgorithmParameterException { |
| checkMode(opmode); |
| // FIXME InvalidKeyException |
| // if keysize exceeds the maximum allowable keysize |
| // (jurisdiction policy files) |
| // FIXME InvalidAlgorithmParameterException |
| // cryptographic strength exceed the legal limits |
| // (jurisdiction policy files) |
| getSpi(key).engineInit(opmode, key, params, random); |
| mode = opmode; |
| } |
| |
| /** |
| * Initializes this cipher instance with the public key from the specified |
| * certificate. |
| * <p> |
| * The cipher will be initialized for the specified operation (one of: |
| * encryption, decryption, key wrapping or key unwrapping) depending on |
| * {@code opmode}. |
| * <p> |
| * It the type of the certificate is X.509 and the certificate has a <i>key |
| * usage</i> extension field marked as critical, the specified {@code |
| * opmode} has the be enabled for this key, otherwise an {@code |
| * InvalidKeyException} is thrown. |
| * <p> |
| * If this cipher instance needs any algorithm parameters that the key in |
| * the certificate can not provide, the underlying implementation of this |
| * cipher is supposed to generate the required parameters (using its |
| * provider or random values). |
| * <p> |
| * 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 certificate |
| * the certificate. |
| * @throws InvalidKeyException |
| * if the public key in the certificate can not be used to |
| * initialize this cipher instance. |
| */ |
| public final void init(int opmode, Certificate certificate) |
| throws InvalidKeyException { |
| if (secureRandom == null) { |
| secureRandom = new SecureRandom(); |
| } |
| init(opmode, certificate, secureRandom); |
| } |
| |
| /** |
| * Initializes this cipher instance with the public key from the specified |
| * certificate and a source of randomness. |
| * <p> |
| * The cipher will be initialized for the specified operation (one of: |
| * encryption, decryption, key wrapping or key unwrapping) depending on |
| * {@code opmode}. |
| * <p> |
| * It the type of the certificate is X.509 and the certificate has a <i>key |
| * usage</i> extension field marked as critical, the specified {@code |
| * opmode} has the be enabled for this key, otherwise an {@code |
| * InvalidKeyException} is thrown. |
| * <p> |
| * If this cipher instance needs any algorithm parameters that the key in |
| * the certificate can not provide, 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}. |
| * <p> |
| * 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 certificate |
| * the certificate. |
| * @param random |
| * the source of randomness to be used. |
| * @throws InvalidKeyException |
| * if the public key in the certificate can not be used to |
| * initialize this cipher instance. |
| */ |
| public final void init(int opmode, Certificate certificate, |
| SecureRandom random) throws InvalidKeyException { |
| checkMode(opmode); |
| if (certificate instanceof X509Certificate) { |
| Set<String> ce = ((X509Certificate) certificate).getCriticalExtensionOIDs(); |
| boolean critical = false; |
| if (ce != null && !ce.isEmpty()) { |
| for (String oid : ce) { |
| if (oid.equals("2.5.29.15")) { // KeyUsage OID = 2.5.29.15 |
| critical = true; |
| break; |
| } |
| } |
| if (critical) { |
| boolean[] keyUsage = ((X509Certificate) certificate).getKeyUsage(); |
| // As specified in RFC 3280: |
| // Internet X.509 Public Key Infrastructure |
| // Certificate and Certificate Revocation List (CRL) Profile. |
| // Section 4.2.1.3 Key Usage |
| // http://www.ietf.org/rfc/rfc3280.txt |
| // |
| // KeyUsage ::= BIT STRING {digitalSignature (0), |
| // nonRepudiation (1), |
| // keyEncipherment (2), |
| // dataEncipherment (3), |
| // keyAgreement (4), |
| // keyCertSign (5), |
| // cRLSign (6), |
| // encipherOnly (7), |
| // decipherOnly (8) } |
| if (keyUsage != null) { |
| if (opmode == ENCRYPT_MODE && !keyUsage[3]) { |
| throw new InvalidKeyException("The public key in the certificate " |
| + "cannot be used for ENCRYPT_MODE"); |
| } else if (opmode == WRAP_MODE && !keyUsage[2]) { |
| throw new InvalidKeyException("The public key in the certificate " |
| + "cannot be used for WRAP_MODE"); |
| } |
| } |
| } |
| } |
| } |
| // FIXME InvalidKeyException |
| // if keysize exceeds the maximum allowable keysize |
| // (jurisdiction policy files) |
| final Key key = certificate.getPublicKey(); |
| getSpi(key).engineInit(opmode, key, random); |
| mode = opmode; |
| } |
| |
| /** |
| * Continues a multi-part transformation (encryption or decryption). The |
| * transformed bytes are returned. |
| * |
| * @param input |
| * the input bytes 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 {@code null}. |
| */ |
| public final byte[] update(byte[] input) { |
| if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { |
| throw new IllegalStateException(); |
| } |
| if (input == null) { |
| throw new IllegalArgumentException("input == null"); |
| } |
| if (input.length == 0) { |
| return null; |
| } |
| return getSpi().engineUpdate(input, 0, input.length); |
| } |
| |
| /** |
| * 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 {@code inputLen} is zero. |
| * @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. |
| */ |
| public final byte[] update(byte[] input, int inputOffset, int inputLen) { |
| if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { |
| throw new IllegalStateException(); |
| } |
| if (input == null) { |
| throw new IllegalArgumentException("input == null"); |
| } |
| checkInputOffsetAndCount(input.length, inputOffset, inputLen); |
| if (inputLen == 0) { |
| return null; |
| } |
| return getSpi().engineUpdate(input, inputOffset, inputLen); |
| } |
| |
| private static void checkInputOffsetAndCount(int inputArrayLength, |
| int inputOffset, |
| int inputLen) { |
| if ((inputOffset | inputLen) < 0 |
| || inputOffset > inputArrayLength |
| || inputArrayLength - inputOffset < inputLen) { |
| throw new IllegalArgumentException("input.length=" + inputArrayLength |
| + "; inputOffset=" + inputOffset |
| + "; inputLen=" + inputLen); |
| } |
| } |
| |
| /** |
| * Continues a multi-part transformation (encryption or decryption). The |
| * transformed bytes are stored in the {@code output} buffer. |
| * <p> |
| * 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. |
| * @return the number of bytes placed in output. |
| * @throws ShortBufferException |
| * if the size of the {@code output} buffer is too small. |
| * @throws IllegalStateException |
| * if this cipher instance is not initialized for encryption or |
| * decryption. |
| * @throws IllegalArgumentException |
| * if the input is {@code null}, the output is {@code null}, or |
| * if {@code inputOffset} and {@code inputLen} do not specify a |
| * valid chunk in the input buffer. |
| */ |
| public final int update(byte[] input, int inputOffset, int inputLen, |
| byte[] output) throws ShortBufferException { |
| return update(input, inputOffset, inputLen, output, 0); |
| } |
| |
| /** |
| * Continues a multi-part transformation (encryption or decryption). The |
| * transformed bytes are stored in the {@code output} buffer. |
| * <p> |
| * 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. |
| * @throws IllegalStateException |
| * if this cipher instance is not initialized for encryption or |
| * decryption. |
| * @throws IllegalArgumentException |
| * if the input is {@code null}, the output is {@code null}, or |
| * if {@code inputOffset} and {@code inputLen} do not specify a |
| * valid chunk in the input buffer. |
| */ |
| public final int update(byte[] input, int inputOffset, int inputLen, |
| byte[] output, int outputOffset) throws ShortBufferException { |
| if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { |
| throw new IllegalStateException(); |
| } |
| if (input == null) { |
| throw new IllegalArgumentException("input == null"); |
| } |
| if (output == null) { |
| throw new IllegalArgumentException("output == null"); |
| } |
| if (outputOffset < 0) { |
| throw new IllegalArgumentException("outputOffset < 0. outputOffset=" + outputOffset); |
| } |
| checkInputOffsetAndCount(input.length, inputOffset, inputLen); |
| if (input.length == 0) { |
| return 0; |
| } |
| return getSpi().engineUpdate(input, inputOffset, inputLen, output, |
| outputOffset); |
| } |
| |
| /** |
| * 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. |
| * <p> |
| * 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. |
| * @throws IllegalStateException |
| * if this cipher instance is not initialized for encryption or |
| * decryption. |
| * @throws IllegalArgumentException |
| * if the input buffer and the output buffer are the identical |
| * object. |
| */ |
| public final int update(ByteBuffer input, ByteBuffer output) |
| throws ShortBufferException { |
| if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { |
| throw new IllegalStateException(); |
| } |
| if (input == output) { |
| throw new IllegalArgumentException("input == output"); |
| } |
| return getSpi().engineUpdate(input, output); |
| } |
| |
| /** |
| * 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. |
| * <p> |
| * 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 |
| * @throws IllegalStateException |
| * if this cipher instance is not initialized for encryption or |
| * decryption. |
| * @throws IllegalArgumentException |
| * if {@code input} is {@code null} |
| * @throws UnsupportedOperationException if the cipher does not support AEAD |
| * @since 1.7 |
| */ |
| public final void updateAAD(byte[] input) { |
| if (input == null) { |
| throw new IllegalArgumentException("input == null"); |
| } |
| if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { |
| throw new IllegalStateException(); |
| } |
| if (input.length == 0) { |
| return; |
| } |
| getSpi().engineUpdateAAD(input, 0, input.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. |
| * <p> |
| * 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 |
| */ |
| public final void updateAAD(byte[] input, int inputOffset, int inputLen) { |
| if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { |
| throw new IllegalStateException(); |
| } |
| if (input == null) { |
| throw new IllegalArgumentException("input == null"); |
| } |
| checkInputOffsetAndCount(input.length, inputOffset, inputLen); |
| if (input.length == 0) { |
| return; |
| } |
| getSpi().engineUpdateAAD(input, inputOffset, inputLen); |
| } |
| |
| /** |
| * 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. |
| * <p> |
| * This is only usable with cipher modes that support Authenticated |
| * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM). |
| * |
| * @param input buffer of AAD to be used |
| * @throws IllegalStateException |
| * if this cipher instance is not initialized for encryption or |
| * decryption. |
| * @throws UnsupportedOperationException if the cipher does not support AEAD |
| * @since 1.7 |
| */ |
| public final void updateAAD(ByteBuffer input) { |
| if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { |
| throw new IllegalStateException("Cipher is not initialized"); |
| } |
| if (input == null) { |
| throw new IllegalArgumentException("input == null"); |
| } |
| getSpi().engineUpdateAAD(input); |
| } |
| |
| /** |
| * Finishes a multi-part transformation (encryption or decryption). |
| * <p> |
| * Processes any bytes that may have been buffered in previous {@code |
| * update} calls. |
| * |
| * @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. |
| * @throws IllegalStateException |
| * if this cipher instance is not initialized for encryption or |
| * decryption. |
| */ |
| public final byte[] doFinal() throws IllegalBlockSizeException, |
| BadPaddingException { |
| if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { |
| throw new IllegalStateException(); |
| } |
| return getSpi().engineDoFinal(null, 0, 0); |
| } |
| |
| /** |
| * Finishes a multi-part transformation (encryption or decryption). |
| * <p> |
| * Processes any bytes that may have been buffered in previous {@code |
| * update} calls. |
| * <p> |
| * The final transformed bytes are stored in the {@code output} buffer. |
| * |
| * @param output |
| * the output buffer. |
| * @param outputOffset |
| * the offset in the output buffer. |
| * @return the number of bytes placed in the output buffer. |
| * @throws IllegalBlockSizeException |
| * if the size of the resulting bytes is not a multiple of the |
| * cipher block size. |
| * @throws ShortBufferException |
| * if the size of the {@code output} buffer is too small. |
| * @throws BadPaddingException |
| * if the padding of the data does not match the padding scheme. |
| * @throws IllegalStateException |
| * if this cipher instance is not initialized for encryption or |
| * decryption. |
| */ |
| public final int doFinal(byte[] output, int outputOffset) |
| throws IllegalBlockSizeException, ShortBufferException, |
| BadPaddingException { |
| if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { |
| throw new IllegalStateException(); |
| } |
| if (outputOffset < 0) { |
| throw new IllegalArgumentException("outputOffset < 0. outputOffset=" + outputOffset); |
| } |
| return getSpi().engineDoFinal(null, 0, 0, output, outputOffset); |
| } |
| |
| /** |
| * Finishes a multi-part transformation (encryption or decryption). |
| * <p> |
| * Processes the bytes in {@code input} buffer, and any bytes that have been |
| * buffered in previous {@code update} calls. |
| * |
| * @param input |
| * the input buffer. |
| * @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. |
| * @throws IllegalStateException |
| * if this cipher instance is not initialized for encryption or |
| * decryption. |
| */ |
| public final byte[] doFinal(byte[] input) throws IllegalBlockSizeException, |
| BadPaddingException { |
| if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { |
| throw new IllegalStateException(); |
| } |
| return getSpi().engineDoFinal(input, 0, input.length); |
| } |
| |
| /** |
| * Finishes a multi-part transformation (encryption or decryption). |
| * <p> |
| * 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. |
| * @throws IllegalStateException |
| * if this cipher instance is not initialized for encryption or |
| * decryption. |
| * @throws IllegalArgumentException |
| * if {@code inputOffset} and {@code inputLen} do not specify an |
| * valid chunk in the input buffer. |
| */ |
| public final byte[] doFinal(byte[] input, int inputOffset, int inputLen) |
| throws IllegalBlockSizeException, BadPaddingException { |
| if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { |
| throw new IllegalStateException(); |
| } |
| checkInputOffsetAndCount(input.length, inputOffset, inputLen); |
| return getSpi().engineDoFinal(input, inputOffset, inputLen); |
| } |
| |
| /** |
| * Finishes a multi-part transformation (encryption or decryption). |
| * <p> |
| * 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. |
| * @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. |
| * @throws IllegalStateException |
| * if this cipher instance is not initialized for encryption or |
| * decryption. |
| * @throws IllegalArgumentException |
| * if {@code inputOffset} and {@code inputLen} do not specify an |
| * valid chunk in the input buffer. |
| */ |
| public final int doFinal(byte[] input, int inputOffset, int inputLen, |
| byte[] output) throws ShortBufferException, |
| IllegalBlockSizeException, BadPaddingException { |
| return doFinal(input, inputOffset, inputLen, output, 0); |
| } |
| |
| /** |
| * Finishes a multi-part transformation (encryption or decryption). |
| * <p> |
| * 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. |
| * @throws IllegalStateException |
| * if this cipher instance is not initialized for encryption or |
| * decryption. |
| * @throws IllegalArgumentException |
| * if {@code inputOffset} and {@code inputLen} do not specify an |
| * valid chunk in the input buffer. |
| */ |
| public final int doFinal(byte[] input, int inputOffset, int inputLen, |
| byte[] output, int outputOffset) throws ShortBufferException, |
| IllegalBlockSizeException, BadPaddingException { |
| if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { |
| throw new IllegalStateException(); |
| } |
| checkInputOffsetAndCount(input.length, inputOffset, inputLen); |
| return getSpi().engineDoFinal(input, inputOffset, inputLen, output, |
| outputOffset); |
| } |
| |
| /** |
| * Finishes a multi-part transformation (encryption or decryption). |
| * <p> |
| * 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. |
| */ |
| public final int doFinal(ByteBuffer input, ByteBuffer output) |
| throws ShortBufferException, IllegalBlockSizeException, |
| BadPaddingException { |
| if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { |
| throw new IllegalStateException(); |
| } |
| if (input == output) { |
| throw new IllegalArgumentException("input == output"); |
| } |
| return getSpi().engineDoFinal(input, output); |
| } |
| |
| /** |
| * Wraps a key using this cipher instance. |
| * |
| * @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 can not wrap this key. |
| * @throws IllegalStateException |
| * if this cipher instance is not initialized for wrapping. |
| */ |
| public final byte[] wrap(Key key) throws IllegalBlockSizeException, |
| InvalidKeyException { |
| if (mode != WRAP_MODE) { |
| throw new IllegalStateException(); |
| } |
| return getSpi().engineWrap(key); |
| } |
| |
| /** |
| * Unwraps a key using this cipher instance. |
| * |
| * @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>, <code>PRIVATE_KEY} or {@code PUBLIC_KEY}) |
| * @return the unwrapped key |
| * @throws InvalidKeyException |
| * if the {@code wrappedKey} can not 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}. |
| * @throws IllegalStateException |
| * if this cipher instance is not initialized for unwrapping. |
| */ |
| public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, |
| int wrappedKeyType) throws InvalidKeyException, |
| NoSuchAlgorithmException { |
| if (mode != UNWRAP_MODE) { |
| throw new IllegalStateException(); |
| } |
| return getSpi().engineUnwrap(wrappedKey, wrappedKeyAlgorithm, |
| wrappedKeyType); |
| } |
| |
| /** |
| * Returns the maximum key length for the specified transformation. |
| * |
| * @param transformation |
| * the transformation name. |
| * @return the maximum key length, currently {@code Integer.MAX_VALUE}. |
| * @throws NoSuchAlgorithmException |
| * if no provider for the specified {@code transformation} can |
| * be found. |
| * @throws NullPointerException |
| * if {@code transformation} is {@code null}. |
| */ |
| public static final int getMaxAllowedKeyLength(String transformation) |
| throws NoSuchAlgorithmException { |
| if (transformation == null) { |
| throw new NullPointerException("transformation == null"); |
| } |
| checkTransformation(transformation); |
| //FIXME jurisdiction policy files |
| return Integer.MAX_VALUE; |
| } |
| |
| /** |
| * Returns the maximum cipher parameter value for the specified |
| * transformation. If there is no maximum limit, {@code null} is returned. |
| * |
| * @param transformation |
| * the transformation name. |
| * @return a parameter spec holding the maximum value or {@code null}. |
| * Currently {@code null}. |
| * @throws NoSuchAlgorithmException |
| * if no provider for the specified {@code transformation} can |
| * be found. |
| * @throws NullPointerException |
| * if {@code transformation} is {@code null}. |
| */ |
| public static final AlgorithmParameterSpec getMaxAllowedParameterSpec( |
| String transformation) throws NoSuchAlgorithmException { |
| if (transformation == null) { |
| throw new NullPointerException("transformation == null"); |
| } |
| checkTransformation(transformation); |
| //FIXME jurisdiction policy files |
| return null; |
| } |
| } |