5

Ich habe erfolgreich javax.crypto.Cipher.getInstance ("DESede/CBC/NoPadding") verwendet, um mit DESFire-Karten auf Android zu authentifizieren (folgendes Beispiel hier: https://stackoverflow.com/a/14160507/2095694). Es hat auf mehreren Geräten von Android 4 bis 5 funktioniert, aber auf meinem Nexus 7 auf 6 Marshmallow (und 6.0.1) aktualisiert funktioniert nicht mehr. Es hatte vor der Aktualisierung auf demselben Gerät funktioniert.javax.crypto.Cipher funktioniert anders seit Android 6 Marshmallow

Es scheint, dass Cipher anders arbeitet und unterschiedliche Ergebnisse für denselben Schlüssel und dieselben Daten liefert. Das Ausführen des folgenden Code ...

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

... gibt mir die folgende Ausgabe:

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

Normalwert, was soll es sein, immer gearbeitet und Karten landet korrekt authentifiziert, so es tut So wie die Karte es erwartet. Wie gesagt habe ich mehrere Geräte (Android 4 und 5) ausprobiert und sie geben das gleiche Ergebnis.

Aber auf meinem Nexus 7 jetzt mit Eibisch bekomme ich etwas anderes (und die Authentifizierung endet versagt)

RSLT: F3ADA5969FA9369C 

hat sich in den Bibliotheken etwas verändert?

+1

einige Änderungen in Verschlüsselungsbibliotheken Es gibt keine. Siehe Langweilige SSL-Sektion http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html Aber ich bin mir nicht sicher über die Auswirkungen auf das Paket javax.crypto. –

+1

Ich habe genau das gleiche Problem. Ich habe ein paar Dinge versucht, die auf dem Crypto-Paket-Update basieren, aber es hat noch nichts funktioniert. entschieden, einen unabhängigen Code für 3DES (DESede/CBC/NoPadding) zu implementieren (portieren), damit es funktioniert. Ich bestätigte, dass das Problem im Marshmallow-Port liegt. Dadurch werden meine Benutzer durch Marshmallow (API Level 23) -Updates auf Benutzergeräten schnell kaputt gemacht und skaliert. – Rodrigo

+0

Danke an euch beide. @Rodrigo Könntest du testen, ob meine Antwort auch für dich funktioniert? – Nublodeveloper

Antwort

6

Es scheint, dass sie den Standardanbieter in Marshmallow geändert haben.

Ein einfaches:

cipher.getProvider().getName(); 

Shows "AndroidOpenSSL" für Eibisch, wo es "BC" (BouncyCastle nehme ich an) vorher war.

die andere getInstance Überlastung Mit ...

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

... gibt mir das erwartete Ergebnis auf meinem Nexus mit Eibisch.

+0

Toller Fund! Mein Problem wurde behoben, wenn DESede/CBC/PKCS7Padding verwendet wurde. Ich habe ein anderes Projekt, in dem ich Cipher verwende und es funktioniert großartig, ohne den Provider anzugeben, der Algorithmus ist PBEWithMD5AndDES, irgendeine Idee warum? – GuilhE

+1

@GuilhE Entschuldigung, ich kann nur das Offensichtliche annehmen, der Standardanbieter für diesen Algorithmus hat sich nicht geändert oder beide funktionieren genau gleich. – Nublodeveloper

1

gibt es ein Android-Fehler ausgegeben: 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

Sie können auch Ihr Problem lösen, indem Sie Schlüssel zu 24 Bytes ändern, wie unter len:

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

Gut finden! Ich habe das gerade getestet und es funktioniert auch. Ich habe auch das 24-Byte-Len-Fix mit "BC" in Marshmallow getestet, also nehme ich an, dass Pre-Marshmallow auch korrekt funktioniert. – Nublodeveloper