Java Card DES生成器applet输出与online-tools输出不同

编写以下小程序以在APDU数据字段上执行DES加密/解密:

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

问题是它的输出与在线工具不相同。 例如,我使用此网站计算加密值0x3030303030303030 ,密钥= 0x3030303030303030 ,这是输出:

在此处输入图像描述

现在我用我的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 

由于我不知道在线工具使用了DES_ECB_PKCS5DES_ECB_NOPADDES_ECB_ISO9797_M2DES_ECB_ISO9797_M1中的哪一个,我在我的卡中对所有这些进行了加密。 但输出与在线工具不同。

  1. 怎么了?
  2. 我如何找出上述密码中的哪一个,在线工具是否使用?

因为我不知道在线工具使用DES_ECB_PKCS5,DES_ECB_NOPAD,DES_ECB_ISO9797_M2或DES_ECB_ISO9797_M1中的哪一个

那就是问题所在。 Blockmode,padding和其他东西非常重要(并且有超过4种组合)。 对于在线工具,charset的东西(一般的输入解释)也是一个问题。

如果不详细了解在线工具,您将无法获得任何正确的信息。
只是不要使用它并搜索标准化的测试向量。

除此之外,为什么你使用DES !? 不要那么做。
它不再安全了。

您使用’00 C1 04 01 08 30 30 30 30 30 30 30 30)进行加密(30 30 30 30 30 30 30 30);

修改这个MyCipher.doFinal(缓冲区, ISO7816.OFFSET_CDATA ,datalen, CipheredData ,(short)0);

真是个好人,你为延迟而感到抱歉