Frage

Blowfish is capable of strong encryption and can use key sizes up to 56 bytes (a 448 bit key). The key must be a multiple of 8 bytes (up to a maximum of 56).

I want to write example will automatically pad and unpad the key to size. Because Blowfish creates blocks of 8 byte encrypted output, the output is also padded and unpadded to multiples of 8 bytes.

actually want to write java code to simulate- http://webnet77.com/cgi-bin/helpers/blowfish.pl

I am using info for tool-

ALGORITM = "Blowfish";
HEX KEY = "92514c2df6e22f079acabedce08f8ac3";
PLAIN_TEXT = "sangasong@song.com"

Tool returns-

CD3A08381467823D4013960E75E465F0B00C5E3BAEFBECBB 

Please suggest.

Tried the java code:

public class TestBlowfish
{
    final String KEY = "92514c2df6e22f079acabedce08f8ac3";
    final String PLAIN_TEXT = "sangasong@song.com";
    byte[] keyBytes = DatatypeConverter.parseHexBinary(KEY); 
}

public static void main(String[] args) throws Exception 
{
    try 
    {
        byte[] encrypted = encrypt(keyBytes, PLAIN_TEXT);
        System.out.println( "Encrypted hex: " + Hex.encodeHexString(encrypted));

    }catch (GeneralSecurityException e) 
    {
        e.printStackTrace();
    }
}

private static byte[] encrypt(byte[] key, String plainText) throws GeneralSecurityException
{
    SecretKey secret_key = new SecretKeySpec(key, "Blowfish");
    Cipher cipher = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.ENCRYPT_MODE, secret_key);

    return cipher.doFinal(plainText.getBytes());
} 

Result -

Encrypted hex: 525bd4bd786a545fe7786b0076b3bbc2127425f0ea58c29d
War es hilfreich?

Lösung

So the script uses an incorrect version of PKCS#7 padding that does not pad when the size of the input is already dividable by the block size - both for the key and the plaintext. Furthermore it uses ECB mode encryption. Neither of which should be used in real life scenarios.

The following code requires the Bouncy Castle provider to be added to the JCE (Service.addProvider(new BouncyCastleProvider())) and that the Hex class of Bouncy Castle libraries is in the class path.

Warning: only tested with limited input, does not cut the key size if the size of the key is larger than the maximum.

enter image description here

WARNING: THE FOLLOWING CODE IS NOT CRYPTOGRAPHICALLY SOUND

import org.bouncycastle.util.encoders.Hex;

public class BadBlowfish {
        private static SecretKey createKey(String theKey) {
        final byte[] keyData = theKey.getBytes(StandardCharsets.US_ASCII);
        final byte[] paddedKeyData = halfPadPKCS7(keyData, 8);
        SecretKey secret = new SecretKeySpec(paddedKeyData, "Blowfish");
        return secret;
    }

    private static byte[] halfUnpadPKCS7(final byte[] paddedPlaintext, int blocksize) {
        int b = paddedPlaintext[paddedPlaintext.length - 1] & 0xFF;
        if (b > 0x07) {
            return paddedPlaintext.clone();
        }
        return Arrays.copyOf(paddedPlaintext, paddedPlaintext.length - b);
    }

    private static byte[] halfPadPKCS7(final byte[] plaintext, int blocksize) {
        if (plaintext.length % blocksize == 0) {
            return plaintext.clone();
        }

        int newLength = (plaintext.length / blocksize + 1) * blocksize;
        int paddingLength = newLength - plaintext.length;

        final byte[] paddedPlaintext = Arrays.copyOf(plaintext, newLength);
        for (int offset = plaintext.length; offset < newLength; offset++) {
            paddedPlaintext[offset] = (byte) paddingLength;
        }
        return paddedPlaintext;
    }

    public static void main(String[] args) throws Exception {
        Cipher cipher = Cipher.getInstance("Blowfish/ECB/NoPadding");
        SecretKey key = createKey("123456781234567");
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] plaintextData = cipher.doFinal(Hex.decode("085585C60B3D23257763E6D8BB0A0891"));
        byte[] unpaddedPlaintextData = halfUnpadPKCS7(plaintextData, cipher.getBlockSize());

        String plaintextHex = Hex.toHexString(unpaddedPlaintextData);
        System.out.println(plaintextHex);
        String plaintext = new String(unpaddedPlaintextData, StandardCharsets.UTF_8);
        System.out.println(plaintext);
    }
}

Andere Tipps

I am not sure about the relevance of this question: IMHO there is no point of getting the same output as this script: you have no guaranty about how secure/efficient it is... What raises my eyebrow is the part about the padding: there are several solution to pad a block, some of then are simple but very unsecured, and maybe this script is using one of these "bad" solution.

Did you check that your program is able to retrieve the correct plain text ? (you will need to code the matching decrypt function). If so, it means that it works correctly and it can be used for whatever your original purpose was, regardless what the ouput of this script is...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top