DES Send and Receive Modes for DESFire Authentication

后端 未结 2 691

I\'m trying to authenticate DESFire card with my android application. I use the example in this link to decypher the bytes I got from the card. For that, I ruled out padding

相关标签:
2条回答
  • 2020-12-13 01:37

    OK I got the solution. My mistake was that I was sending

    3DES(randA + randB') 
    

    But I should send

    3DES(randA) + 3DES(randB' XOR 3DES(randA))
    

    Here's the authentication code for Android/Java (it's so sad that this is the only one that can be found on the net currently!):

    The actual authentication code:

    // send initial authentication request
    byte[] result = idTag.transceive(Utils.wrapMessage((byte)0x0a, new byte[]{(byte)0x0}));
    
    // get encrypted(randB) from the response
    byte[] b0 = new byte[8];
    for(int i = 0; i < 8; i++) {
        b0[i] = result[i];
    }
    
    // 16 bytes default key
    byte[] key = new byte[] {(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
        (byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
        (byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
        (byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0 };
    // keys for TripleDes
    byte[][] keys = new byte[3][];
    keys[0] = key; keys[1] = key; keys[2] = key;
    
    // decrypt encoded(randB)
    byte[] r0 = DES.TripleDES_Decrypt(b0, keys);
    
    // generate randA (integer 0-7 for trying, should randomize for real-life use) 
    byte[] nr = new byte[8];
    for(int i = 0; i < 8; i++) {
        nr[i] = Byte.parseByte(Integer.toString(i), 16);
    }
    
    // decrypt randA, should XOR with IV, but IV is all 0's, not necessary
    byte[] b1 = DES.TripleDES_Decrypt(nr, keys);
    
    // shift randB one byte left and get randB'
    byte[] r1 =new byte[8];
    for(int i = 0; i < 7; i++) {
        r1[i] = r0[i + 1];
    }
    r1[7]=r0[0];
    
    // xor randB' with randA and decrypt
    byte[] b2 = new byte[8];
    for(int i = 0; i < 8; i++) {
        b2[i] = (byte) (b1[i] ^ r1[i]);
    }
    b2 = DES.TripleDES_Decrypt(b2, keys);
    
    // concat (randA + randB')
    byte[] b1b2 = new byte[16];
    
    for (int i = 0; i < b1b2.length; i++) {
        if(i <= 7) {
            b1b2[i] = b1[i];
        } else {
            b1b2[i]=b2[i-8];
        }
    }
    
    result = idTag.transceive(Utils.wrapMessage((byte)0xaf, b1b2));
    

    TripleDes is the one in the question. wrapMessage function:

    public static byte[] wrapMessage (byte command, byte[] parameters) throws Exception {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
    
        stream.write((byte) 0x90);
        stream.write(command);
        stream.write((byte) 0x00);
        stream.write((byte) 0x00);
        if (parameters != null) {
            stream.write((byte) parameters.length);
            stream.write(parameters);
        }
        stream.write((byte) 0x00);
    
        return stream.toByteArray();
    }
    

    EDIT: Thanks to VGe0rge, we found out the reason why this authentication doesn't work from time to time. Instead of calling the 3DES function in the question, just call:

    Cipher.getInstance("DESede/CBC/NoPadding");
    
    0 讨论(0)
  • 2020-12-13 01:46

    Ismat, did you try to write data to the DESFIRE files?

    As you explained, when sending data to the card: The PCD uses DES “send mode” when sending data (xor before DES), and the card uses DES “recieve mode” when recieving data (xor after DES)

    So I can't get the proper code in order to implement the TDES with the XOR before..I need to do all the crypt-decrypt-crypt and the process is to slow for my application:

    res = criptoTransformDec.TransformBlock(datosEscribir, 0, 8, datosEscribir, 0);
    res = criptoTransformEnc.TransformBlock(datosEscribir, 0, 8, datosEscribir, 0);
    res = criptoTransformDec1.TransformBlock(datosEscribir, 0, 8, datosEscribir, 0);
    
    int l_iAux = 0;
    while (l_iAux < (datosEscribir.Length - 8))
        {
            criptoTransformDec2 = desDec.CreateDecryptor(claveSes1, tdesInitialVector);
            //desEnc2 = new DESCryptoServiceProvider();
            criptoTransformEnc2 = desEnc.CreateEncryptor(claveSes2, tdesInitialVector);
            //desDec3 = new DESCryptoServiceProvider();
                    criptoTransformDec3 = desDec.CreateDecryptor(claveSes1, tdesInitialVector);
    
            Array.Copy(datosEscribir, 8 + l_iAux, aux1, 0, 8);
            Array.Copy(datosEscribir, l_iAux, aux2, 0, 8);
            DesfireBarik.XorStr(ref aux1, ref aux2, 8);
            res = criptoTransformDec2.TransformBlock(aux1, 0, 8, datosEscribir, 8 + l_iAux);
            res = criptoTransformEnc2.TransformBlock(datosEscribir, 8 + l_iAux, 8, datosEscribir, 8 + l_iAux);
            res = criptoTransformDec3.TransformBlock(datosEscribir, 8 + l_iAux, 8, datosEscribir, 8 + l_iAux);
    
            l_iAux += 8;
        }
    
    private static void XorStr (ref byte[] str1, ref byte[] str2, int qty )
        {
            int i = 0;
            for (i = 0; i < qty; i++ )
                str1[i] = (byte)(str1[i] ^ str2[i]);
        }
    
    0 讨论(0)
提交回复
热议问题