获取java.security.InvalidKeyException:密钥必须为128、192或256位长的twofish

时间:2020-06-10 07:12:30

标签: java twofish iaik-jce

以下代码用于加密纯文本,我在Java中使用 IAIK Twofish 加密/解密代码,下面的示例代码在128位密钥下工作正常,但是当我在192位和156位尝试时键会给出java.security.InvalidKeyException: Key must be 128, 192, or 256 bit long!-

的异常
private static void doCrypto(int cipherMode, String key, File inputFile, File outputFile) throws CryptoException {
        try {
            SecretKey secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
            Cipher cipher = Cipher.getInstance(TRANSFORMATION, "IAIK");
            cipher.init(cipherMode, secretKey); 
            FileInputStream inputStream = new FileInputStream(inputFile);
            byte[] inputBytes = new byte[(int) inputFile.length()];
            inputStream.read(inputBytes);
            byte[] outputBytes = cipher.doFinal(inputBytes);
            FileOutputStream outputStream = new FileOutputStream(outputFile);
            outputStream.write(outputBytes);
            inputStream.close();
            outputStream.close();
        } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | BadPaddingException
                | IllegalBlockSizeException | IOException ex) {
            throw new CryptoException("Error encrypting/decrypting file", ex);
        } catch (NoSuchProviderException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

对于上述方法,当我提供128位密钥时,它的工作原理如下,

    KeyGenerator keyGen = KeyGenerator.getInstance("Twofish", "IAIK");
    keyGen.init(192);
    txtSecretKey.setText(iaik.utils.Util.toString(key.getEncoded()));
    SekertKey key = key.generateKey();
    encrypt(txtSecretKey.getText(), inputFile, encryptedFile);
Caused by: java.security.InvalidKeyException: Key must be 128, 192, or 256 bit long!
    at iaik.security.cipher.N.a(Unknown Source)
    at iaik.security.cipher.i.a(Unknown Source)
    at iaik.security.cipher.a.engineInit(Unknown Source)
    at javax.crypto.Cipher.init(Cipher.java:1249)
    at javax.crypto.Cipher.init(Cipher.java:1189)
    at com.opensourse.crypto.twofish.CryptoUtils.doCrypto(CryptoUtils.java:38)

3 个答案:

答案 0 :(得分:0)

确保您具有here中的“ java密码扩展(jce)无限强度管辖权策略文件8”。有关说明,请参见this

答案 1 :(得分:0)

仔细检查一些答案总是好的,因为错误“ 128位aes密钥正在工作,而192/256个密钥却没有” 对受限密码策略的症状。 请运行这个小程序,并在控制台上向我们显示结果(“ false”表示无限制的加密策略...)

import javax.crypto.Cipher;
import java.security.NoSuchAlgorithmException;
public class Main {
    public static void main(String[] args) {
        System.out.println("\nTest with Java version: " + Runtime.version());
        System.out.println("Java restricted cryptography: " + restrictedCryptography());
    }
    /**
     * Determines if cryptography restrictions apply.
     * Restrictions apply if the value of {@link Cipher#getMaxAllowedKeyLength(String)} returns a value smaller than {@link Integer#MAX_VALUE} if there are any restrictions according to the JavaDoc of the method.
     * This method is used with the transform <code>"AES/CBC/PKCS5Padding"</code> as this is an often used algorithm that is <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#impl">an implementation requirement for Java SE</a>.
     *
     * @return <code>true</code> if restrictions apply, <code>false</code> otherwise
     *
     * code by Maarten Bodewes, https://stackoverflow.com/questions/7953567/checking-if-unlimited-cryptography-is-available#
     */
    public static boolean restrictedCryptography() {
        try {
            return Cipher.getMaxAllowedKeyLength("AES/CBC/PKCS5Padding") < Integer.MAX_VALUE;
        } catch (final NoSuchAlgorithmException e) {
            throw new IllegalStateException("The transform \"AES/CBC/PKCS5Padding\" is not available (the availability of this algorithm is mandatory for Java SE implementations)", e);
        }
    }
}

答案 2 :(得分:0)

在您的主要方法中,您正在将SecretKey转换为(GUI)文本字段中显示的字符串。打印密钥内容如下:

key in hex: 7b44a1f09136a248a40c8043fa02fbcf
textfield : 7B:44:A1:F0:91:36:A2:48:A4:0C:80:43:FA:02:FB:CF

将文本字段中的此字符串转换回byte []以使用“ .getBytes”重新生成secretKey将会失败,因为冒号字符也会被解码:

SecretKey secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM)

IAIK-Util类提供了一个“ .toByteArray”方法,该方法仅忽略“ 0-9”和“ a-f”以外的其他字符,请参见文档 在http://javadoc.iaik.tugraz.at/iaik_jce/current/iaik/utils/Util.html中:

将具有十六进制值的给定字符串转换为字节数组。例如,“ 001122”变成{0,0x11,0x22}。所有在'0'-'9','a'-'z'和'A'-'Z'范围之外的字符,或者被忽略。

只需更改doCrypto方法中的行即可,一切正常:

SecretKey secretKey = new SecretKeySpec(iaik.utils.Util.toByteArray(key), ALGORITHM);