The output of the DES Java card generator applet is different from the output of the online tools

The following applet is written to encrypt / decrypt DES in the APDU data field:

package cryptoPack;

import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.JCSystem;
import javacard.framework.Util;
import javacard.security.CryptoException;
import javacard.security.DESKey;
import javacard.security.KeyBuilder;
import javacardx.crypto.Cipher;

public class CryptoDES extends Applet {

    // Array for the encryption/decryption key
    private byte[] TheDES_Key = { (byte) 0x00, (byte) 0x00, (byte) 0x00,
            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
            (byte) 0x00 };

    // Defining required Keys
    DESKey MyDES1Key = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES,
            KeyBuilder.LENGTH_DES, false);
    DESKey MyDES2Key = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES,
            KeyBuilder.LENGTH_DES3_2KEY, false);
    DESKey MyDES3Key = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES,
            KeyBuilder.LENGTH_DES3_3KEY, false);

    byte ConfiguredKeyLength;

    // Defining required cipher
    Cipher MyCipher;

    // Defining switch case variables for supported instructions = INS in APDU command
    final byte SetKey = (byte) 0xC0;
    final byte OneKeyDES = (byte) 0xC1;
    final byte TwoKeyDES = (byte) 0xC2;
    final byte ThreeKeyDES = (byte) 0xC3;

    // Defining switch case variables for cipher algorithms = P1 in APDU command
    final byte DES_CBC_ISO9797_M1 = (byte) 0x00;
    final byte DES_CBC_ISO9797_M2 = (byte) 0x01;
    final byte DES_CBC_NOPAD = (byte) 0x02;
    final byte DES_CBC_PKCS5 = (byte) 0x03;
    final byte DES_ECB_ISO9797_M1 = (byte) 0x04;
    final byte DES_ECB_ISO9797_M2 = (byte) 0x05;
    final byte DES_ECB_NOPAD = (byte) 0x06;
    final byte DES_ECB_PKCS5 = (byte) 0x07;

    // Defining Proprietary Status Words
    final short KeyInNotSetGood = 0x6440;

    // A flag to be sure that the configured key has the same length that the
    // algorithm needs.

    private CryptoDES() {

    }

    public static void install(byte bArray[], short bOffset, byte bLength)
            throws ISOException {
        new CryptoDES().register();
    }

    public void process(APDU apdu) throws ISOException {

        // Assigning 0 to "ConfiguredKeyLength" to force the user to use ...
        // ... "SetKey" command, after applet selection.
        if (selectingApplet()) {
            ConfiguredKeyLength = 0;
            return;
        }

        byte[] buffer = apdu.getBuffer();

        // Checking the CLA field in the APDU command.
        if (buffer[ISO7816.OFFSET_CLA] != 0) {
            ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
        }

        // Checking the P1 and P2 fields in the APDU command.
        if (buffer[ISO7816.OFFSET_P1] > 7 || buffer[ISO7816.OFFSET_P2] > 1) {
            ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
        }

        // Analyzing the command.
        try {

            switch (buffer[ISO7816.OFFSET_INS]) {

            case SetKey:
                SetCryptoKeyAndInitCipher(apdu);
                break;

            case OneKeyDES:

                OneKeyDESCrypto(apdu);
                DoEncryptDecrypt(apdu);

                break;

            case TwoKeyDES:
                TwoKeyDESCrypto(apdu);
                DoEncryptDecrypt(apdu);
                break;

            case (byte) ThreeKeyDES:
                ThreeKeyDESCrypto(apdu);
                DoEncryptDecrypt(apdu);
                break;

            default:
                ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);

            }

        } catch (CryptoException e) {
            ISOException.throwIt(((CryptoException) e).getReason());
        }

    }

    public void SetCryptoKeyAndInitCipher(APDU apdu)
            throws ISOException {
        byte[] buffer = apdu.getBuffer();
        // Key must has a length of 8, 16 or 24 bytes
        if (buffer[ISO7816.OFFSET_LC] == 8 || buffer[ISO7816.OFFSET_LC] == 16
                || buffer[ISO7816.OFFSET_LC] == 24) {
            Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, TheDES_Key,
                    (short) 0, buffer[ISO7816.OFFSET_LC]);

            ConfiguredKeyLength = buffer[ISO7816.OFFSET_LC];

        } else {
            ISOException.throwIt(ISO7816.SW_DATA_INVALID);
        }

        switch (buffer[ISO7816.OFFSET_P1]) {
        case DES_CBC_ISO9797_M1:
            MyCipher = Cipher.getInstance(Cipher.ALG_DES_CBC_ISO9797_M1, false);
            break;
        case DES_CBC_ISO9797_M2:
            MyCipher = Cipher.getInstance(Cipher.ALG_DES_CBC_ISO9797_M2, false);
            break;
        case DES_CBC_NOPAD:
            MyCipher = Cipher.getInstance(Cipher.ALG_DES_CBC_NOPAD, false);
            break;
        case DES_CBC_PKCS5:
            MyCipher = Cipher.getInstance(Cipher.ALG_DES_CBC_PKCS5, false);
            break;
        case DES_ECB_ISO9797_M1:
            MyCipher = Cipher.getInstance(Cipher.ALG_DES_ECB_ISO9797_M1, false);
            break;
        case DES_ECB_ISO9797_M2:
            MyCipher = Cipher.getInstance(Cipher.ALG_DES_ECB_ISO9797_M2, false);
            break;
        case DES_ECB_NOPAD:
            MyCipher = Cipher.getInstance(Cipher.ALG_DES_ECB_NOPAD, false);
            break;
        case DES_ECB_PKCS5:
            MyCipher = Cipher.getInstance(Cipher.ALG_DES_ECB_PKCS5, false);
            break;

        }

    }

    public void OneKeyDESCrypto(APDU apdu)
            throws ISOException {
        byte[] buffer = apdu.getBuffer();
        // Check to see if the configured key is the required key for this ...
        // ... algorithm or not
        if (ConfiguredKeyLength != 8) {
            ISOException.throwIt(KeyInNotSetGood);
        }
        MyDES1Key.setKey(TheDES_Key, (short) 0);

        if (buffer[ISO7816.OFFSET_P2] == 1) {
            MyCipher.init(MyDES1Key, Cipher.MODE_ENCRYPT);
        } else {
            MyCipher.init(MyDES1Key, Cipher.MODE_DECRYPT);

        }

    }

    public void TwoKeyDESCrypto(APDU apdu)
            throws ISOException {
        byte[] buffer = apdu.getBuffer();
        // Check to see if the configured key is the required key for this ...
        // ... algorithm or not

        if (ConfiguredKeyLength != 16) {
            ISOException.throwIt(KeyInNotSetGood);
        }
        MyDES2Key.setKey(TheDES_Key, (short) 0);

        if (buffer[ISO7816.OFFSET_P2] == 1) {
            MyCipher.init(MyDES2Key, Cipher.MODE_ENCRYPT);
        } else {
            MyCipher.init(MyDES2Key, Cipher.MODE_DECRYPT);

        }

    }

    public void ThreeKeyDESCrypto(APDU apdu)
            throws ISOException {
        byte[] buffer = apdu.getBuffer();
        // Check to see if the configured key is the required key for this ...
        // ... algorithm or not
        if (ConfiguredKeyLength != 24) {
            ISOException.throwIt(KeyInNotSetGood);
        }

        MyDES3Key.setKey(TheDES_Key, (short) 0);

        if (buffer[ISO7816.OFFSET_P2] == 1) {
            MyCipher.init(MyDES3Key, Cipher.MODE_ENCRYPT);
        } else {
            MyCipher.init(MyDES3Key, Cipher.MODE_DECRYPT);

        }

    }

    public void DoEncryptDecrypt(APDU apdu) {
        byte[] buffer = apdu.getBuffer();

        byte[] CipheredData = JCSystem.makeTransientByteArray((short) 32,
                JCSystem.CLEAR_ON_DESELECT);

        short datalen = apdu.setIncomingAndReceive();
        if ((datalen % 8) != 0) {
            ISOException.throwIt(ISO7816.SW_DATA_INVALID);
        }

        MyCipher.doFinal(buffer, (short) 0, datalen, CipheredData, (short) 0);
        Util.arrayCopyNonAtomic(CipheredData, (short) 0, buffer, (short) 0,
                datalen);
        apdu.setOutgoingAndSend((short) 0, datalen);
    }

}

      

