【问题标题】:Getting java.security.InvalidKeyException: Key must be 128, 192, or 256 bit long twofish获取 java.security.InvalidKeyException: Key must be 128, 192, or 256 bit long twofish
【发布时间】:2020-06-10 07:12:30
【问题描述】:

下面的代码是用来加密纯文本的,我在下面的示例代码中使用 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)

【问题讨论】:

    标签: java twofish iaik-jce


    【解决方案1】:

    在您的主要方法中,您将 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-method 中的行,一切正常:

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

    【讨论】:

      【解决方案2】:

      确保您拥有来自here 的“java 加密扩展 (jce) 无限强度管辖策略文件 8”。有关说明,请参阅this

      【讨论】:

      • 我已经启用了上述无限强度管辖权政策,没有改变,它在 128 位密钥上工作正常,当我生成 192 位和 256 位密钥时它开始表现不同。
      • encrypt(txtSecretKey.getText(), inputFile, encryptedFile) 中有什么内容?检查密钥是否真的是 192 位长。
      • 是我在下面检查生成密钥: - 128位-DC2A9E5A58086AE5AC88CA9D4146B911 192bit的-598537E137985BE955AD732F7680C019666B0C3154A187D4 256位,3C448EAA34F43D8F25A63A22E6506BE167D1E50255FA7905FC87A4598120FB28的一点是,当我通过128位的它工作得很好,FORR(192256)也开始给我例外
      【解决方案3】:

      仔细检查一些答案总是好的,因为错误“128bit aes key is working, 192/256 keys not”是 有限加密策略的症状。 请运行这个小程序并在控制台上向我们展示结果(“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);
              }
          }
      }
      

      【讨论】:

      • 它显示 Test with Java version: 1.8.0_251[newline]Java restricted cryptography: false 表示它已启用?
      • 是的,您的 Java 使用 UNLIMITED 加密策略运行,这很好
      猜你喜欢
      • 2011-10-01
      • 1970-01-01
      • 2013-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-23
      • 2022-12-26
      • 2011-05-23
      相关资源
      最近更新 更多