如何检查Cipher是否支持某些密钥大小?

时间:2017-01-07 23:35:51

标签: java encryption key

如何检查所选密码算法转换是否支持某些密钥长度?

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 ) {
    }
    ...
}

1 个答案:

答案 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);
                }
            }
        }
    }
}

应该做的伎俩。结果有点比我想要的更丑。