3

I know theoretical that blowfish is much faster than aes. But I benchmarked several algorithms including aes and blowfish for 1MB, 5MB, 10MB etc. files in java 8 platform and bouncy castle library. In every test scenarios aes is faster than blowfish.

I wonder if I make mistake somwhere?

Here is the code :

private static final int WARMUP_COUNT = 5;
private static final int FILE_LENGTH = 1024*512;
private static final int ITERATOR_COUNT = 1000;
private static final double BOLME = 1_000_000.0 * (ITERATOR_COUNT-WARMUP_COUNT);
static final private byte[] ivBytes = new byte[] { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
private static final IvParameterSpec ivSpec16bytes = new IvParameterSpec(ivBytes);
private static final IvParameterSpec ivSpec8bytes = new IvParameterSpec(Arrays.copyOfRange(ivBytes,0,8));

static String[] algosWithMode = {"AES/CBC/PKCS7Padding","Blowfish/CBC/PKCS7Padding","CAST5/CBC/PKCS7Padding","DES/CBC/PKCS7Padding","DESede/CBC/PKCS7Padding",  "IDEA/CBC/PKCS7Padding","ARC4", };
static String[] algos = {   "AES","Blowfish","CAST5","DES", "DESede","IDEA","ARC4"  };
static int[] keylenngth = {128,128,128,56,  168,128,128 };


@SuppressWarnings("unused")
public static void main(String[] args) throws Exception {

    if(ITERATOR_COUNT <= WARMUP_COUNT )
        throw new Exception("iterator count must be greater than warm up count iterator: "+ITERATOR_COUNT
                +" warmup count :" + WARMUP_COUNT);

    Security.addProvider(new BouncyCastleProvider());
    Key key = null;
    byte[] plainText=null;
    byte[] cipherText=null;
    byte[] decryptedText=null;
    long startTime;
    DecimalFormat df = new DecimalFormat("0.000"); 


    for (int k = 0; k < 7; k++) {

        long timeDec = 0,timeEnc = 0,timekey = 0;
        long maxtimeDec = 0,maxtimeEnc = 0,maxtimekey = 0;
        long mintimeDec = Long.MAX_VALUE,mintimeEnc = Long.MAX_VALUE,mintimekey = Long.MAX_VALUE;
        long topDec = 0,topEnc = 0,topkey = 0;



        for (int i = 0; i < ITERATOR_COUNT; i++) {



            SecureRandom random= new SecureRandom();
            plainText = random.generateSeed(FILE_LENGTH);


            startTime=System.nanoTime();
            KeyGenerator keyGen = KeyGenerator.getInstance(algos[k]);
            keyGen.init(keylenngth[k],random);
            key=keyGen.generateKey();
            timekey=System.nanoTime()-startTime;


            Cipher cipher=null;
            if(k == 0){
                 cipher = Cipher.getInstance(algosWithMode[k]);   
                 cipher.init(Cipher.ENCRYPT_MODE, key,ivSpec16bytes); 
            }else if(k == 6){
                cipher = Cipher.getInstance(algosWithMode[k]);   
                cipher.init(Cipher.ENCRYPT_MODE, key); 
            }else{
                cipher = Cipher.getInstance(algosWithMode[k]);   
                cipher.init(Cipher.ENCRYPT_MODE, key,ivSpec8bytes);
            }

            startTime=System.nanoTime();
            cipherText = cipher.doFinal(plainText);
            timeEnc=System.nanoTime()-startTime;


            if(k == 0){
                 cipher = Cipher.getInstance(algosWithMode[k]);   
                 cipher.init(Cipher.DECRYPT_MODE, key,ivSpec16bytes); 
            }else if(k== 6){
                cipher = Cipher.getInstance(algosWithMode[k]);   
                cipher.init(Cipher.DECRYPT_MODE, key); 
            }else {
                cipher = Cipher.getInstance(algosWithMode[k]);   
                cipher.init(Cipher.DECRYPT_MODE, key,ivSpec8bytes);
            }

            startTime=System.nanoTime();
            cipher.doFinal(cipherText);
            timeDec=System.nanoTime()-startTime;

            if (i >= WARMUP_COUNT) {
                if (maxtimeEnc < timeEnc)
                    maxtimeEnc = timeEnc;
                if (maxtimeDec < timeDec)
                    maxtimeDec = timeDec;
                if (maxtimekey < timekey)
                    maxtimekey = timekey;
                if (mintimeEnc > timeEnc)
                    mintimeEnc = timeEnc;
                if (mintimeDec > timeDec)
                    mintimeDec = timeDec;
                if (mintimekey > timekey)
                    mintimekey = timekey;
                topEnc += timeEnc;
                topDec += timeDec;
                topkey += timekey;
            }



        }
        double avgEnc=topEnc/BOLME;
        double avgDec=topDec/BOLME;
        double avgKey=topkey/BOLME;
        System.out.println("********************************************************"+algos[k]+"*****************************************************************");
        System.out.println("Avg Enc :"+df.format(avgEnc)+" - "+" Avg Dec :"+df.format(avgDec)+"-"+" Avg Key :"+ df.format(avgKey));
        System.out.println("Max Enc :"+df.format(maxtimeEnc/1_000_000.0)+" - "+" Max Dec :"+df.format(maxtimeDec/1_000_000.0)+"-"+" Max Key :"+ df.format(maxtimekey/1_000_000.0));
        System.out.println("Min Enc :"+df.format(mintimeEnc/1_000_000.0)+" - "+" Min Dec :"+df.format(mintimeDec/1_000_000.0)+"-"+" Min Key :"+ df.format(mintimekey/1_000_000.0));
        System.out.println();
        //System.out.println();

    }


}
2
  • @TildalWave firstly thanks for reply. But I think if statements does not effect on evaluations. Because I set the startTime variable every operation such as key derivation encryption and decryption. – ersan May 26 '14 at 19:48
  • You're right, my bad. – TildalWave May 27 '14 at 1:11
6

Theoretically, Blowfish is supposed to be faster than AES, but not much faster. See this question for some details.

Then there is optimization. For a given algorithm, you can somehow define its "top speed" as being the performance achieved with optimal code; but actual implementations are never completely optimal, and how close (or far) they are to optimality depends on the efforts invested in them. AES is big and used a lot; so people who write AES implementations take care to tune their code so that it is fast on most architectures, including the newest. Blowfish, on the other hand, has a dwindling use base, for good reasons (it has 64-bit blocks, which are not large enough to ensure security when gigabytes of data are encrypted with a given key). Thus, one can assume that in a given cryptographic library, AES implementations are more likely to have been optimized and maintained than Blowfish implementations.

Other points:

  • Though Blowfish encryption is fast, the key schedule (which transforms the key into internal tables ready to process a lot of data) is awfully slow in Blowfish. In your code, you appear to try to measure speed of encryption "as a whole". If you want to measure raw encryption speed, you should first encrypt, say, one megabyte (to make sure that key schedule occurred and all caches have been populated); then measure the speed of encryption of 10 or 100 more megabytes.

  • Blowfish is fast because it works over a lot of lookups in a key-dependent S-box (a 4 kB table). In Java, array accesses are checked (the index must fall within the array length), which makes them relatively slower than other operations. Encryption algorithms which are heavy on array accesses thus incur a slowdown factor compared with algorithms which are expressed as arithmetic operations (a typical case is RC4). This may explain why a Java-based Blowfish does not seem as efficient (compared to a Java-based AES) as a C-based Blowfish (compared to a C-based AES).

  • Modern CPU have specialized AES opcodes, which imply very fast AES encryption. A pure Java library cannot use these opcodes, but Java may call native code. If your library uses native code to call upon the AES-NI opcodes, then AES encryption will necessarily be a screamer and Blowfish won't be able to compete.

0

Modern x86 CPUs provide hardware acceleration for AES encryption/decryption, which is enabled in the JVM. Although Blowfish might be faster in AES in software implementations, hardware acceleration makes it much faster.

By the way, this question should be on Stack Overflow, not here.

2
  • I would have guessed code review instead of SO - the code is working. – user2813274 Aug 21 '14 at 18:14
  • @user2813274 Code Review is for code quality, and Stack Overflow is not just for non-working code. Code quality and the performance of self-written code is not the issue here, it's performance of the employed libraries and algorithms. It should be on SO. – DCKing Aug 26 '14 at 20:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.