2
votes

Here is a problem I am facing with BlowFish encryption/Decryption.

The below code is used for testing BlowFish Encryption/Decryption

// Code below omits comments for Brevity

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;

import java.math.BigInteger;

public class JBoss {

    public static void main(String[] args) throws Exception {

        if ((args.length != 2)
                || !(args[0].equals("-e") | args[0].equals("-d"))) {
            System.out
                    .println("Usage:\n\tjava JBoss <-e|-d> <encrypted_password>");
            return;
        }

        String mode = args[0];

        byte[] kbytes = "jaas is the way".getBytes();
        SecretKeySpec key = new SecretKeySpec(kbytes, "Blowfish");
        Cipher cipher = Cipher.getInstance("Blowfish");

        String out = null;

        if (mode.equals("-e")) {
            String secret = args[1];
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encoding = cipher.doFinal(secret.getBytes());
            out = new BigInteger(encoding).toString(16);
        } else {
            BigInteger secret = new BigInteger(args[1], 16);
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] encoding = cipher.doFinal(secret.toByteArray());
            out = new String(encoding);
        }
        System.out.println(out);
    }
}

Now, if I try to encrypt the string

u7mzqw2

I get the value as

-7ccb7ff0c2858a

If I try to decrypt

-7ccb7ff0c2858a

I get the error as below:

    java JBoss -d -7ccb7ff0c2858a
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
        at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
        at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
        at com.sun.crypto.provider.BlowfishCipher.engineDoFinal(DashoA13*..)
        at javax.crypto.Cipher.doFinal(DashoA13*..)
        at JBoss.main(JBoss.java:41)

Entire code is here

It has nothing to do with 7 character length original or non /8=0 encrypted value, if I am not mistaken, as the below one works

java JBoss -e qwerty

-40e961f375c2eee6

java JBoss -d -40e961f375c2eee6

qwerty

What am I missing??

3
Why are you converting to BigInteger?CodesInChaos
Its a trick to get hexadecimal strings, it is tricky in the sense that bigints are signed, and it is of course far from ideal.Maarten Bodewes
Not that I want to, this seem to be the way the implementation is in JBoss. Please see this link (usefulfor.com/security/2009/09/24/…)Abhilash

3 Answers

1
votes

Here is my observation : I modified the code a little bit adding few sops with individual bytes and the corresponding hexadecimal value.

Input: asdfda

16::10

60::3c

105::69

57::39

-60::-3c

110::6e

19::13

-52::-34

Encoded Value:103c6939c46e13cc

As you can see the items on the left are the bytes and on the right we have the individual biginteger with radix 16 values, and at the bottom we have the encoded value. You might seeing a big pattern matching. except the values with -tive. like -60 corresponds value -3c , but as with 1 byte consersion the value becames c4 ( see yourslef).

Now I tested with the value to encrypt as u7mzqw2, lets see what happens.

Input: u7mzqw2

-1::-1

-125::-7d

52::34

-128::-80

15::f

61::3d

122::7a

118::76

Encoded value:-7ccb7ff0c2858a

Now do you see the pattern matching, now you won't , why not ? lets see, well -1 whose hexadecimal should be -1 ? ??? , no it is 0XFF, now can we represent 0xFF in Byte ? No, we can't. read yourself Byte and -1

Update: what puzzled me was how these encoding was evaluated ? Still looking , help me identify this

0
votes

Try this,

public static void main(String[] args) throws Exception {
     // generate key
     KeyGenerator keyGen = KeyGenerator.getInstance("Blowfish");
     SecretKey secretKey = keyGen.generateKey();
     // get Cipher and init it for encryption
     Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
     cipher.init(Cipher.ENCRYPT_MODE, secretKey);
     String data="u7mzqw2";

     // encrypt data
     byte[] cipherText = cipher.doFinal(data.getBytes());
     // get the initialization vector from the cipher
     byte[] ivBytes = cipher.getIV();
     IvParameterSpec iv = new IvParameterSpec(ivBytes);

     byte[] keyBytes = secretKey.getEncoded();
     // create a SecretKeySpec from key material
     SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "Blowfish");
     // get Cipher and init it for encryption
     cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
     cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, iv);
     byte[] plainText = cipher.doFinal(cipherText);
     System.out.println(new String(plainText));
}
-1
votes

If we look at our code following line in the secret.toByteArray() is giving length 7 byte array which should be the cause of the issue.

byte[] encoding = cipher.doFinal(secret.toByteArray()); //During decoding logic

Issues seems to be in the implementation of BlowfishCipher, CipherCore.

public BlowfishCipher()
{
        core = new CipherCore(new BlowfishCrypt(),
                              BlowfishConstants.BLOWFISH_BLOCK_SIZE);
}

http://www.docjar.com/html/api/com/sun/crypto/provider/BlowfishConstants.java.html

We are using the BlowfishConstants.BLOWFISH_BLOCK_SIZE = 8; // number of bytes

http://hg.openjdk.java.net/jdk6/jdk6/jdk/raw-file/2d585507a41b/src/share/classes/com/sun/crypto/provider/CipherCore.java

if ((paddingLen > 0) && (paddingLen != blockSize) &&
            (padding != null) && decrypting) {
            throw new IllegalBlockSizeException
                ("Input length must be multiple of " + blockSize +
                 "when decrypting with padded cipher");
        }