本文介绍了自Android 6棉花糖以来,javax.crypto.Cipher的工作方式有所不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经成功使用javax.crypto.Cipher.getInstance("DESede/CBC/NoPadding")在Android上通过DESFire卡进行身份验证(以下示例):https://stackoverflow.com/a/14160507/2095694 ).它已经在Android 4到5的多种设备上运行,但是在我更新为6棉花糖(和6.0.1)的Nexus 7上停止了工作.在更新之前,它一直在同一设备上工作.

I've been successfully using javax.crypto.Cipher.getInstance("DESede/CBC/NoPadding") to Authenticate with DESFire cards on Android (following the example here: https://stackoverflow.com/a/14160507/2095694). It's been working on several devices from Android 4 to 5, but stopped working on my Nexus 7 updated to 6 Marshmallow (and 6.0.1). It had been working on the same device before updating.

似乎Cipher的工作方式不同,对于相同的密钥和数据给出不同的结果.运行以下代码...

It seems Cipher is working differently, giving different results for the same key and data. Running the following 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));
}

...给我以下输出:

... gives me the following output:

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

正常值(应该是正常值)始终有效,并且卡最终会正确进行身份验证,因此它按照卡期望的方式进行操作.就像我说过的那样,我尝试了几种设备(Android 4和5),它们给出的结果相同.

Normal value, what it should be, always worked and card ends up authenticating correctly, so it's doing it the way the card expects. As a said I tried on several devices (Android 4 and 5) and they give the same result.

但是现在在使用棉花糖的Nexus 7上我得到了其他东西(认证最终失败)

But on my Nexus 7 now with Marshmallow I get something else (and the authentication ends up failing)

RSLT: F3ADA5969FA9369C 

库中是否有更改?

推荐答案

出现了一个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

there is a android bug issued: 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

您还可以通过将密钥更改为24字节len来解决问题,如下所示:

you can also solve your problem by changing you key to 24 bytes len as below:

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

这篇关于自Android 6棉花糖以来,javax.crypto.Cipher的工作方式有所不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-19 06:56