是的,您当然可以循环浏览它们,但 Java 没有属性(就像 C#/.NET 一样,可以返回密码“服务”的所有可能的密钥大小。
由于密钥大小通常由标准定义(例如 AES 和所有 AES 候选者的 128、192 和 256 位),因此在您的应用程序代码中使它们成为常量相对容易。
通常,无论如何您都不想动态设置密钥大小。但是,是的,您无法获取此信息很烦人(现在添加它可能会破坏所有提供程序的实现)。
getMaxAllowedKeyLength 不应用于此目的。安装无限制加密扩展时(对于此特定运行时),它将返回 Integer.MAX_VALUE。注意,它是一个静态方法,所以从对象实例调用它也是不对的,在需要的地方使用Cipher.getMaxAllowedKeyLength即可。
如果您想知道,您可以简单地尝试对称密码从 16 到 32 或 64 字节的所有密钥大小。 Cipher 类本身列出了必须支持的密码和密钥大小(一直到底部)。
好的,如果你确实想试试这个:
package nl.owlstead.stackoverflow;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Provider.Service;
import java.security.Security;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class FindKeySizes {
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
Provider[] providers = Security.getProviders();
for (Provider provider : providers) {
Set<Service> services = provider.getServices();
for (Service service : services) {
if (!service.getType().equalsIgnoreCase("cipher")) {
continue;
}
String alg = service.getAlgorithm();
KeyGenerator skf = null;
Cipher cipher;
try {
// filters out symmetric algorithms
skf = KeyGenerator.getInstance(alg, provider);
} catch (NoSuchAlgorithmException e) {
// OK, that may not exist
}
try {
cipher = Cipher.getInstance(alg, provider);
} catch (NoSuchAlgorithmException e) {
continue;
}
SortedSet<Integer> keySizes = new TreeSet<>();
for (int keySize = Byte.SIZE; keySize <= 512; keySize += Byte.SIZE) {
try {
SecretKey key;
if (skf != null) {
try {
skf.init(keySize);
key = skf.generateKey();
} catch (Exception e) {
continue;
}
} else {
key = new SecretKeySpec(new byte[keySize / Byte.SIZE], alg);
}
cipher.init(Cipher.ENCRYPT_MODE, key);
keySizes.add(keySize);
} catch (Exception e) {
// needed for RuntimeException from providers
if (alg.equalsIgnoreCase("AES") && (keySize == 128)) {
e.printStackTrace(System.err);
}
continue;
}
}
if (!keySizes.isEmpty()) {
System.out.printf("Provider: %s, cipher: %s, key sizes: %s%n",
provider.getName(), alg, keySizes);
}
}
}
}
}
应该可以解决问题。结果比我想的要丑。