2013-08-26 11 views
5

Richiesto crittografia/decrittografia AES256 in un'applicazione web commerciale. Attualmente tutto funziona bene con una dimensione della chiave di 128. Questo non è soddisfacente crittograficamente, quindi il mio problema è il modo migliore per aggirare questo problema senza richiedere all'utente di installare nulla manualmente.Java: applicazione dei criteri di protezione lato client dall'applet per AES256

Ho i file jar di giurisdizione illimitati da Oracle ma non ho idea se la sostituzione di questi nella directory JRE/lib/security dell'utente sia compatibile con le versioni precedenti. Ovviamente non voglio danneggiare il JRE dell'utente. Inoltre ho il permesso di scrittura sulla mia directory di sicurezza JRE ma presumo che alcuni utenti non abbiano questi privilegi.

C'è un modo semplice per risolvere questo problema o sono bloccato con una crittografia debole o un passaggio potenzialmente problematico per gli utenti?


Aggiornamento per "unrestricting" javax.crypto.JceSecurity

@ntoskml Lei ha ragione. getMaxAllowedKeyLength restituisce comunque la dimensione della chiave limitata ma la crittografia ha esito positivo con la dimensione della chiave == 256 :). Aggiornerò il mio metodo di prova e imposto le dimensioni della chiave se è disponibile una crittografia avanzata. Grazie

>>> from javax.crypto import Cipher 
>>> Cipher.getMaxAllowedKeyLength("AES") 
128 
>>> from java.lang import Class 
>>> c = Class.forName("javax.crypto.JceSecurity") 
>>> isRestricted = c.getDeclaredField("isRestricted") 
>>> isRestricted.setAccessible(True) 
>>> isRestricted.set(None, False) 
>>> isRestricted.get(None) 
False 
>>> Cipher.getMaxAllowedKeyLength("AES") 
128 
>>> from javax.crypto import KeyGenerator 
>>> kge = KeyGenerator.getInstance("AES") 
>>> kge.init(256) 
>>> aesKey = kgen.generateKey() 
>>> c2 = Cipher.getInstance("AES") 
>>> c2.init(Cipher.ENCRYPT_MODE, aesKey) 
>>> c2.doFinal("test") 
array('b', [-81, 99, -61, -51, 93, -42, -68, -28, 107, 59, -109, -98, -25, 127, 37, 23]) 

E il banco di prova dopo il riavvio della console Jython

>>> # Reflection as above 
>>> isRestricted.get(None) 
True 
>>> kge.init(256) 
>>> aesKey = kge.generateKey() 
>>> c2.init(Cipher.ENCRYPT_MODE, aesKey) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
     at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1011) 
     at javax.crypto.Cipher.implInit(Cipher.java:786) 
     at javax.crypto.Cipher.chooseProvider(Cipher.java:849) 
     at javax.crypto.Cipher.init(Cipher.java:1213) 
     at javax.crypto.Cipher.init(Cipher.java:1153) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
     at java.lang.reflect.Method.invoke(Unknown Source) 

java.security.InvalidKeyException: java.security.InvalidKeyException: Illegal key size or default parameters 

Bingo :) Grazie per la condivisione @ntoskml

+0

Si prega di non modificare la domanda in questo modo - attualmente è un po 'difficile da leggere per le persone in cerca di una soluzione. Mi piacerebbe anche conoscere le restrizioni sull'utilizzo di questa risposta. Normalmente le applet non consentono di utilizzare i riflessi in questo modo, almeno non quando vengono eseguite nel browser. –

+0

@owlstead Dove dovrei metterlo? – drew

+0

Questo metodo funziona in applet con Windows 8 a 64 bit Java (TM) SE Runtime Environment 1.7.0_21 – drew

risposta

5

EDIT: Ecco una risposta aggiornata a questa domanda: How to avoid installing "Unlimited Strength" JCE policy files when deploying an application?


E 'possibile disabilitare le restrizioni di dimensione chiave semplicemente utilizzando poche righe di riflessione. Utilizziamo questo metodo nel nostro programma che richiede l'accesso alla crittografia a 256 bit per scopi di interoperabilità.

