javax.crypto.Cipher working differently since Android 6 Marshmallow

后端 未结 2 1830
长情又很酷
长情又很酷 2020-12-30 14:40

I\'ve been successfully using javax.crypto.Cipher.getInstance(\"DESede/CBC/NoPadding\") to Authenticate with DESFire cards on Android (following the example here: https://st

相关标签:
2条回答
  • 2020-12-30 14:58

    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

    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));
    
    0 讨论(0)
  • 2020-12-30 15:22

    It seems they changed the default provider in Marshmallow.

    A simple:

    cipher.getProvider().getName();
    

    Shows "AndroidOpenSSL" for Marshmallow, where it was "BC" (BouncyCastle I suppose) before.

    Using the other getInstance overload...

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

    ...gives me the expected result on my Nexus with Marshmallow.

    Update: I now get this warning:

    The BC provider is deprecated and when targetSdkVersion is moved to P this method will throw a NoSuchAlgorithmException. To fix this you should stop specifying a provider and use the default implementation
    Cipher#getInstance should not be called with ECB as the cipher mode or without setting the cipher mode because the default mode on android is ECB, which is insecure.

    So I have ended up using the other answer here that will (hopefully) work on all versions of Android.

    0 讨论(0)
提交回复
热议问题