2016-01-25 9 views
1

返回不同的結果,我寫了下面的小程序做兩個CBC和ECB模式的AES加密和解密:AES Applet的不同卡上的

package cryptoPack; 

import javacard.framework.*; 
import javacard.security.AESKey; 
import javacard.security.CryptoException; 
import javacard.security.KeyBuilder; 
import javacardx.crypto.Cipher; 

public class CryptoAES extends Applet { 

    // Abbreviations 
    private static final boolean NO_EXTERNAL_ACCESS = false; 

    // AES Cipher AND its required key 
    Cipher cipher; 
    AESKey AESkey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, NO_EXTERNAL_ACCESS); 

    // A fixed Initial vector for AES CBC mode. 
    public byte[] IV = { (byte) 0x00, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66, 
      (byte) 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, 
      (byte) 0xFF }; 

    // Defining switch case variables for supported instructions ::: INS in APDU 
    // command 
    final byte SET_KEY = (byte) 0xC0; 
    final byte DO_CRYPTO = (byte) 0xC2; 

    // Defining switch case variables for cipher algorithms ::: P1 in APDU 
    // command 
    final byte AES_BLOCK_128_CBC_NOPAD = (byte) 0x00; 
    final byte AES_BLOCK_128_ECB_NOPAD = (byte) 0x01; 

    public static void install(byte[] bArray, short bOffset, byte bLength) { 
     new CryptoAES(); 
    } 

    protected CryptoAES() { 
     register(); 
    } 

    public void process(APDU apdu) { 

     if (selectingApplet()) { 
      return; 
     } 

     byte[] buffer = apdu.getBuffer(); 

     // Analyzing the command. 
     try { 

      switch (buffer[ISO7816.OFFSET_INS]) { 

      case SET_KEY: 
       setKeyAndInit(apdu); 
       break; 

      case DO_CRYPTO: 
       do_crypto(apdu); 

       break; 

      default: 
       ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); 

      } 

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



    public void setKeyAndInit(APDU apdu) throws ISOException { 
     byte[] buffer = apdu.getBuffer(); 
     if (buffer[ISO7816.OFFSET_LC] == 16) { 
      AESkey.setKey(buffer, (short) ISO7816.OFFSET_CDATA); 
     } else { 
      ISOException.throwIt(ISO7816.SW_DATA_INVALID); 
     } 

     switch (buffer[ISO7816.OFFSET_P1]) { 
     case AES_BLOCK_128_CBC_NOPAD: 
      cipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, NO_EXTERNAL_ACCESS); 
      break; 
     case AES_BLOCK_128_ECB_NOPAD: 
      cipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_ECB_NOPAD, NO_EXTERNAL_ACCESS); 
      break; 
     } 
    } 



    public void do_crypto(APDU apdu) throws ISOException { 
     byte[] buffer = apdu.getBuffer(); 

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

     byte[] out_data = JCSystem.makeTransientByteArray((short) 16, JCSystem.CLEAR_ON_DESELECT); 

     switch (buffer[ISO7816.OFFSET_P1]) { 

     case AES_BLOCK_128_CBC_NOPAD: 
      if(buffer[ISO7816.OFFSET_P2]== 0x00){ 
       cipher.init(AESkey, Cipher.MODE_DECRYPT, IV, (short) 0x00, (short) 0x10);  
      }else{ 
       cipher.init(AESkey, Cipher.MODE_ENCRYPT, IV, (short) 0x00, (short) 0x10);  
      } 

      break; 

     case AES_BLOCK_128_ECB_NOPAD: 
      if(buffer[ISO7816.OFFSET_P2]== 0x00){ 
       cipher.init(AESkey, Cipher.MODE_DECRYPT);  
      }else{ 
       cipher.init(AESkey, Cipher.MODE_ENCRYPT);  
      } 
      break; 

     default: 
      break; 
     } 

     short out_data_len = cipher.doFinal(buffer, (short) ISO7816.OFFSET_CDATA, datalen, out_data, 
       (short) 0); 
     Util.arrayCopyNonAtomic(out_data, (short) 0, buffer, (short) 0, out_data_len); 
     apdu.setOutgoingAndSend((short) 0, out_data_len); 
    } 

} 

在三個不同的卡上面的小程序安裝完成後,我有以下結果:

NXP JCOP V2.4.2 3 - T = 1個TPDU:

Send: 00 A4 04 00 06 01 02 03 04 07 01 00 
Recv: 90 00 
Time used: 15.000 ms 
Send: 00 C0 00 00 10 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 00 
Recv: 90 00 
Time used: 123.000 ms 
Send: 00 C2 00 00 10 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 00 
Recv: C6 11 20 8A 02 37 B4 21 82 80 BC 62 CB 14 6C 46 90 00 
Time used: 102.000 ms 
Send: 00 C2 00 01 10 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 00 
Recv: BB E0 95 7A 71 0E 04 4B FB 6B 5B 81 04 F6 7A A1 90 00 
Time used: 72.000 ms 
Send: 00 C2 01 00 10 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 00 
Recv: C6 00 02 B9 46 62 D2 56 0A 19 16 D9 07 C9 82 B9 90 00 
Time used: 73.000 ms 
Send: 00 C2 01 01 10 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 00 
Recv: E5 6E 26 F5 60 8B 8D 26 8F 25 56 E1 98 A0 E0 1B 90 00 
Time used: 73.000 ms 

兩其他卡 - T = 0 TPDU:

Send: 00 A4 04 00 06 01 02 03 04 07 01 00 
Recv: 90 00 
Time used: 675.000 ms 
Send: 00 C0 00 00 10 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 00 
Recv: 90 00 
Time used: 57.000 ms 
Send: 00 C2 00 00 10 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 00 
Recv: A8 03 C8 BC 28 C3 C9 AD EB 56 82 55 9B 7A 68 1E 90 00 
Time used: 88.000 ms 
Send: 00 C2 00 01 10 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 00 
Recv: 74 3F B8 61 66 76 1C E0 B3 85 A3 AF E7 55 D1 29 90 00 
Time used: 80.000 ms 
Send: 00 C2 01 00 10 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 00 
Recv: A8 12 EA 8F 6C 96 AF DA 63 CF 28 EE 57 A7 86 E1 90 00 
Time used: 86.000 ms 
Send: 00 C2 01 01 10 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 00 
Recv: FF A3 C7 ED 04 71 0B 98 06 7D AE 68 15 E2 75 1F 90 00 
Time used: 83.000 ms 

正如你看到的上面,結果是不同的。我將以上結果與this online tool進行比較。看來我的恩智浦JCOP卡工作正常。其他兩張卡有什麼問題?

+2

我在'setKeyAndInit'中看不到'apdu.setIncomingAndReceive()'。某些卡在調用之前不允許您訪問APDU緩衝區 - APDU緩衝區爲空。 – vojta

回答

3

在訪問INS == 0xC0 (setKeyAndInit)的APDU緩衝區之前未調用setIncomingAndReceive方法。

小應用程序接收到APDU實例從Applet.process(APDU)方法的Java卡 運行時環境處理,並且所述第一 5頭字節[CLA,INS,P1,P2,P3]是在APDU 緩衝區中可用。

在調用setIncomingAndReceive之前,在APDU緩衝區中沒有保證的數據部分,並且您不應該訪問它。但是,真正的行爲通常取決於特定的Java卡實現,這就是爲什麼您的小程序可以在恩智浦卡上正確工作。