2014-09-30 5 views
7

Sto scrivendo software per JVM (in Clojure) che esegue un'operazione di crittografia. Specificamente, dato un input segreto, una chiave segreta, un sale non segreto, una personalizzazione non segreta, usa BLAKE2 per ricavare 512 bit di materiale chiave. Quindi esegue il taglio della matrice in due blocchi a 256 bit, utilizzando gli strumenti della classe Arrays. (source)Come gestisco in modo sicuro e azzeriamo i buffer dei materiali chiave su JVM?

L'effettiva attuazione di tale operazione vive in libsodium quindi è implementato in C. sto usando caesium per accedervi, il che è un wrapper sopra kalium, una libreria che utilizza jnr-ffi per chiamare l'implementazione C sottostante.

Poiché tutti i buffer sopra hanno un materiale sensibile per le chiavi, mi piacerebbe assicurarmi che sia stato eliminato dalla memoria. Non sono sicuro di come farlo in modo sicuro sulla JVM (diamine, non sono nemmeno sicuro di sapere how to do that safely in C). Dato che il materiale è tradotto da C const char * a JVM byte[], e poi alcune delle mie operazioni creano nuovi array di byte JVM, il materiale chiave sta andando a vivere in array di byte JVM. Ciò solleva due preoccupazioni:

  • Se io ZEROFILL un byte[], che non viene toccato da alcun codice in seguito, come posso essere sicuro che il byte[] è stato effettivamente portato a zero? Immagino che JVM sia libero di ottimizzarlo.
  • Anche se sono stato in grado di garantire l'azzeramento di uno byte[], come faccio a sapere che la JVM non ha deciso di copiare quell'array (ad esempio nel contesto di un garbage collector) un sacco di volte senza azzerare la posizione originale, quindi lasciando il materiale di keying su tutta la memoria virtuale comunque?

sto cercando di indovinare la risposta finirà per essere "non in C & ASM" o forse anche "farlo in un HSM", ma mi piacerebbe sentire se ci sono modi JVM-terra di risolvendo questo problema.

+3

Se il riferimento al 'byte []' è stato pubblicato all'esterno dello scopo del metodo in cui è stato creato, l'ottimizzatore JVM non può decidere di ignorare le azioni di scrittura tra thread. Tuttavia, il tuo secondo punto è pienamente valido e probabilmente non c'è nulla che tu possa fare al riguardo. –

+4

Se hai codificato un 'ByteBuffer' diretto, che alloca la memoria non heap, allora potresti essere in una posizione migliore rispetto al punto su GC. Potrebbe anche essere utile qualcosa della classe 'Unsafe'. –

+0

Grazie per i vostri commenti, @MarkoTopolnik. Sei sicuro che la JVM non sia in grado di ottimizzarlo se il riferimento è visibile in più punti, anche se può provare che nient'altro tocca quel riferimento dopo l'azzeramento? Ottenere questo comportamento dai compilatori C, ad esempio, finisce per essere piuttosto complicato. (Ovvero, impedendo loro di ottimizzare l'azzeramento.) – lvh

risposta

1

Se tutto ciò che serve è pulire un array, Arrays.fill non assegna un nuovo array ma cambia i valori in quello passato come parametro. Se scarichi i sorgenti puoi leggerli direttamente lì.

Problemi correlati