2015-12-15 18 views
5

Utilizzo correttamente javax.crypto.Cipher.getInstance ("DESede/CBC/NoPadding") per l'autenticazione con le schede DESFire su Android (nell'esempio riportato di seguito: https://stackoverflow.com/a/14160507/2095694). Sta funzionando su diversi dispositivi da Android 4 a 5, ma ha smesso di funzionare sul mio Nexus 7 aggiornato a 6 Marshmallow (e 6.0.1). Stava lavorando sullo stesso dispositivo prima dell'aggiornamento.javax.crypto.Cipher funziona in modo diverso da Android 6 Marshmallow

Sembra che Cipher stia funzionando in modo diverso, dando risultati diversi per la stessa chiave e dati. L'esecuzione del codice seguente ...

public static void testCipher() throws Exception 
{ 
    byte[] KEY = 
      new byte[]{ 
        (byte) 0x0C, (byte) 0x09, (byte) 0x03, (byte) 0x0E, 
        (byte) 0x05, (byte) 0x0A, (byte) 0x0D, (byte) 0x02, 
        (byte) 0x03, (byte) 0x0A, (byte) 0x09, (byte) 0x0B, 
        (byte) 0x06, (byte) 0x10, (byte) 0x04, (byte) 0x10 
      }; 

    byte[] DATA = 
      new byte[]{ 
        (byte) 0x29, (byte) 0xDA, (byte) 0xC0, (byte) 0xC4, 
        (byte) 0xB8, (byte) 0x47, (byte) 0x13, (byte) 0xA2}; 

    byte[] newByte8 = new byte[8]; //Zeroes 

    android.util.Log.d("TEST", "KEY : " + bin2hex(KEY)); 
    android.util.Log.d("TEST", "DATA: " + bin2hex(DATA)); 
    android.util.Log.d("TEST", "IVPS: " + bin2hex(newByte8)); 
    android.util.Log.d("TEST", "----"); 

    javax.crypto.Cipher cipher = 
      javax.crypto.Cipher.getInstance("DESede/CBC/NoPadding"); 

    cipher.init(
      Cipher.DECRYPT_MODE, 
      new javax.crypto.spec.SecretKeySpec(KEY, "DESede"), 
      new javax.crypto.spec.IvParameterSpec(newByte8)); 

    byte[] result = cipher.doFinal(DATA); 

    android.util.Log.d("TEST", "RSLT: " + bin2hex(result)); 
} 

public static String bin2hex(byte[] data) { 
    return String.format("%0" + (data.length * 2) + "X", new java.math.BigInteger(1, data)); 
} 

... mi dà il seguente risultato:

KEY : 0C09030E050A0D02030A090B06100410 
DATA: 29DAC0C4B84713A2 
IVPS: 0000000000000000 
---- 
RSLT: 47BC415065B8155E 

Il valore normale, quello che dovrebbe essere, ha sempre lavorato e una carta finisce per autenticare correttamente, in modo che sta facendo è il modo in cui la carta si aspetta. Come detto ho provato su diversi dispositivi (Android 4 e 5) e danno lo stesso risultato.

Ma sul mio Nexus 7 ora con Marshmallow ottengo qualcosa di diverso (e l'autenticazione finisce per non aver)

RSLT: F3ADA5969FA9369C 

ha qualcosa cambiato nelle biblioteche?

+1

Ci sono alcuni cambiamenti nelle librerie crittografiche. Vedere la sezione Boring SSL http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html Ma non si è sicuri sull'impatto sul pacchetto javax.crypto. –

+1

Sto avendo lo stesso identico problema. Ho provato alcune cose sulla base dell'aggiornamento del pacchetto crittografico, ma non ha funzionato ancora. ha deciso di implementare (port) un codice indipendente per 3DES (DESede/CBC/NoPadding) per farlo funzionare. Ho convalidato il problema è nella porta Marshmallow. Questo sta violando i miei utenti e scalando rapidamente a causa degli aggiornamenti di Marshmallow (API Livello 23) sui dispositivi degli utenti. – Rodrigo

+0

Grazie a tutti e due. @Rodrigo Potresti provare se la mia risposta funziona anche per te? – Nublodeveloper

risposta

6

Sembra che abbiano cambiato il provider predefinito in Marshmallow.

Una semplice:

cipher.getProvider().getName(); 

Spettacoli "AndroidOpenSSL" per Marshmallow, dov'era "BC" (BouncyCastle suppongo) prima.

Con l'altra sovraccarico getInstance ...

javax.crypto.Cipher cipher = 
      javax.crypto.Cipher.getInstance("DESede/CBC/NoPadding","BC"); 

... mi dà il risultato atteso sul mio Nexus con Marshmallow.

+0

Grande scoperta! Risolto il mio problema quando si utilizza DESede/CBC/PKCS7Padding. Ho un altro progetto in cui sto usando Cipher e funziona alla grande senza specificare il provider, l'algoritmo è PBEWithMD5AndDES, qualche idea del perché? – GuilhE

+1

@GuilhE Spiacente, posso solo assumere l'ovvio, il provider predefinito per quell'algoritmo non è cambiato o entrambi funzionano esattamente allo stesso modo. – Nublodeveloper

1

c'è un bug di Android rilasciato: https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=triple%20des&colspec=ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20Opened&groupby=&sort=&id=189292

si può anche risolvere il problema da voi cambiando chiave a 24 byte len come di seguito:

MessageDigest md = MessageDigest.getInstance("MD5"); 
seed_key = md.digest(new String(key).getBytes()); 

if (seed_key.length == 16) { 
    byte[] tempkey = new byte[24]; 
    System.arraycopy(seed_key, 0, tempkey, 0, 16); 
    System.arraycopy(seed_key, 0, tempkey, 16, 8); 

    seed_key = tempkey; 
} 
SecretKeySpec keySpec = new SecretKeySpec(seed_key, "DESede"); 
nCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); 
byte[] IVector = new byte[] { 27, 9, 45, 27, 0, 72, (byte) 171, 54 }; 
IvParameterSpec iv = new IvParameterSpec(IVector); 
nCipher.init(Cipher.ENCRYPT_MODE, keySpec, iv); 

byte[] cipherbyte = nCipher.doFinal(data.getBytes()); 
encodeTxt = new String(Base64.encodeBase64(cipherbyte)); 
+0

Buona scoperta! Ho appena provato questo e funziona anche. Ho anche testato la correzione di 24 byte len con "BC" in marshmallow, quindi suppongo che anche il pre-marshmallow funzionerà correttamente. – Nublodeveloper

Problemi correlati