The problem is that its output is not equal to online tools. for example i am using this website to compute an encrypted value 0x3030303030303030

with key = 1122334455667788

and this is outputted:

enter image description here

Now I repeat the above encryption with my applet:

OpenSC:: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00c0000008112233
4455667788 -s 00c10401083030303030303030
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 C0 00 00 08 11 22 33 44 55 66 77 88
Received (SW1=0x90, SW2=0x00)
Sending: 00 C1 04 01 08 30 30 30 30 30 30 30 30
Received (SW1=0x90, SW2=0x00):
8E 43 CF B8 91 02 01 38 .C.....8

OpenSC:: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00c0000008112233
4455667788 -s 00c10501083030303030303030
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 C0 00 00 08 11 22 33 44 55 66 77 88
Received (SW1=0x90, SW2=0x00)
Sending: 00 C1 05 01 08 30 30 30 30 30 30 30 30
Received (SW1=0x90, SW2=0x00):
A6 DE 1C D9 1B A9 EE D0 ........

OpenSC:: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00c0000008112233
4455667788 -s 00c10601083030303030303030
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 C0 00 00 08 11 22 33 44 55 66 77 88
Received (SW1=0x90, SW2=0x00)
Sending: 00 C1 06 01 08 30 30 30 30 30 30 30 30
Received (SW1=0x90, SW2=0x00):
0B FC BF EE 82 F4 8B 19 ........

OpenSC:: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00c0000008112233
4455667788 -s 00c10701083030303030303030
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 C0 00 00 08 11 22 33 44 55 66 77 88
Received (SW1=0x90, SW2=0x00)
Sending: 00 C1 07 01 08 30 30 30 30 30 30 30 30
Received (SW1=0x90, SW2=0x00):
AA 6E 4D 79 E5 0C B1 51 .nMy...Q

      

Since I did not know which of the DES_ECB_PKCS5

, DES_ECB_NOPAD

, DES_ECB_ISO9797_M2

, or DES_ECB_ISO9797_M1

use the online tool, I do encryption with all of them on your map. but the result is different from the online tool.

  • What's wrong?
  • How can I find out which of the above ciphers the online tool is using?
+3


source to share


2 answers


As I didn't know which of DES_ECB_PKCS5, DES_ECB_NOPAD, DES_ECB_ISO9797_M2 or DES_ECB_ISO9797_M1 is being used by the online tool.

That's the problem. Block mod, spacer and other things are very important (and there are many more than 4 combinations). And in the case of online tools, the encoding issue (introductory interpretation in general) is also an issue.



Without knowing the online tool in detail, you won't get anything with this. Just don't use it and look for standardized test vectors.

Also, why are you using DES !? Stop it.
He is no longer protected.

+1


source


You do encryption from '00 C1 04 01 08 30 30 30 30 30 30 30 30) not (30 30 30 30 30 30 30 30);

change only this MyCipher.doFinal (buffer, ISO7816.OFFSET_CDATA , datalen, CipheredData, (short) 0);



Really good problems you regret the delay

0


source







All Articles