如何检查所选密码算法转换是否支持某些密钥长度?
boolean checkAlgorithm( String encryptMethod, int keyLength ) {
Cipher cipher = Cipher.getInstance(encryptMethod);
int maxLength = cipher.getMaxAllowedKeyLength(encryptMethod);
if ( keyLength <= maxLength && SOMETHING_ELSE ) {
return true;
} else {
return false;
}
}
对于每次转换,有没有办法逐一执行:
switch( encryptMethod ) {
case "Blowfish":
if ( keyLength <= maxLength && keyLength >= 32 && keyLength % 8 == 0 ) {
}
...
}
答案 0 :(得分:3)
是的,当然你可以循环使用它们,但Java没有属性(比如C#/ .NET会为密码返回所有可能的密钥大小&#34; service&#34;。
由于密钥大小通常由标准定义(例如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);
}
}
}
}
}
应该做的伎俩。结果有点比我想要的更丑。