È AES (Rijndael) più veloce di Blowfish?

3

So che teorico che blowfish è molto più veloce di aes. Ma ho confrontato diversi algoritmi, tra cui aes e blowfish per file da 1 MB, 5 MB, 10 MB, ecc. Nella piattaforma java 8 e nella libreria bouncy castle. In ogni scenario di test, aes è più veloce di blowfish.

Mi chiedo se sbaglio da qualche parte?

Ecco il codice:

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();

    }


}
    
posta ersan 26.05.2014 - 16:48
fonte

2 risposte

6

Teoricamente, Blowfish dovrebbe essere più veloce di AES, ma non molto più veloce. Vedi questa domanda per alcuni dettagli.

Poi c'è ottimizzazione . Per un determinato algoritmo, è possibile in qualche modo definire la sua "velocità massima" come la prestazione ottenuta con un codice ottimale; ma le implementazioni effettive non sono mai del tutto ottimali, e quanto sono vicini (o lontani) all'ottimalità dipende dagli sforzi investiti in esse. AES è grande e usato molto; così le persone che scrivono le implementazioni AES si preoccupano di mettere a punto il loro codice in modo che sia veloce sulla maggior parte delle architetture, inclusa la più recente. Blowfish, d'altra parte, ha una base d'uso in diminuzione, per buoni motivi (ha blocchi a 64 bit, che non sono abbastanza grandi per garantire la sicurezza quando i gigabyte di dati sono crittografati con una determinata chiave). Pertanto, si può supporre che in una determinata libreria crittografica, le implementazioni AES siano più probabilmente ottimizzate e mantenute rispetto alle implementazioni Blowfish.

Altri punti:

  • Sebbene la crittografia di Blowfish sia veloce, la pianificazione dei tasti (che trasforma la chiave in tabelle interne pronte a elaborare molti dati) è terribilmente lenta in Blowfish. Nel tuo codice, sembra che tu cerchi di misurare la velocità della crittografia "nel suo complesso". Se si desidera misurare la velocità di crittografia grezza, è necessario innanzitutto crittografare, ad esempio, un megabyte (per assicurarsi che sia stata eseguita la pianificazione della chiave e che tutte le cache siano state compilate); quindi misurare la velocità di crittografia di 10 o 100 megabyte in più.

  • Blowfish è veloce perché funziona su molte ricerche in una S-box dipendente dalla chiave (una tabella da 4 kB). In Java, gli accessi agli array sono controllati (l'indice deve rientrare nella lunghezza dell'array), il che li rende relativamente più lenti di altre operazioni. Gli algoritmi di crittografia che sono pesanti sugli accessi agli array comportano quindi un fattore di rallentamento rispetto agli algoritmi espressi come operazioni aritmetiche (un caso tipico è RC4). Questo potrebbe spiegare perché un Blowfish basato su Java non sembra efficiente (rispetto ad AES basato su Java) come Blowfish basato su C (rispetto a un AES basato su C).

  • Le CPU moderne hanno codici opzionali AES specializzati , che implicano una crittografia AES molto veloce. Una libreria Java pura non può utilizzare questi opcode, ma Java può chiamare codice nativo. Se la tua libreria utilizza il codice nativo per chiamare gli opcode AES-NI, allora la crittografia AES sarà necessariamente un urlatore e Blowfish non sarà in grado di competere.

risposta data 26.05.2014 - 17:30
fonte
0

Le moderne CPU x86 forniscono accelerazione hardware per la crittografia / decrittografia AES, che è enabled nella JVM . Anche se Blowfish potrebbe essere più veloce in AES nelle implementazioni software, l'accelerazione hardware lo rende molto più veloce.

A proposito, questa domanda dovrebbe essere su Stack Overflow, non qui.

    
risposta data 26.05.2014 - 17:14
fonte

Leggi altre domande sui tag