jBcrypt è un'implementazione Java. Le app Android sono scritte in quasi-Java, per una macchina virtuale quasi-Java chiamata Dalvik .
Per le attività di elaborazione intensiva, in particolare algoritmi crittografici, Java comporta un tipico rallentamento 3x rispetto al codice C ottimizzato equivalente: una buona macchina virtuale Java esegue un Compilatore JIT , e le prestazioni del codice saranno limitate dai vincoli su cui una JVM deve operare (la conversione da bytecode a codice nativo deve essere veloce e incrementale, i metodi vengono tradotti in base alla chiamata) e il risultato deve essere ancora appropriato per il garbage collector ). Un ulteriore rallentamento può essere osservato in alcuni casi specifici in cui il codice nativo può trarre vantaggio da opcode aggiuntivi forniti dalla CPU, il caso tipico è rappresentato da calcoli su interi grandi (ad esempio, per RSA), poiché la CPU può offrire una moltiplicazione "estesa" (64x64- > 128) che il codice Java non può utilizzare, a causa della mancanza di un tipo intero a 128 bit in Java.
Per un esperimento piuttosto approfondito nel contesto delle funzioni hash (non "hashing password", solo "hashing"), vedi sphlib : una libreria che implementa molte funzioni hash, in C e in Java, con "sforzi simili alle ottimizzazioni" (lo stesso sviluppatore per l'intero lotto) e include misure su una varietà di tipi di piattaforma .
Ora, ci possono essere ulteriori rallentamenti per le app Android:
-
La CPU di uno smartphone non è veloce come quella di un PC. La CPU per smartphone può andare all'intervallo di gigahertz, ma fare comunque meno lavoro per ciclo rispetto alla CPU x86 - perché uno degli obiettivi principali della CPU di uno smartphone è quello di risparmiare la batteria. Uno smartphone deve essere in vita per un giorno intero, mentre si sta impegnando in attività radio, mentre un portatile può avere una batteria più voluminosa e ha solo bisogno di essere in piedi per alcune ore. Gli smartphone moderni sono efficienti, ma c'è ancora un gap rispetto al PC desktop. Diciamo un ulteriore fattore 3x.
-
Dalvik non è necessariamente il miglior compilatore JIT in circolazione. La relativa mancanza di muscoli grezzi significa che il JIT non può applicare le strategie di ottimizzazione più complesse, perché renderebbe la traduzione in JIT di un metodo troppo costoso.
-
Fino a Android 2.1 (incluso), Dalvik non ha JIT . Questo è il peggior rallentamento, a cui altre risposte alludono. In Android 2.1 (e prima), il bytecode Java è interpretato, non tradotto in codice nativo, e ciò comporta un costo extra pesante (diciamo da 10 a 20 volte più lento del codice JIT). Android 2.2 in poi ha JIT.
Passare a PBKDF2 non cambierà molto l'immagine. Se usi PBKDF2 , assicurati di usare SHA-256 (o SHA-1), non SHA-512, perché il la CPU dello smartphone è basata su ARM e sarà piuttosto scomoda con operazioni aritmetiche a 64 bit su cui si basa pesantemente l'SHA-512, rallentando così il codice - laddove l'hacker ha un PC, che mangia operazioni a 64 bit per la colazione, e non subire lo stesso rallentamento.
Riepilogo: bcrypt sarà molto lento su Android 2.1 (e versioni precedenti). Sarà piuttosto veloce su Android 2.2, anche se non così veloce come un PC (diciamo, tra 5 e 10 volte più lento). PBKDF2, scrypt ... non modificare questa immagine in modo significativo.
Tutto questo è detto sulle prestazioni di bcrypt. Non ho fatto commenti in alcun modo sull'uso corretto dei segreti derivati da bcrypt per la verifica della password di e di crittografia. In effetti, quando si memorizza "qualcosa" per convalidare una password, non si intende quel "qualcosa" troppo vicino alla chiave derivata dalla password che si utilizza per la crittografia.
Un "metodo crittograficamente ragionevole" consiste nel calcolare l'hash della password con bcrypt o PBKDF2 (con sali e iterazioni e tutto), quindi prendere l'output e espanderlo con un Key Derivation Function in abbastanza materiale chiave per le tue esigenze. Nel tuo contesto, prendi l'output bcrypt, quindi esegui l'hash con SHA-256. Questo produce 256 bit. Memorizza i primi 128 bit nel tuo database come "token di verifica password". Utilizza la altra metà come chiave di crittografia.
PBKDF2 rende questo processo un po 'più semplice dal momento che è un KDF, quindi puoi richiedere subito 256 bit di output derivato da password, senza bisogno di un hashing aggiuntivo; mentre la dimensione dell'output di bcrypt è fissata a 192 bit, il che potrebbe non essere sufficiente per le tue esigenze.