How to check if Cipher supports certain key size?

笑着哭i 提交于 2021-02-07 04:19:01

问题


How can I check if a chosen cipher algorithm transformation supports certain key length?

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;
  }

}

Is there a way without doing it one by one for each transformation like:

switch( encryptMethod ) {
  case "Blowfish":
    if ( keyLength <= maxLength && keyLength >= 32 && keyLength % 8 == 0 ) {
    }
    ...
}

回答1:


Yes, of course you can cycle through them, but Java doesn't have a property (like C#/.NET does to return all possible key sizes for a cipher "service".

As the key sizes are generally defined by the standard (e.g. 128, 192 and 256 bits for AES and all AES candidates) it is relatively easy to make them constants in your application code though.

Generally you do not want to dynamically set key sizes anyway. But yes, it is annoying that you cannot get this information (and adding it now will likely break all provider implementations).


getMaxAllowedKeyLength should not be used for this. It will return Integer.MAX_VALUE when the unlimited cryptography extension is installed (for this particular runtime). Note that it is a static method, so calling it from a object instance is not right either, just use Cipher.getMaxAllowedKeyLength where you need it.

If you want to find out you can simply try all key sizes from 16 up to 32 or 64 bytes for symmetric ciphers. The ciphers and key sizes that MUST be supported are listed in the Cipher class itself (all the way to the bottom).


Ok, so if you do want to try this out:

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

should do the trick. That turned out somewhat uglier than I wanted though.



来源:https://stackoverflow.com/questions/41527789/how-to-check-if-cipher-supports-certain-key-size

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!