private static void removeCryptographyRestrictions() { 
    if (!isRestrictedCryptography()) { 
     return; 
    } 
    try { 
     java.lang.reflect.Field isRestricted; 
     try { 
      final Class<?> c = Class.forName("javax.crypto.JceSecurity"); 
      isRestricted = c.getDeclaredField("isRestricted"); 
     } catch (final ClassNotFoundException e) { 
      try { 
       // Java 6 has obfuscated JCE classes 
       final Class<?> c = Class.forName("javax.crypto.SunJCE_b"); 
       isRestricted = c.getDeclaredField("g"); 
      } catch (final ClassNotFoundException e2) { 
       throw e; 
      } 
     } 
     isRestricted.setAccessible(true); 
     isRestricted.set(null, false); 
    } catch (final Throwable e) { 
     logger.log(Level.WARNING, 
       "Failed to remove cryptography restrictions", e); 
    } 
} 

private static boolean isRestrictedCryptography() { 
    return "Java(TM) SE Runtime Environment" 
      .equals(System.getProperty("java.runtime.name")); 
} 

Tuttavia, il nostro programma non è un applet, e io non sono sicuro se le applet hanno accesso alle API di riflessione.

Anche la questione della legalità rimane. C'è una ragione per quel limite. Consulta un avvocato se sei preoccupato.

Se possibile, provare a tenerlo su chiavi a 128 bit. Anche prendendo in considerazione la legge di Moore, la rottura di AES a 128 bit richiederebbe miliardi su miliardi di anni. Le chiavi più lunghe non offrono alcun vantaggio nel mondo reale, in particolare quando le chiavi derivano da password, che comunque non hanno nulla a che vedere con 256 bit di entropia.

+0

Champion. Lo proveremo domani. C'è ancora speranza;) – drew

+0

@ntoskml Senza fortuna qui. Imposta la variabile di classe su ** JceSecurity ** ma non riesce a consentire keysize> = 128. Versione Java: ** SE 1.7.0_21 ** – drew

+0

@drew Questo è strano, perché funziona per noi in tutte le versioni di Java 6 e 7 abbiamo testato. Non abbiamo nemmeno sentito alcun rapporto da parte degli utenti. Infatti, anche [Java 8] (http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/javax/crypto/JceSecurity.java) ha ancora la stessa classe e campo Hai invocato questo metodo prima di caricare le classi di crittografia? Prova ad invocarlo da un inizializzatore statico per essere sicuro. Oltre a questo, sembra un problema con le applet. Forse qualche politica di sicurezza o inganno di classloader? Si prega di provare in un ambiente non applet per escludere altri problemi. – ntoskrnl

2

Si sta bloccato con la crittografia debole o un passo potenzialmente problematico per gli utenti se ci si attiene a SunJCE.

Non c'è ovviamente alcun problema nell'importare una libreria AES, c'è solo un problema nell'usarlo usando un'istanza di Cipher. Se si dispone di un software specifico che non dipende da JCA, è possibile, ad esempio, riscriverlo per utilizzare l'API di crittografia leggera di Bouncy Castle.

Si noti che molte altre parti dell'API di Bouncy dipendono dal JCE. L'API leggera è anche più complicata da usare e meno documentata/testata rispetto a SunJCE.

Anche l'API leggera di Bouncy Castle è abbastanza grande. Contiene molte funzionalità che non ti serviranno. Quindi è probabilmente troppo grande per l'applet. Se lo è, ti consiglio di creare una nuova libreria che contenga solo le classi specifiche di cui hai bisogno da Bouncy Castle. Il castello gonfiabile è fortunatamente molto autorizzato. Se conservi le dichiarazioni sul copyright ecc., Puoi facilmente dividerlo.

+0

La soluzione BC è molto gonfia. Essere un'applet è un po 'restrittivo. Ho cercato di evitarlo fino ad ora. – drew

+0

Sarebbe il "JCE con provider e API leggera" in [ultime versioni di bouncycastle] (http://www.bouncycastle.org/latest_releases.html) intendete per questa funzionalità? Questo è intorno ai 7,7 meg come zip. La "Lightweight API" accanto è una zip da 6,6 megawatt. Sto solo riflettendo su quanti più byte significherà per l'utente dell'applet .. BTW - per quanto riguarda il problema (beh, più vicino) .. Cosa fa esattamente questa applet? Perché la forte (?) Crittografia? –

+0

Voglio crittografare e memorizzare una password dell'archivio chiavi PKCS # 12 tra le sessioni nel contesto del browser. L'accesso al keystore viene utilizzato per firmare upload e decrittografare token scaricati (funzioni separate). In caso contrario, potrebbe essere necessario inserire la password più volte. – drew