javatwofishiaik-jce

Getting java.security.InvalidKeyException: Key must be 128, 192, or 256 bit long twofish


Following code is written to encrypt the plain text, I am using IAIK Twofish encryption/decryption code in java below sample code works fine with 128 bit key but when i try it with 192 and 156 bit key it gives an exception that 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();
        }
    }

for above method when I am giving 128 bit key it works fine as below,

    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)

Solution

  • In your main method you're transforming the SecretKey to a String that is shown in a (GUI) textfield. Printing out the contents of the key looks like:

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

    Converting this String in the textfield back to a byte[] to regenerate the secretKey with ".getBytes" will fail as the colon chars will be decoded as well:

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

    The IAIK-Util-class provides a ".toByteArray" method that simply ignores other chars than '0-9' and 'a-f', see the documentation in http://javadoc.iaik.tugraz.at/iaik_jce/current/iaik/utils/Util.html:

    Convert the given string with hex values to a byte array. For example "001122" is turned into {0, 0x11, 0x22}. All characters outside the range of '0'-'9', 'a'-'z', and 'A'-'Z' or simply ignored.

    Simply change the line in doCrypto-method and all is working:

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