I have a unit test which passes in Java 8+ and fails on Java 7 because GCM mode doesn't seem to be supported in Java 7 and earlier.
I know that I can attempt to Create a cipher with the transform e.g. AES/GCM/PKCS5Padding
and catch NoSuchAlgorithmException
, but that exception might be thrown just for that particular transform and not just because GCM mode itself isn't supported (within any transform).
I can also just check for the JVM version, but that wouldn't be a valid check for an environment where a 3rd-party crypto library is in use (e.g. BouncyCastle) or a JVM with built-in support from another vendor which happens to include support for GCM.
I'd prefer to skip the test only if GCM in general is not supported, and not just if the particular (and complete) transform I choose in my code is not supported.
Is it possible to detect supported cipher block modes from Java? Or is it only possible to try a particular transform and see if it works?
Yes, you can traverse through the providers and services and look for a service that is a cipher and contains GCM in the name, e.g.
Provider[] provs = Security.getProviders();
for (Provider prov : provs) {
Set<Service> services = prov.getServices();
for (Service service : services) {
if (!service.getType().matches("(?i)Cipher")) {
break;
}
String algo = service.getAlgorithm();
if (algo.matches("(?i).*/GCM/.*")) {
System.out.println(service);
}
}
}
Beware that you may want to check for unlimited crypto for older Java runtimes, e.g. using my answer here.
You may want to consider that GCM is only valid for 128 bit ciphers, and that it is unlikely that you'll find implementations that do not use AES. Furthermore, there aren't any parameters other than "NoPadding"
that make sense for GCM mode (in the algorithm string anyway, I'm not talking about GCCMParameterSpec
of course).
Beware that later providers may not return "AES/GCM/NoPadding"
but return "AES_128/GCM/NoPadding"
, "AES_192/GCM/NoPadding"
and "AES_256/GCM/NoPadding"
instead. This also influences, the Provider#getService(type, algorithm)
call, rendering it useless in case you want to check for "AES/GCM/NoPadding"
, i.e. AES with any valid key size.