/* * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/** * This class provides the functionality of a cryptographic cipher for * encryption and decryption. It forms the core of the Java Cryptographic * Extension (JCE) framework. * * <p>In order to create a {@code Cipher} object, the application calls the * cipher's {@code getInstance} method, and passes the name of the * requested <i>transformation</i> to it. Optionally, the name of a provider * may be specified. * * <p>A <i>transformation</i> is a string that describes the operation (or * set of operations) to be performed on the given input, to produce some * output. A transformation always includes the name of a cryptographic * algorithm (e.g., <i>AES</i>), and may be followed by a feedback mode and * padding scheme. * * <p> A transformation is of the form: * * <ul> * <li>"<i>algorithm/mode/padding</i>" or * * <li>"<i>algorithm</i>" * </ul> * * <P> (in the latter case, * provider-specific default values for the mode and padding scheme are used). * For example, the following is a valid transformation: * * <pre> * Cipher c = Cipher.getInstance("<i>AES/CBC/PKCS5Padding</i>"); * </pre> * * Using modes such as {@code CFB} and {@code OFB}, block * ciphers can encrypt data in units smaller than the cipher's actual * block size. When requesting such a mode, you may optionally specify * the number of bits to be processed at a time by appending this number * to the mode name as shown in the "{@code AES/CFB8/NoPadding}" and * "{@code AES/OFB32/PKCS5Padding}" transformations. If no such * number is specified, a provider-specific default is used. * (See the * {@extLink security_guide_jdk_providers JDK Providers Documentation} * for the JDK Providers default values.) * Thus, block ciphers can be turned into byte-oriented stream ciphers by * using an 8 bit mode such as CFB8 or OFB8. * <p> * Modes such as Authenticated Encryption with Associated Data (AEAD) * provide authenticity assurances for both confidential data and * Additional Associated Data (AAD) that is not encrypted. (Please see * <a href="http://www.ietf.org/rfc/rfc5116.txt"> RFC 5116 </a> for more * information on AEAD and AAD algorithms such as GCM/CCM.) Both * confidential and AAD data can be used when calculating the * authentication tag (similar to a {@link Mac}). This tag is appended * to the ciphertext during encryption, and is verified on decryption. * <p> * AEAD modes such as GCM/CCM perform all AAD authenticity calculations * before starting the ciphertext authenticity calculations. To avoid * implementations having to internally buffer ciphertext, all AAD data * must be supplied to GCM/CCM implementations (via the {@code updateAAD} * methods) <b>before</b> the ciphertext is processed (via * the {@code update} and {@code doFinal} methods). * <p> * Note that GCM mode has a uniqueness requirement on IVs used in * encryption with a given key. When IVs are repeated for GCM * encryption, such usages are subject to forgery attacks. Thus, after * each encryption operation using GCM mode, callers should re-initialize * the {@code Cipher} objects with GCM parameters which have a different IV * value. * <pre> * GCMParameterSpec s = ...; * cipher.init(..., s); * * // If the GCM parameters were generated by the provider, it can * // be retrieved by: * // cipher.getParameters().getParameterSpec(GCMParameterSpec.class); * * cipher.updateAAD(...); // AAD * cipher.update(...); // Multi-part update * cipher.doFinal(...); // conclusion of operation * * // Use a different IV value for every encryption * byte[] newIv = ...; * s = new GCMParameterSpec(s.getTLen(), newIv); * cipher.init(..., s); * ... * * </pre> * The ChaCha20 and ChaCha20-Poly1305 algorithms have a similar requirement * for unique nonces with a given key. After each encryption or decryption * operation, callers should re-initialize their ChaCha20 or ChaCha20-Poly1305 * ciphers with parameters that specify a different nonce value. Please * see <a href="https://tools.ietf.org/html/rfc7539">RFC 7539</a> for more * information on the ChaCha20 and ChaCha20-Poly1305 algorithms. * <p> * Every implementation of the Java platform is required to support * the following standard {@code Cipher} object transformations with * the keysizes in parentheses: * <ul> * <li>{@code AES/CBC/NoPadding} (128)</li> * <li>{@code AES/CBC/PKCS5Padding} (128)</li> * <li>{@code AES/ECB/NoPadding} (128)</li> * <li>{@code AES/ECB/PKCS5Padding} (128)</li> * <li>{@code AES/GCM/NoPadding} (128)</li> * <li>{@code DESede/CBC/NoPadding} (168)</li> * <li>{@code DESede/CBC/PKCS5Padding} (168)</li> * <li>{@code DESede/ECB/NoPadding} (168)</li> * <li>{@code DESede/ECB/PKCS5Padding} (168)</li> * <li>{@code RSA/ECB/PKCS1Padding} (1024, 2048)</li> * <li>{@code RSA/ECB/OAEPWithSHA-1AndMGF1Padding} (1024, 2048)</li> * <li>{@code RSA/ECB/OAEPWithSHA-256AndMGF1Padding} (1024, 2048)</li> * </ul> * These transformations are described in the * <a href="{@docRoot}/../specs/security/standard-names.html#cipher-algorithms"> * Cipher section</a> of the * Java Security Standard Algorithm Names Specification. * Consult the release documentation for your implementation to see if any * other transformations are supported. * * @author Jan Luehe * @see KeyGenerator * @see SecretKey * @since 1.4
*/
/** * Constant used to initialize cipher to encryption mode.
*/ publicstaticfinalint ENCRYPT_MODE = 1;
/** * Constant used to initialize cipher to decryption mode.
*/ publicstaticfinalint DECRYPT_MODE = 2;
/** * Constant used to initialize cipher to key-wrapping mode.
*/ publicstaticfinalint WRAP_MODE = 3;
/** * Constant used to initialize cipher to key-unwrapping mode.
*/ publicstaticfinalint UNWRAP_MODE = 4;
/** * Constant used to indicate the to-be-unwrapped key is a "public key".
*/ publicstaticfinalint PUBLIC_KEY = 1;
/** * Constant used to indicate the to-be-unwrapped key is a "private key".
*/ publicstaticfinalint PRIVATE_KEY = 2;
/** * Constant used to indicate the to-be-unwrapped key is a "secret key".
*/ publicstaticfinalint SECRET_KEY = 3;
// The provider private Provider provider;
// The provider implementation (delegate) private CipherSpi spi;
// The transformation privatefinal String transformation;
// Crypto permission representing the maximum allowable cryptographic // strength that this cipher can be used for. (The cryptographic // strength is a function of the keysize and algorithm parameters encoded // in the crypto permission.) private CryptoPermission cryptoPerm;
// The exemption mechanism that needs to be enforced private ExemptionMechanism exmech;
// Flag which indicates whether or not this cipher has been initialized privateboolean initialized = false;
// The operation mode - store the operation mode after the // cipher has been initialized. privateint opmode = 0;
// next SPI to try in provider selection // null once provider is selected private CipherSpi firstSpi;
// next service to try in provider selection // null once provider is selected private Service firstService;
// remaining services to try in provider selection // null once provider is selected private Iterator<Service> serviceIterator;
// list of transform Strings to lookup in the provider private List<Transform> transforms;
privatefinal Object lock;
/** * Creates a {@code Cipher} object. * * @param cipherSpi the delegate * @param provider the provider * @param transformation the transformation * @throws NullPointerException if {@code provider} is {@code null} * @throws IllegalArgumentException if the supplied arguments * are deemed invalid for constructing the {@code Cipher} object
*/ protected Cipher(CipherSpi cipherSpi,
Provider provider,
String transformation) { // See bug 4341369 & 4334690 for more info. // If the caller is trusted, then okay. // Otherwise throw an IllegalArgumentException. if (!JceSecurityManager.INSTANCE.isCallerTrusted(
JceSecurityManager.WALKER.getCallerClass(), provider)) { thrownew IllegalArgumentException("Cannot construct cipher");
} this.spi = cipherSpi; this.provider = provider; this.transformation = transformation; this.cryptoPerm = CryptoAllPermission.INSTANCE; this.lock = null;
}
/** * Creates a {code Cipher} object. Called internally by {code NullCipher}. * * @param cipherSpi the delegate * @param transformation the transformation
*/
Cipher(CipherSpi cipherSpi, String transformation) { this.spi = cipherSpi; this.transformation = transformation; this.cryptoPerm = CryptoAllPermission.INSTANCE; this.lock = null;
}
privatestatic String[] tokenizeTransformation(String transformation) throws NoSuchAlgorithmException { if (transformation == null) { thrownew NoSuchAlgorithmException("No transformation given");
} /* * array containing the components of a cipher transformation: * * index 0: algorithm component (e.g., AES) * index 1: feedback component (e.g., CFB) * index 2: padding component (e.g., PKCS5Padding)
*/
String[] parts = new String[3]; int count = 0;
StringTokenizer parser = new StringTokenizer(transformation, "/"); try { while (parser.hasMoreTokens() && count < 3) {
parts[count++] = parser.nextToken().trim();
} if (count == 0 || count == 2) { thrownew NoSuchAlgorithmException("Invalid transformation"
+ " format:" +
transformation);
} // treats all subsequent tokens as part of padding if (count == 3 && parser.hasMoreTokens()) {
parts[2] = parts[2] + parser.nextToken("\r\n");
}
} catch (NoSuchElementException e) { thrownew NoSuchAlgorithmException("Invalid transformation " + "format:" + transformation);
} if ((parts[0] == null) || (parts[0].isEmpty())) { thrownew NoSuchAlgorithmException("Invalid transformation: " + "algorithm not specified-"
+ transformation);
} return parts;
}
// Provider attribute name for supported chaining mode privatestaticfinal String ATTR_MODE = "SupportedModes"; // Provider attribute name for supported padding names privatestaticfinal String ATTR_PAD = "SupportedPaddings";
// constants indicating whether the provider supports // a given mode or padding privatestaticfinalint S_NO = 0; // does not support privatestaticfinalint S_MAYBE = 1; // unable to determine privatestaticfinalint S_YES = 2; // does support
/** * Nested class to deal with modes and paddings.
*/ privatestaticclass Transform { // transform string to lookup in the provider final String transform; // the mode/padding suffix in upper case. for example, if the algorithm // to lookup is "AES/CBC/PKCS5Padding" suffix is "/CBC/PKCS5PADDING" // if lookup is "AES", suffix is the empty string // needed because aliases prevent straight transform.equals() final String suffix; // value to pass to setMode() or null if no such call required final String mode; // value to pass to setPadding() or null if no such call required final String pad;
Transform(String alg, String suffix, String mode, String pad) { this.transform = alg + suffix; this.suffix = suffix.toUpperCase(Locale.ENGLISH); this.mode = mode; this.pad = pad;
} // set mode and padding for the given SPI void setModePadding(CipherSpi spi) throws NoSuchAlgorithmException,
NoSuchPaddingException { if (mode != null) {
spi.engineSetMode(mode);
} if (pad != null) {
spi.engineSetPadding(pad);
}
} // check whether the given services supports the mode and // padding described by this Transform int supportsModePadding(Service s) { int smode = supportsMode(s); if (smode == S_NO) { return smode;
} int spad = supportsPadding(s); // our constants are defined so that Math.min() is a tri-valued AND return Math.min(smode, spad);
}
// separate methods for mode and padding // called directly by cipher only to throw the correct exception int supportsMode(Service s) { return supports(s, ATTR_MODE, mode);
} int supportsPadding(Service s) { return supports(s, ATTR_PAD, pad);
}
// get the transform matching the specified service privatestatic Transform getTransform(Service s,
List<Transform> transforms) {
String alg = s.getAlgorithm().toUpperCase(Locale.ENGLISH); for (Transform tr : transforms) { if (alg.endsWith(tr.suffix)) { return tr;
}
} returnnull;
}
/** * Returns a {@code Cipher} object that implements the specified * transformation. * * <p> This method traverses the list of registered security providers, * starting with the most preferred provider. * A new {@code Cipher} object encapsulating the * {@code CipherSpi} implementation from the first * provider that supports the specified algorithm is returned. * * <p> Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @apiNote * It is recommended to use a transformation that fully specifies the * algorithm, mode, and padding. By not doing so, the provider will * use a default for the mode and padding which may not meet the security * requirements of your application. * * @implNote * The JDK Reference Implementation additionally uses the * {@code jdk.security.provider.preferred} * {@link Security#getProperty(String) Security} property to determine * the preferred provider order for the specified algorithm. This * may be different than the order of providers returned by * {@link Security#getProviders() Security.getProviders()}. * See also the Cipher Transformations section of the {@extLink * security_guide_jdk_providers JDK Providers} document for information * on the transformation defaults used by JDK providers. * * @param transformation the name of the transformation, e.g., * <i>AES/CBC/PKCS5Padding</i>. * See the Cipher section in the <a href= * "{@docRoot}/../specs/security/standard-names.html#cipher-algorithms"> * Java Security Standard Algorithm Names Specification</a> * for information about standard transformation names. * * @return a {@code Cipher} object that implements the requested * transformation * * @throws NoSuchAlgorithmException if {@code transformation} * is {@code null}, empty, in an invalid format, * or if no provider supports a {@code CipherSpi} * implementation for the specified algorithm * * @throws NoSuchPaddingException if {@code transformation} * contains a padding scheme that is not available * * @see java.security.Provider
*/ publicstaticfinal Cipher getInstance(String transformation) throws NoSuchAlgorithmException, NoSuchPaddingException
{ if ((transformation == null) || transformation.isEmpty()) { thrownew NoSuchAlgorithmException("Null or empty transformation");
}
List<Transform> transforms = getTransforms(transformation);
List<ServiceId> cipherServices = new ArrayList<>(transforms.size()); for (Transform transform : transforms) {
cipherServices.add(new ServiceId("Cipher", transform.transform));
}
List<Service> services = GetInstance.getServices(cipherServices); // make sure there is at least one service from a signed provider // and that it can use the specified mode and padding
Iterator<Service> t = services.iterator();
Exception failure = null; while (t.hasNext()) {
Service s = t.next(); if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue;
}
Transform tr = getTransform(s, transforms); if (tr == null) { // should never happen continue;
} int canuse = tr.supportsModePadding(s); if (canuse == S_NO) { // does not support mode or padding we need, ignore continue;
} // S_YES, S_MAYBE // even when mode and padding are both supported, they // may not be used together, try out and see if it works try {
CipherSpi spi = (CipherSpi)s.newInstance(null);
tr.setModePadding(spi); // specify null instead of spi for delayed provider selection returnnew Cipher(null, s, t, transformation, transforms);
} catch (Exception e) {
failure = e;
}
} thrownew NoSuchAlgorithmException
("Cannot find any provider supporting " + transformation, failure);
}
/** * Returns a {@code Cipher} object that implements the specified * transformation. * * <p> A new {@code Cipher} object encapsulating the * {@code CipherSpi} implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * * <p> Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @apiNote * It is recommended to use a transformation that fully specifies the * algorithm, mode, and padding. By not doing so, the provider will * use a default for the mode and padding which may not meet the security * requirements of your application. * * @implNote * See the Cipher Transformations section of the {@extLink * security_guide_jdk_providers JDK Providers} document for information * on the transformation defaults used by JDK providers. * * @param transformation the name of the transformation, * e.g., <i>AES/CBC/PKCS5Padding</i>. * See the Cipher section in the <a href= * "{@docRoot}/../specs/security/standard-names.html#cipher-algorithms"> * Java Security Standard Algorithm Names Specification</a> * for information about standard transformation names. * * @param provider the name of the provider * * @return a {@code Cipher} object that implements the requested * transformation * * @throws IllegalArgumentException if the {@code provider} * is {@code null} or empty * * @throws NoSuchAlgorithmException if {@code transformation} * is {@code null}, empty, in an invalid format, * or if a {@code CipherSpi} implementation for the * specified algorithm is not available from the specified * provider * * @throws NoSuchPaddingException if {@code transformation} * contains a padding scheme that is not available * * @throws NoSuchProviderException if the specified provider is not * registered in the security provider list * * @see java.security.Provider
*/ publicstaticfinal Cipher getInstance(String transformation,
String provider) throws NoSuchAlgorithmException, NoSuchProviderException,
NoSuchPaddingException
{ if ((transformation == null) || transformation.isEmpty()) { thrownew NoSuchAlgorithmException("Null or empty transformation");
} if ((provider == null) || (provider.isEmpty())) { thrownew IllegalArgumentException("Missing provider");
}
Provider p = Security.getProvider(provider); if (p == null) { thrownew NoSuchProviderException("No such provider: " +
provider);
} return getInstance(transformation, p);
}
/** * Returns a {@code Cipher} object that implements the specified * transformation. * * <p> A new {@code Cipher} object encapsulating the * {@code CipherSpi} implementation from the specified {@code provider} * object is returned. Note that the specified {@code provider} object * does not have to be registered in the provider list. * * @apiNote * It is recommended to use a transformation that fully specifies the * algorithm, mode, and padding. By not doing so, the provider will * use a default for the mode and padding which may not meet the security * requirements of your application. * * @implNote * See the Cipher Transformations section of the {@extLink * security_guide_jdk_providers JDK Providers} document for information * on the transformation defaults used by JDK providers. * * @param transformation the name of the transformation, * e.g., <i>AES/CBC/PKCS5Padding</i>. * See the Cipher section in the <a href= * "{@docRoot}/../specs/security/standard-names.html#cipher-algorithms"> * Java Security Standard Algorithm Names Specification</a> * for information about standard transformation names. * * @param provider the provider * * @return a {@code Cipher} object that implements the requested * transformation * * @throws IllegalArgumentException if the {@code provider} * is {@code null} * * @throws NoSuchAlgorithmException if {@code transformation} * is {@code null}, empty, in an invalid format, * or if a {@code CipherSpi} implementation for the * specified algorithm is not available from the specified * {@code provider} object * * @throws NoSuchPaddingException if {@code transformation} * contains a padding scheme that is not available * * @see java.security.Provider
*/ publicstaticfinal Cipher getInstance(String transformation,
Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException
{ if ((transformation == null) || transformation.isEmpty()) { thrownew NoSuchAlgorithmException("Null or empty transformation");
} if (provider == null) { thrownew IllegalArgumentException("Missing provider");
}
Exception failure = null;
List<Transform> transforms = getTransforms(transformation); boolean providerChecked = false;
String paddingError = null; for (Transform tr : transforms) {
Service s = provider.getService("Cipher", tr.transform); if (s == null) { continue;
} if (providerChecked == false) { // for compatibility, first do the lookup and then verify // the provider. this makes the difference between a NSAE // and a SecurityException if the // provider does not support the algorithm.
Exception ve = JceSecurity.getVerificationResult(provider); if (ve != null) {
String msg = "JCE cannot authenticate the provider "
+ provider.getName(); thrownew SecurityException(msg, ve);
}
providerChecked = true;
} if (tr.supportsMode(s) == S_NO) { continue;
} if (tr.supportsPadding(s) == S_NO) {
paddingError = tr.pad; continue;
} try {
CipherSpi spi = (CipherSpi)s.newInstance(null);
tr.setModePadding(spi);
Cipher cipher = new Cipher(spi, transformation);
cipher.provider = s.getProvider();
cipher.initCryptoPermission(); return cipher;
} catch (Exception e) {
failure = e;
}
}
// throw NoSuchPaddingException if the problem is with padding if (failure instanceof NoSuchPaddingException) { throw (NoSuchPaddingException)failure;
} if (paddingError != null) { thrownew NoSuchPaddingException
("Padding not supported: " + paddingError);
} thrownew NoSuchAlgorithmException
("No such algorithm: " + transformation, failure);
}
// If the requested crypto service is export-controlled, // determine the maximum allowable keysize. privatevoid initCryptoPermission() throws NoSuchAlgorithmException { if (JceSecurity.isRestricted() == false) {
cryptoPerm = CryptoAllPermission.INSTANCE;
exmech = null; return;
}
cryptoPerm = getConfiguredPermission(transformation); // Instantiate the exemption mechanism (if required)
String exmechName = cryptoPerm.getExemptionMechanism(); if (exmechName != null) {
exmech = ExemptionMechanism.getInstance(exmechName);
}
}
// max number of debug warnings to print from chooseFirstProvider() privatestaticint warnCount = 10;
/** * Choose the Spi from the first provider available. Used if * delayed provider selection is not possible because init() * is not the first method called.
*/ void chooseFirstProvider() { if (spi != null) { return;
} synchronized (lock) { if (spi != null) { return;
} if (debug != null) { int w = --warnCount; if (w >= 0) {
debug.println("Cipher.init() not first method "
+ "called, disabling delayed provider selection"); if (w == 0) {
debug.println("Further warnings of this type will "
+ "be suppressed");
} new Exception("Call trace").printStackTrace();
}
}
Exception lastException = null; while ((firstService != null) || serviceIterator.hasNext()) {
Service s;
CipherSpi thisSpi; if (firstService != null) {
s = firstService;
thisSpi = firstSpi;
firstService = null;
firstSpi = null;
} else {
s = serviceIterator.next();
thisSpi = null;
} if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue;
}
Transform tr = getTransform(s, transforms); if (tr == null) { // should never happen continue;
} if (tr.supportsModePadding(s) == S_NO) { continue;
} try { if (thisSpi == null) {
Object obj = s.newInstance(null); if (obj instanceof CipherSpi == false) { continue;
}
thisSpi = (CipherSpi)obj;
}
tr.setModePadding(thisSpi);
initCryptoPermission();
spi = thisSpi;
provider = s.getProvider(); // not needed any more
firstService = null;
serviceIterator = null;
transforms = null; return;
} catch (Exception e) {
lastException = e;
}
}
ProviderException e = new ProviderException
("Could not construct CipherSpi instance"); if (lastException != null) {
e.initCause(lastException);
} throw e;
}
}
privatevoid chooseProvider(int initType, int opmode, Key key,
AlgorithmParameterSpec paramSpec,
AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { synchronized (lock) { if (spi != null) {
implInit(spi, initType, opmode, key, paramSpec, params, random); return;
}
Exception lastException = null; while ((firstService != null) || serviceIterator.hasNext()) {
Service s;
CipherSpi thisSpi; if (firstService != null) {
s = firstService;
thisSpi = firstSpi;
firstService = null;
firstSpi = null;
} else {
s = serviceIterator.next();
thisSpi = null;
} // if provider says it does not support this key, ignore it if (s.supportsParameter(key) == false) { continue;
} if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue;
}
Transform tr = getTransform(s, transforms); if (tr == null) { // should never happen continue;
} if (tr.supportsModePadding(s) == S_NO) { continue;
} try { if (thisSpi == null) {
thisSpi = (CipherSpi)s.newInstance(null);
}
tr.setModePadding(thisSpi);
initCryptoPermission();
implInit(thisSpi, initType, opmode, key, paramSpec,
params, random);
provider = s.getProvider(); this.spi = thisSpi;
firstService = null;
serviceIterator = null;
transforms = null; return;
} catch (Exception e) { // NoSuchAlgorithmException from newInstance() // InvalidKeyException from init() // RuntimeException (ProviderException) from init() // SecurityException from crypto permission check if (lastException == null) {
lastException = e;
}
}
} // no working provider found, fail if (lastException instanceof InvalidKeyException) { throw (InvalidKeyException)lastException;
} if (lastException instanceof InvalidAlgorithmParameterException) { throw (InvalidAlgorithmParameterException)lastException;
} if (lastException instanceof RuntimeException) { throw (RuntimeException)lastException;
}
String kName = (key != null) ? key.getClass().getName() : "(null)"; thrownew InvalidKeyException
("No installed provider supports this key: "
+ kName, lastException);
}
}
/** * Returns the provider of this {@code Cipher} object. * * @return the provider of this {@code Cipher} object
*/ publicfinal Provider getProvider() {
chooseFirstProvider(); returnthis.provider;
}
/** * Returns the algorithm name of this {@code Cipher} object. * * <p>This is the same name that was specified in one of the * {@code getInstance} calls that created this {@code Cipher} * object. * * @return the algorithm name of this {@code Cipher} object
*/ publicfinal String getAlgorithm() { returnthis.transformation;
}
/** * Returns the block size (in bytes). * * @return the block size (in bytes), or 0 if this cipher is * not a block cipher
*/ publicfinalint getBlockSize() {
chooseFirstProvider(); return spi.engineGetBlockSize();
}
/** * Returns the length in bytes that an output buffer would need to be in * order to hold the result of the next {@code update} or * {@code doFinal} operation, given the input length * {@code inputLen} (in bytes). * * <p>This call takes into account any unprocessed (buffered) data from a * previous {@code update} call, padding, and AEAD tagging. * * <p>The actual output length of the next {@code update} or * {@code doFinal} call may be smaller than the length returned by * this method. * * @param inputLen the input length (in bytes) * * @return the required output buffer size (in bytes) * * @throws IllegalStateException if this {@code Cipher} object is in a * wrong state (e.g., has not yet been initialized)
*/ publicfinalint getOutputSize(int inputLen) {
if (!initialized && !(thisinstanceof NullCipher)) { thrownew IllegalStateException("Cipher not initialized");
} if (inputLen < 0) { thrownew IllegalArgumentException("Input size must be equal " + "to or greater than zero");
}
chooseFirstProvider(); return spi.engineGetOutputSize(inputLen);
}
/** * Returns the initialization vector (IV) in a new buffer. * * <p>This is useful in the case where a random IV was created, * or in the context of password-based encryption or * decryption, where the IV is derived from a user-supplied password. * * @return the initialization vector in a new buffer, or {@code null} if * this cipher does not use an IV, or if the IV has not yet * been set.
*/ publicfinalbyte[] getIV() {
chooseFirstProvider(); return spi.engineGetIV();
}
/** * Returns the parameters used with this {@code Cipher} object. * * <p>The returned parameters may be the same that were used to initialize * this cipher, or may contain additional default or random parameter * values used by the underlying cipher implementation. If the required * parameters were not supplied and can be generated by the cipher, the * generated parameters are returned. Otherwise, {@code null} is returned. * * @return the parameters used with this cipher, or {@code null}
*/ publicfinal AlgorithmParameters getParameters() {
chooseFirstProvider(); return spi.engineGetParameters();
}
/** * Returns the exemption mechanism object used with this {@code Cipher} * object. * * @return the exemption mechanism object used with this {@code Cipher} * object, or {@code null} if this {@code Cipher} object does not use any * exemption mechanism.
*/ publicfinal ExemptionMechanism getExemptionMechanism() {
chooseFirstProvider(); return exmech;
}
// // Crypto permission check code below // privatevoid checkCryptoPerm(CipherSpi checkSpi, Key key) throws InvalidKeyException { if (cryptoPerm == CryptoAllPermission.INSTANCE) { return;
} // Check if key size and default parameters are within legal limits
AlgorithmParameterSpec params; try {
params = getAlgorithmParameterSpec(checkSpi.engineGetParameters());
} catch (InvalidParameterSpecException ipse) { thrownew InvalidKeyException
("Unsupported default algorithm parameters");
} if (!passCryptoPermCheck(checkSpi, key, params)) { thrownew InvalidKeyException( "Illegal key size or default parameters");
}
}
privatevoid checkCryptoPerm(CipherSpi checkSpi, Key key,
AlgorithmParameterSpec params) throws InvalidKeyException,
InvalidAlgorithmParameterException { if (cryptoPerm == CryptoAllPermission.INSTANCE) { return;
} // Determine keysize and check if it is within legal limits if (!passCryptoPermCheck(checkSpi, key, null)) { thrownew InvalidKeyException("Illegal key size");
} if ((params != null) && (!passCryptoPermCheck(checkSpi, key, params))) { thrownew InvalidAlgorithmParameterException("Illegal parameters");
}
}
privatevoid checkCryptoPerm(CipherSpi checkSpi, Key key,
AlgorithmParameters params) throws InvalidKeyException, InvalidAlgorithmParameterException { if (cryptoPerm == CryptoAllPermission.INSTANCE) { return;
} // Convert the specified parameters into specs and then delegate.
AlgorithmParameterSpec pSpec; try {
pSpec = getAlgorithmParameterSpec(params);
} catch (InvalidParameterSpecException ipse) { thrownew InvalidAlgorithmParameterException
("Failed to retrieve algorithm parameter specification");
}
checkCryptoPerm(checkSpi, key, pSpec);
}
privateboolean passCryptoPermCheck(CipherSpi checkSpi, Key key,
AlgorithmParameterSpec params) throws InvalidKeyException {
String em = cryptoPerm.getExemptionMechanism(); int keySize = checkSpi.engineGetKeySize(key); // Use the "algorithm" component of the cipher // transformation so that the perm check would // work when the key has the "aliased" algo.
String algComponent; int index = transformation.indexOf('/'); if (index != -1) {
algComponent = transformation.substring(0, index);
} else {
algComponent = transformation;
}
CryptoPermission checkPerm = new CryptoPermission(algComponent, keySize, params, em);
if (!cryptoPerm.implies(checkPerm)) { if (debug != null) {
debug.println("Crypto Permission check failed");
debug.println("granted: " + cryptoPerm);
debug.println("requesting: " + checkPerm);
} returnfalse;
} if (exmech == null) { returntrue;
} try { if (!exmech.isCryptoAllowed(key)) { if (debug != null) {
debug.println(exmech.getName() + " isn't enforced");
} returnfalse;
}
} catch (ExemptionMechanismException eme) { if (debug != null) {
debug.println("Cannot determine whether "+
exmech.getName() + " has been enforced");
eme.printStackTrace();
} returnfalse;
} returntrue;
}
// check if opmode is one of the defined constants // throw InvalidParameterException if not privatestaticvoid checkOpmode(int opmode) { if ((opmode < ENCRYPT_MODE) || (opmode > UNWRAP_MODE)) { thrownew InvalidParameterException("Invalid operation mode");
}
}
/** * Initializes this {@code Cipher} object with a key. * * <p>The {@code Cipher} object is initialized for one of the following four * operations: * encryption, decryption, key wrapping or key unwrapping, depending * on the value of {@code opmode}. * * <p>If this cipher requires any algorithm parameters that cannot be * derived from the given {@code key}, the underlying cipher * implementation is supposed to generate the required parameters itself * (using provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * {@code InvalidKeyException} if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * * <p>If this cipher requires algorithm parameters that cannot be * derived from the input parameters, and there are no reasonable * provider-specific default values, initialization will * necessarily fail. * * <p>If this cipher (including its feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them using the {@link java.security.SecureRandom} * implementation of the highest-priority * installed provider as the source of randomness. * (If none of the installed providers supply an implementation of * SecureRandom, a system-provided source of randomness will be used.) * * <p>Note that when a {@code Cipher} object is initialized, it loses all * previously-acquired state. In other words, initializing a {@code Cipher} * object is equivalent to creating a new instance of that {@code Cipher} * object and initializing it. * * @param opmode the operation mode of this {@code Cipher} object * (this is one of the following: * {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, * {@code WRAP_MODE} or {@code UNWRAP_MODE}) * @param key the key * * @throws InvalidKeyException if the given key is inappropriate for * initializing this cipher, or requires * algorithm parameters that cannot be * determined from the given key, or if the given key has a keysize that * exceeds the maximum allowable keysize (as determined from the * configured jurisdiction policy files) * @throws UnsupportedOperationException if {@code opmode} is * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented * by the underlying {@code CipherSpi} * @throws InvalidParameterException if {@code opmode} is not one of the * recognized values
*/ publicfinalvoid init(int opmode, Key key) throws InvalidKeyException {
init(opmode, key, JCAUtil.getDefSecureRandom());
}
/** * Initializes this {@code Cipher} object with a key and a * source of randomness. * * <p>The {@code Cipher} object is initialized for one of the following four * operations: * encryption, decryption, key wrapping or key unwrapping, depending * on the value of {@code opmode}. * * <p>If this cipher requires any algorithm parameters that cannot be * derived from the given {@code key}, the underlying cipher * implementation is supposed to generate the required parameters itself * (using provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * {@code InvalidKeyException} if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * * <p>If this cipher requires algorithm parameters that cannot be * derived from the input parameters, and there are no reasonable * provider-specific default values, initialization will * necessarily fail. * * <p>If this cipher (including its feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them from {@code random}. * * <p>Note that when a {@code Cipher} object is initialized, it loses all * previously-acquired state. In other words, initializing a {@code Cipher} * object is equivalent to creating a new instance of that * {@code Cipher} object and initializing it. * * @param opmode the operation mode of this {@code Cipher} object * (this is one of the following: * {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, * {@code WRAP_MODE} or {@code UNWRAP_MODE}) * @param key the encryption key * @param random the source of randomness * * @throws InvalidKeyException if the given key is inappropriate for * initializing this cipher, or requires * algorithm parameters that cannot be * determined from the given key, or if the given key has a keysize that * exceeds the maximum allowable keysize (as determined from the * configured jurisdiction policy files) * @throws UnsupportedOperationException if {@code opmode} is * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented * by the underlying {@code CipherSpi} * @throws InvalidParameterException if {@code opmode} is not one of the * recognized values
*/ publicfinalvoid init(int opmode, Key key, SecureRandom random) throws InvalidKeyException
{
initialized = false;
checkOpmode(opmode);
if (!skipDebug && pdebug != null) {
pdebug.println(this.toString());
}
}
/** * Initializes this {@code Cipher} object with a key and a set of algorithm * parameters. * * <p>The {@code Cipher} object is initialized for one of the following four * operations: * encryption, decryption, key wrapping or key unwrapping, depending * on the value of {@code opmode}. * * <p>If this cipher requires any algorithm parameters and * {@code params} is {@code null}, the underlying cipher implementation is * supposed to generate the required parameters itself (using * provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * {@code InvalidAlgorithmParameterException} if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * * <p>If this cipher requires algorithm parameters that cannot be * derived from the input parameters, and there are no reasonable * provider-specific default values, initialization will * necessarily fail. * * <p>If this cipher (including its feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them using the {@link java.security.SecureRandom} * implementation of the highest-priority * installed provider as the source of randomness. * (If none of the installed providers supply an implementation of * SecureRandom, a system-provided source of randomness will be used.) * * <p>Note that when a {@code Cipher} object is initialized, it loses all * previously-acquired state. In other words, initializing a {@code Cipher} * object is equivalent to creating a new instance of that {@code Cipher} * object and initializing it. * * @param opmode the operation mode of this {@code Cipher} object * (this is one of the following: * {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, * {@code WRAP_MODE} or {@code UNWRAP_MODE}) * @param key the encryption key * @param params the algorithm parameters * * @throws InvalidKeyException if the given key is inappropriate for * initializing this cipher, or its keysize exceeds the maximum allowable * keysize (as determined from the configured jurisdiction policy files) * @throws InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this cipher, * or this cipher requires * algorithm parameters and {@code params} is {@code null}, or the given * algorithm parameters imply a cryptographic strength that would exceed * the legal limits (as determined from the configured jurisdiction * policy files) * @throws UnsupportedOperationException if {@code opmode} is * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented * by the underlying {@code CipherSpi} * @throws InvalidParameterException if {@code opmode} is not one of the * recognized values *
*/ publicfinalvoid init(int opmode, Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException
{
init(opmode, key, params, JCAUtil.getDefSecureRandom());
}
/** * Initializes this {@code Cipher} object with a key, a set of algorithm * parameters, and a source of randomness. * * <p>The {@code Cipher} object is initialized for one of the following four * operations: * encryption, decryption, key wrapping or key unwrapping, depending * on the value of {@code opmode}. * * <p>If this cipher requires any algorithm parameters and * {@code params} is {@code null}, the underlying cipher implementation is * supposed to generate the required parameters itself (using * provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * {@code InvalidAlgorithmParameterException} if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * * <p>If this cipher requires algorithm parameters that cannot be * derived from the input parameters, and there are no reasonable * provider-specific default values, initialization will * necessarily fail. * * <p>If this cipher (including its feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them from {@code random}. * * <p>Note that when a {@code Cipher} object is initialized, it loses all * previously-acquired state. In other words, initializing a {@code Cipher} * object is equivalent to creating a new instance of that {@code Cipher} * object and initializing it. * * @param opmode the operation mode of this {@code Cipher} object * (this is one of the following: * {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, * {@code WRAP_MODE} or {@code UNWRAP_MODE}) * @param key the encryption key * @param params the algorithm parameters * @param random the source of randomness * * @throws InvalidKeyException if the given key is inappropriate for * initializing this cipher, or its keysize exceeds the maximum allowable * keysize (as determined from the configured jurisdiction policy files) * @throws InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this cipher, * or this cipher requires * algorithm parameters and {@code params} is {@code null}, or the given * algorithm parameters imply a cryptographic strength that would exceed * the legal limits (as determined from the configured jurisdiction * policy files) * @throws UnsupportedOperationException if {@code opmode} is * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented * by the underlying {@code CipherSpi} * @throws InvalidParameterException if {@code opmode} is not one of the * recognized values *
*/ publicfinalvoid init(int opmode, Key key, AlgorithmParameterSpec params,
SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException
{
initialized = false;
checkOpmode(opmode);
if (!skipDebug && pdebug != null) {
pdebug.println(this.toString());
}
}
/** * Initializes this {@code Cipher} object with a key and a set of algorithm * parameters. * * <p>The {@code Cipher} object is initialized for one of the following four * operations: * encryption, decryption, key wrapping or key unwrapping, depending * on the value of {@code opmode}. * * <p>If this cipher requires any algorithm parameters and * {@code params} is {@code null}, the underlying cipher implementation is * supposed to generate the required parameters itself (using * provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * {@code InvalidAlgorithmParameterException} if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * * <p>If this cipher requires algorithm parameters that cannot be * derived from the input parameters, and there are no reasonable * provider-specific default values, initialization will * necessarily fail. * * <p>If this cipher (including its feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them using the {@link java.security.SecureRandom} * implementation of the highest-priority * installed provider as the source of randomness. * (If none of the installed providers supply an implementation of * SecureRandom, a system-provided source of randomness will be used.) * * <p>Note that when a {@code Cipher} object is initialized, it loses all * previously-acquired state. In other words, initializing a {@code Cipher} * object is equivalent to creating a new instance of that {@code Cipher} * object and initializing it. * * @param opmode the operation mode of this {@code Cipher} object * this is one of the following: {@code ENCRYPT_MODE}, * {@code DECRYPT_MODE}, {@code WRAP_MODE} * or {@code UNWRAP_MODE}) * @param key the encryption key * @param params the algorithm parameters * * @throws InvalidKeyException if the given key is inappropriate for * initializing this cipher, or its keysize exceeds the maximum allowable * keysize (as determined from the configured jurisdiction policy files). * @throws InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this cipher, * or this cipher requires * algorithm parameters and {@code params} is {@code null}, or the given * algorithm parameters imply a cryptographic strength that would exceed * the legal limits (as determined from the configured jurisdiction * policy files) * @throws UnsupportedOperationException if {@code opmode} is * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented * by the underlying {@code CipherSpi} * @throws InvalidParameterException if {@code opmode} is not one of the * recognized values
*/ publicfinalvoid init(int opmode, Key key, AlgorithmParameters params) throws InvalidKeyException, InvalidAlgorithmParameterException
{
init(opmode, key, params, JCAUtil.getDefSecureRandom());
}
/** * Initializes this {@code Cipher} object with a key, a set of algorithm * parameters, and a source of randomness. * * <p>The {@code Cipher} object is initialized for one of the following four * operations: * encryption, decryption, key wrapping or key unwrapping, depending * on the value of {@code opmode}. * * <p>If this cipher requires any algorithm parameters and * {@code params} is {@code null}, the underlying cipher implementation is * supposed to generate the required parameters itself (using * provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * {@code InvalidAlgorithmParameterException} if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * * <p>If this cipher requires algorithm parameters that cannot be * derived from the input parameters, and there are no reasonable * provider-specific default values, initialization will * necessarily fail. * * <p>If this cipher (including its feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them from {@code random}. * * <p>Note that when a {@code Cipher} object is initialized, it loses all * previously-acquired state. In other words, initializing a {@code Cipher} * object is equivalent to creating a new instance of that {@code Cipher} * object and initializing it. * * @param opmode the operation mode of this {@code Cipher} object * (this is one of the following: {@code ENCRYPT_MODE}, * {@code DECRYPT_MODE}, {@code WRAP_MODE} * or {@code UNWRAP_MODE}) * @param key the encryption key
--> --------------------
--> maximum size reached
--> --------------------
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.34Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.