2015-12-15 28 views
5

我已成功使用javax.crypto.Cipher.getInstance(「DESede/CBC/NoPadding」)通過Android上的DESFire卡進行身份驗證(以下示例爲:https://stackoverflow.com/a/14160507/2095694 )。它一直在從Android 4到5的幾款設備上工作,但停止了將Nexus 7升級到6款棉花糖(和6.0.1)的工作。它在更新之前一直在使用相同的設備。javax.crypto.Cipher自Android 6以不同的工作方式改變棉花糖

看來Cipher工作方式不同,對同一個密鑰和數據給出不同的結果。運行下面的代碼...

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

...給我下面的輸出:

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

正常價值,它應該是什麼,總是工作和卡片結束了正確驗證,所以它在做什麼它是卡片期望的方式。正如我說的,我嘗試了幾個設備(Android 4和5),他們給出了相同的結果。

但在我的Nexus 7現在棉花糖我得到其他的東西(和認證最終失敗)

RSLT: F3ADA5969FA9369C 

有事在庫中的改變?

+1

有在加密庫的一些變化。請參閱Boring SSL部分http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html但不確定對javax.crypto包的影響。 –

+1

我有完全相同的問題。嘗試了一些基於crypto軟件包更新的事情,但沒有任何工作。決定實施(端口)一個獨立的3DES代碼(DESede/CBC/NoPadding)以使其工作。我驗證了問題是在棉花糖港口。由於用戶設備上的棉花糖(API Level 23)更新,這打破了我的用戶並迅速擴展。 – Rodrigo

+0

感謝你們倆。 @Rodrigo你能否測試我的答案是否也適合你? – Nublodeveloper

回答

6

看來他們改變了棉花糖的默認供應商。

一個簡單的:

cipher.getProvider().getName(); 

節目之前 「AndroidOpenSSL」 爲棉花糖,它在哪裏 「BC」(BouncyCastle的我想)。

使用其他的getInstance超載...

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

...使我對我的Nexus與棉花糖預期的結果。

+0

很棒的發現!使用DESede/CBC/PKCS7Padding解決了我的問題。我有另一個項目,我使用密碼,它沒有指定提供程序,它的工作很好,算法是PBEWithMD5AndDES,任何想法爲什麼? – GuilhE

+1

@GuilhE對不起,我只能假設明顯的,該算法的默認提供者沒有改變,或者他們兩個完全相同。 – Nublodeveloper

1

有發佈了Android的錯誤: 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

您還可以通過更改你的關鍵如下len個24個字節解決您的問題:

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

好找!我剛剛測試過,它也可以。我還用棉花糖中的「BC」測試了24字節的len解決方案,所以我想棉花糖也可以正常工作。 – Nublodeveloper

相關問題