下面列出了java.security.Provider.Service#newInstance ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private static boolean isSpi(Service s) {
if (s.getType().equals("Cipher")) {
// must be a CipherSpi, which we can wrap with the CipherAdapter
return true;
}
String className = s.getClassName();
Boolean result = signatureInfo.get(className);
if (result == null) {
try {
Object instance = s.newInstance(null);
// Signature extends SignatureSpi
// so it is a "real" Spi if it is an
// instance of SignatureSpi but not Signature
boolean r = (instance instanceof SignatureSpi)
&& (instance instanceof Signature == false);
if ((debug != null) && (r == false)) {
debug.println("Not a SignatureSpi " + className);
debug.println("Delayed provider selection may not be "
+ "available for algorithm " + s.getAlgorithm());
}
result = Boolean.valueOf(r);
signatureInfo.put(className, result);
} catch (Exception e) {
// something is wrong, assume not an SPI
return false;
}
}
return result.booleanValue();
}
/**
* Returns a <code>KeyInfoFactory</code> that supports the
* requested XML processing mechanism and representation type (ex: "DOM"),
* as supplied by the specified provider. 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.
*
* @param mechanismType the type of the XML processing mechanism and
* representation. See the <a href=
* "{@docRoot}/../specs/security/standard-names.html#xml-signature-xmlsignaturefactorykeyinfofactorytransformservice-mechanisms">
* Java Security Standard Algorithm Names</a> document
* for more information.
* @param provider the string name of the provider
* @return a new <code>KeyInfoFactory</code>
* @throws NoSuchProviderException if the specified provider is not
* registered in the security provider list
* @throws NullPointerException if <code>mechanismType</code> or
* <code>provider</code> are <code>null</code>
* @throws NoSuchMechanismException if a <code>KeyInfoFactory</code>
* implementation for the specified mechanism is not available from the
* specified provider
* @see Provider
*/
public static KeyInfoFactory getInstance(String mechanismType,
String provider) throws NoSuchProviderException {
if (mechanismType == null) {
throw new NullPointerException("mechanismType cannot be null");
} else if (provider == null) {
throw new NullPointerException("provider cannot be null");
} else if (provider.length() == 0) {
throw new NoSuchProviderException();
}
Provider p = Security.getProvider(provider);
if (p == null) {
throw new NoSuchProviderException("No such provider: " +
provider);
}
Service s = p.getService("KeyInfoFactory", mechanismType);
if (s != null) {
Object obj = null;
try {
obj = s.newInstance(null);
} catch (NoSuchAlgorithmException nsae) {
throw new NoSuchMechanismException(nsae);
}
if (obj instanceof KeyInfoFactory) {
KeyInfoFactory factory = (KeyInfoFactory) obj;
factory.mechanismType = mechanismType;
factory.provider = p;
return factory;
}
}
throw new NoSuchMechanismException
("Mechanism " + mechanismType + " not available from " + provider);
}
public static Instance getInstance(Service s, Class<?> clazz)
throws NoSuchAlgorithmException {
Object instance = s.newInstance(null);
checkSuperClass(s, instance.getClass(), clazz);
return new Instance(s.getProvider(), instance);
}
/**
* Returns a <code>KeyInfoFactory</code> that supports the
* requested XML processing mechanism and representation type (ex: "DOM"),
* as supplied by the specified provider. Note that the specified
* <code>Provider</code> object does not have to be registered in the
* provider list.
*
* @param mechanismType the type of the XML processing mechanism and
* representation. See the <a href=
* "{@docRoot}/../specs/security/standard-names.html#xml-signature-xmlsignaturefactorykeyinfofactorytransformservice-mechanisms">
* Java Security Standard Algorithm Names</a> document
* for more information.
* @param provider the <code>Provider</code> object
* @return a new <code>KeyInfoFactory</code>
* @throws NullPointerException if <code>mechanismType</code> or
* <code>provider</code> are <code>null</code>
* @throws NoSuchMechanismException if a <code>KeyInfoFactory</code>
* implementation for the specified mechanism is not available from the
* specified <code>Provider</code> object
* @see Provider
*/
public static KeyInfoFactory getInstance(String mechanismType,
Provider provider) {
if (mechanismType == null) {
throw new NullPointerException("mechanismType cannot be null");
} else if (provider == null) {
throw new NullPointerException("provider cannot be null");
}
Service s = provider.getService("KeyInfoFactory", mechanismType);
if (s != null) {
Object obj = null;
try {
obj = s.newInstance(null);
} catch (NoSuchAlgorithmException nsae) {
throw new NoSuchMechanismException(nsae);
}
if (obj instanceof KeyInfoFactory) {
KeyInfoFactory factory = (KeyInfoFactory) obj;
factory.mechanismType = mechanismType;
factory.provider = provider;
return factory;
}
}
throw new NoSuchMechanismException
("Mechanism " + mechanismType + " not available from " + provider.getName());
}
private static boolean isSpi(Service s) {
if (s.getType().equals("Cipher")) {
// must be a CipherSpi, which we can wrap with the CipherAdapter
return true;
}
String className = s.getClassName();
Boolean result = signatureInfo.get(className);
if (result == null) {
try {
Object instance = s.newInstance(null);
// Signature extends SignatureSpi
// so it is a "real" Spi if it is an
// instance of SignatureSpi but not Signature
boolean r = (instance instanceof SignatureSpi)
&& (instance instanceof Signature == false);
if ((debug != null) && (r == false)) {
debug.println("Not a SignatureSpi " + className);
debug.println("Delayed provider selection may not be "
+ "available for algorithm " + s.getAlgorithm());
}
result = Boolean.valueOf(r);
signatureInfo.put(className, result);
} catch (Exception e) {
// something is wrong, assume not an SPI
return false;
}
}
return result.booleanValue();
}
/**
* Returns a <code>Cipher</code> object that implements the specified
* transformation.
*
* <p> This method traverses the list of registered security Providers,
* starting with the most preferred Provider.
* A new Cipher object encapsulating the
* 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.
*
* @param transformation the name of the transformation, e.g.,
* <i>DES/CBC/PKCS5Padding</i>.
* See the Cipher section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard transformation names.
*
* @return a cipher that implements the requested transformation.
*
* @exception NoSuchAlgorithmException if <code>transformation</code>
* is null, empty, in an invalid format,
* or if no Provider supports a CipherSpi implementation for the
* specified algorithm.
*
* @exception NoSuchPaddingException if <code>transformation</code>
* contains a padding scheme that is not available.
*
* @see java.security.Provider
*/
public static final Cipher getInstance(String transformation)
throws NoSuchAlgorithmException, NoSuchPaddingException
{
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;
}
if (canuse == S_YES) {
return new Cipher(null, s, t, transformation, transforms);
} else { // S_MAYBE, try out if it works
try {
CipherSpi spi = (CipherSpi)s.newInstance(null);
tr.setModePadding(spi);
return new Cipher(spi, s, t, transformation, transforms);
} catch (Exception e) {
failure = e;
}
}
}
throw new NoSuchAlgorithmException
("Cannot find any provider supporting " + transformation, failure);
}
private void 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)";
throw new InvalidKeyException
("No installed provider supports this key: "
+ kName, lastException);
}
}
public static Instance getInstance(Service s, Class<?> clazz,
Object param) throws NoSuchAlgorithmException {
Object instance = s.newInstance(param);
checkSuperClass(s, instance.getClass(), clazz);
return new Instance(s.getProvider(), instance);
}
private void 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)";
throw new InvalidKeyException
("No installed provider supports this key: "
+ kName, lastException);
}
}
private void 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)";
throw new InvalidKeyException
("No installed provider supports this key: "
+ kName, lastException);
}
}
/**
* Returns a <code>KeyInfoFactory</code> that supports the
* specified XML processing mechanism and representation type (ex: "DOM").
*
* <p>This method uses the standard JCA provider lookup mechanism to
* locate and instantiate a <code>KeyInfoFactory</code> implementation of
* the desired mechanism type. It traverses the list of registered security
* <code>Provider</code>s, starting with the most preferred
* <code>Provider</code>. A new <code>KeyInfoFactory</code> object
* from the first <code>Provider</code> that supports the specified
* mechanism is returned.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @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()}.
*
* @param mechanismType the type of the XML processing mechanism and
* representation. See the <a href=
* "{@docRoot}/../specs/security/standard-names.html#xml-signature-xmlsignaturefactorykeyinfofactorytransformservice-mechanisms">
* Java Security Standard Algorithm Names</a> document
* for more information.
* @return a new <code>KeyInfoFactory</code>
* @throws NullPointerException if <code>mechanismType</code> is
* <code>null</code>
* @throws NoSuchMechanismException if no <code>Provider</code> supports a
* <code>KeyInfoFactory</code> implementation for the specified mechanism
* @see Provider
*/
public static KeyInfoFactory getInstance(String mechanismType) {
if (mechanismType == null) {
throw new NullPointerException("mechanismType cannot be null");
}
Provider[] provs = Security.getProviders();
for (Provider p : provs) {
Service s = p.getService("KeyInfoFactory", mechanismType);
if (s != null) {
Object obj = null;
try {
obj = s.newInstance(null);
} catch (NoSuchAlgorithmException nsae) {
throw new NoSuchMechanismException(nsae);
}
if (obj instanceof KeyInfoFactory) {
KeyInfoFactory factory = (KeyInfoFactory) obj;
factory.mechanismType = mechanismType;
factory.provider = p;
return factory;
}
}
}
throw new NoSuchMechanismException
("Mechanism " + mechanismType + " not available");
}
private void 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)";
throw new InvalidKeyException
("No installed provider supports this key: "
+ kName, lastException);
}
}
public static Instance getInstance(Service s, Class<?> clazz,
Object param) throws NoSuchAlgorithmException {
Object instance = s.newInstance(param);
checkSuperClass(s, instance.getClass(), clazz);
return new Instance(s.getProvider(), instance);
}
/**
* Returns a <code>Cipher</code> object that implements the specified
* transformation.
*
* <p> A new Cipher object encapsulating the
* CipherSpi implementation from the specified Provider
* object is returned. Note that the specified Provider object
* does not have to be registered in the provider list.
*
* @param transformation the name of the transformation,
* e.g., <i>DES/CBC/PKCS5Padding</i>.
* See the Cipher section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard transformation names.
*
* @param provider the provider.
*
* @return a cipher that implements the requested transformation.
*
* @exception NoSuchAlgorithmException if <code>transformation</code>
* is null, empty, in an invalid format,
* or if a CipherSpi implementation for the specified algorithm
* is not available from the specified Provider object.
*
* @exception NoSuchPaddingException if <code>transformation</code>
* contains a padding scheme that is not available.
*
* @exception IllegalArgumentException if the <code>provider</code>
* is null.
*
* @see java.security.Provider
*/
public static final Cipher getInstance(String transformation,
Provider provider)
throws NoSuchAlgorithmException, NoSuchPaddingException
{
if (provider == null) {
throw new 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();
throw new 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) {
throw new NoSuchPaddingException
("Padding not supported: " + paddingError);
}
throw new NoSuchAlgorithmException
("No such algorithm: " + transformation, failure);
}
private void 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)";
throw new InvalidKeyException
("No installed provider supports this key: "
+ kName, lastException);
}
}
public static Instance getInstance(Service s, Class<?> clazz)
throws NoSuchAlgorithmException {
Object instance = s.newInstance(null);
checkSuperClass(s, instance.getClass(), clazz);
return new Instance(s.getProvider(), instance);
}
public static Instance getInstance(Service s, Class<?> clazz)
throws NoSuchAlgorithmException {
Object instance = s.newInstance(null);
checkSuperClass(s, instance.getClass(), clazz);
return new Instance(s.getProvider(), instance);
}
public static Instance getInstance(Service s, Class<?> clazz,
Object param) throws NoSuchAlgorithmException {
Object instance = s.newInstance(param);
checkSuperClass(s, instance.getClass(), clazz);
return new Instance(s.getProvider(), instance);
}
private void 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)";
throw new InvalidKeyException
("No installed provider supports this key: "
+ kName, lastException);
}
}
/**
* 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 Cipher object encapsulating the
* 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-algorithm-names">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard transformation names.
*
* @return a cipher that implements the requested transformation
*
* @throws NoSuchAlgorithmException if {@code transformation}
* is {@code null}, empty, in an invalid format,
* or if no {@code 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
*/
public static final Cipher getInstance(String transformation)
throws NoSuchAlgorithmException, NoSuchPaddingException
{
if ((transformation == null) || transformation.isEmpty()) {
throw new 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
return new Cipher(null, s, t, transformation, transforms);
} catch (Exception e) {
failure = e;
}
}
throw new NoSuchAlgorithmException
("Cannot find any provider supporting " + transformation, failure);
}