Как рассчитать Retail-MAC (Single DES Plus Final Triple DES MAC) в SCP02 (протокол защищенного канала 02) с шифрованием ICV? - PullRequest
0 голосов
/ 15 марта 2019

Я видел, как несколько человек обращались за помощью в создании C-MAC (Retail MAC). Этот вопрос также содержит ответ. Это поможет вам достаточно времени. Я проверил эту функцию на реальной карте, и она работала нормально.

Ответы [ 2 ]

0 голосов
/ 15 апреля 2019

Более простой способ - использовать Signature.ALG_DES_MAC8_ISO9797_1_M2_ALG3 (если поддерживается картой) для вычисления розничного значения MAC для C-MAC в SCP02.

Примечание: CMAC - это код аутентификации сообщения, который вообще не используется в SCP02.

РЕДАКТИРОВАТЬ> Для стороны ПК рассмотрим ISO9797Alg3Mac из Надувной замок .

0 голосов
/ 15 марта 2019

Примечание:

  1. Можно повысить эффективность функции, если хотите.
  2. Если вы обнаружите какое-либо улучшение, предложите.
  3. Перед тем, как начать работу с SCP 02, связавшись с Ext_Atuh в качестве CMAC, проверьте значение SCP i.
  4. Эта функция поддерживает шифрование ICV для следующей команды.

открытый статический байт [] generateCmac (byte [] apdu, byte [] sMacSessionKey, byte [] icv) выдает исключение {

    if(sMacSessionKey.length == 16) {
    byte []temp  = sMacSessionKey.clone();
    sMacSessionKey = new byte[24];
    System.arraycopy(temp,0,sMacSessionKey,0,temp.length);
    System.arraycopy(temp,0,sMacSessionKey,16,8);
    }

    byte []cMac = new byte[8];
    byte []padding = {(byte)0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};
    int paddingRequired  = 8 - (apdu.length) %8;
    byte[] data = new byte[apdu.length + paddingRequired];
    System.arraycopy(apdu, 0, data, 0, apdu.length);
    System.arraycopy(padding, 0, data, apdu.length,paddingRequired);

            Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");

            Cipher singleDesCipher = Cipher.getInstance("DES/CBC/NoPadding",
                "SunJCE");
            SecretKeySpec desSingleKey = new SecretKeySpec(sMacSessionKey, 0, 8,
                "DES");
            SecretKey secretKey = new SecretKeySpec(sMacSessionKey, "DESede");
            // Calculate the first n - 1 block. For this case, n = 1
            IvParameterSpec ivSpec = new IvParameterSpec(icv);
            singleDesCipher.init(Cipher.ENCRYPT_MODE, desSingleKey, ivSpec);
            // byte ivForLastBlock[] = singleDesCipher.doFinal(data, 0, 8);

            int blocks = data.length / 8;

            for (int i = 0; i < blocks - 1; i++) {
                singleDesCipher.init(Cipher.ENCRYPT_MODE, desSingleKey, ivSpec);
                byte[] block = singleDesCipher.doFinal(data, i * 8, 8);
                ivSpec = new IvParameterSpec(block);
            }

            int offset = (blocks - 1) * 8;

            cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
            cMac = cipher.doFinal(data, offset, 8);

            ivSpec = new IvParameterSpec(new byte[8]);

            singleDesCipher.init(Cipher.ENCRYPT_MODE, desSingleKey, ivSpec);
            icvNextCommand = singleDesCipher.doFinal(cMac);
            System.out.println("icvNextCommand"+Utility.bytesToHex(icvNextCommand, icvNextCommand.length));

            return cMac;

    }
...