Java 卡 检测到与智能卡的通信错误

标签 java eclipse javacard apdu

我使用 Java Card 2.1.2 SDK 和 GPShell 作为与设备通信的方式在 Java Card 上构建一个项目。我从 GpShell 测试了 helloworld 示例,并成功发送了 Simple APDU 。但是,当我尝试将 APDU 发送到更大的 .cap 文件时,设备给出以下错误

send_APDU() returns 0x8010002F (A communications error with the smart card has b
een detected. Retry the operation.
)

我附上了下面小程序中的代码片段。尽管 Java Card 有 80 Kb EEPROM 和几乎 2 Kb RAM,但在我看来,这是一个内存问题。在 Eclipse 模拟器中,该应用程序运行良好。

TwineCipher.java

 public class TwineCipher implements IConsts{

    /**
     * The 80 bits of cipher twine
     */

    public static final short MAX_MEMORY_TEMPORARY=32;
    private static  TwineCipher ref_twineCipher_80 = null;
    private static  TwineCipher ref_twineCipher_128 = null;

    public  byte[] temp   =  JCSystem.makeTransientByteArray(MAX_MEMORY_TEMPORARY,JCSystem.CLEAR_ON_DESELECT);
    public  byte[] rk   = JCSystem.makeTransientByteArray((short) ((short)36*8),JCSystem.CLEAR_ON_DESELECT); 

    private static byte  [] roundconst = 
        {
                0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x23, 0x05, 0x0a, 0x14, 0x28, 0x13, 0x26,
                0x0f, 0x1e, 0x3c, 0x3b, 0x35, 0x29, 0x11, 0x22, 0x07, 0x0e, 0x1c, 0x38, 0x33, 0x25, 0x09, 0x12, 0x24, 0x0b,
        };

    private static short [] shufinv = {1, 2, 11, 6, 3, 0, 9, 4, 7, 10, 13, 14, 5, 8, 15, 12};
    private static short [] shuf = { 5, 0, 1, 4, 7, 12, 3, 8, 13, 6, 9, 2, 15, 10, 11, 14};
    private static byte  [] sbox = {0x0C, 0x00, 0x0F, 0x0A, 0x02, 0x0B, 0x09, 0x05, 0x08, 0x03, 0x0D, 0x07, 0x01, 0x0E, 0x06, 0x04};
    private static byte  [] data_enc  = new byte[16];

    public static TwineCipher getInstance(byte type,byte[] key)
    {
        switch(type)
        {
            case TWINE_CIPHER_80:
                if(ref_twineCipher_80 != null)
                    return ref_twineCipher_80;
                ref_twineCipher_80 =  new TwineCipher(key,TWINE_CIPHER_80);
                return ref_twineCipher_80;
            case TWINE_CIPHER_128:
                if(ref_twineCipher_128 != null)
                    return ref_twineCipher_128;
                ref_twineCipher_128 =  new TwineCipher(key,TWINE_CIPHER_128);
                return ref_twineCipher_128;
            default:
                ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
        }
        ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
        return null;
    }

    public static TwineCipher getInstance(byte type)
    {
        switch(type)
        {
            case TWINE_CIPHER_80:
                if(ref_twineCipher_80 != null)
                    return ref_twineCipher_80;
                ref_twineCipher_80 =  new TwineCipher();
                return ref_twineCipher_80;
            case TWINE_CIPHER_128:
                if(ref_twineCipher_128 != null)
                    return ref_twineCipher_128;
                ref_twineCipher_128 =  new TwineCipher();
                return ref_twineCipher_128;
            default:
                ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
        }
        ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
        return null;
    }
    private TwineCipher(byte[] key,byte keySize)
    {
        switch(keySize)
        {
            case TWINE_CIPHER_80:
                expand80Key(key);
                break;
            case TWINE_CIPHER_128:
                expand128Key(key);
                break;
            default:
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }
    }
    private TwineCipher()
    {

    }

    private void expand80Key(byte[] key)
    {
        short len_x = 20;
        short key_size = 10;
        short iterator = 0,iterator2=0;;
        byte temp_val=-1;
        byte temp_val2=-1,temp_val3=-1,temp_val4=-1;
        short sh=0;
        // reset the array
        Util.arrayFillNonAtomic(temp, (short)0, (short)20, IConsts.UNTOUCHED_VALUE);

        unrowl80ExpandKey(key);

        for ( iterator = 0 ; iterator < 35;iterator ++)
        {
            rk[(short)(iterator * 8 + 0)] = temp[1];
            rk[(short)(iterator * 8 + 1)] = temp[3];
            rk[(short)(iterator * 8 + 2)] = temp[4];
            rk[(short)(iterator * 8 + 3)] = temp[6];
            rk[(short)(iterator * 8 + 4)] = temp[13];
            rk[(short)(iterator * 8 + 5)] = temp[14];
            rk[(short)(iterator * 8 + 6)] = temp[15];
            rk[(short)(iterator * 8 + 7)] = temp[16];

            temp[1] ^= sbox[temp[0]];
            temp[4] ^= sbox[temp[16]];
            temp_val = roundconst[iterator];
            temp[7] ^= temp_val >> 3;
            temp[19] ^= temp_val & 7;

            temp_val  = temp[0];
            temp_val2 = temp[1];
            temp_val3 = temp[2];
            temp_val4 = temp[3];

            for (iterator2 = 0 ; iterator2 < 4;iterator2++)
            {
                sh                  = (short)(iterator2*4);
                temp[sh]            = temp[(short)(sh+4)];
                temp[(short)(sh+1)] = temp[(short)(sh+5)];
                temp[(short)(sh+2)] = temp[(short)(sh+6)];
                temp[(short)(sh+3)] = temp[(short)(sh+7)];
            }

            temp[16]   = temp_val2;
            temp[17]   = temp_val3;
            temp[18]   = temp_val4;
            temp[19]   = temp_val;

        }
        rk[(short)(35 * 8 + 0)] = temp[1];  
        rk[(short)(35 * 8 + 1)] = temp[3];  
        rk[(short)(35 * 8 + 2)] = temp[4];  
        rk[(short)(35 * 8 + 3)] = temp[6];  
        rk[(short)(35 * 8 + 4)] = temp[13]; 
        rk[(short)(35 * 8 + 5)] = temp[14]; 
        rk[(short)(35 * 8 + 6)] = temp[15]; 
        rk[(short)(35 * 8 + 7)] = temp[16]; 

    }
    private void expand128Key(byte[] key)
    {

    }

    public byte[] encrypt(byte[] src,byte[] dest,short len_src)
    {
        Util.arrayFillNonAtomic(temp, (short)0, (short)32, IConsts.UNTOUCHED_VALUE); //reset all values 
                                                   // 16 bytes for first part
                                                  // 16 bytes for next
        short iterator=0,iterator2=0,iterator3=0;
        short START_ITERATOR = 16;
        for( iterator = 0 ; iterator < len_src ; iterator++)
        {
            temp[(short)(2*iterator)] = (byte)((short) (src[iterator] & 0x00FF) >> 4);
            temp[(short)(2*iterator+1)] = (byte)((short) (src[iterator] & 0x00FF) & 0x0F);
        }

        for ( iterator = 0 ; iterator < 35 ; iterator ++)
        {
            for ( iterator2 = 0 ; iterator2 < 8 ; iterator2 ++)
            {
                temp[(short)(2*iterator2+1)] ^= sbox[temp[(short)(2*iterator2)] ^ rk[(short)(iterator*8+iterator2)]]; 

            }

            for (iterator3 = 0 ; iterator3 < 16;iterator3++)
            {
                temp[(short)(shuf[iterator3]+16)] = temp[(short)(iterator3)];
            }
            Util.arrayCopy(temp, (short)16, temp, (short)0, (short)16);
        }
        iterator = 35;
        for (iterator2 = 0; iterator2 < 8 ;iterator2++)
        {
            temp[(short)(2*iterator2+1)] ^= sbox[temp[(short)(2*iterator2)]^ rk[(short)(iterator*8+iterator2)]];        
        }

        for ( iterator = 0 ;iterator < 8 ;iterator++)
        {
            temp[(short)(24+iterator)] = (byte)(temp[(short)(2*iterator)] << 4 | temp[(short)(2*iterator + 1)]);
        }
        Util.arrayCopy(temp, (short)24, dest, (short)(ISO7816.OFFSET_CDATA), (short)8);
        return temp; // returns bytes from 24 to 32
    }
    public byte[] decrypt(byte[] src,byte[] dest,short len_src)
    {
        // for this alg len_src is always 8 
        Util.arrayFillNonAtomic(temp, (short)0, (short)32, IConsts.UNTOUCHED_VALUE); //reset all values 
        short iterator=0,iterator2=0,iterator3=0;
        short START_ITERATOR = 16;
        for( iterator = 0 ; iterator < len_src ; iterator++)
        {
            temp[(short)(2*iterator)] = (byte)((short) (src[iterator] & 0x00FF) >> 4);
            temp[(short)(2*iterator+1)] = (byte)((short) (src[iterator] & 0x00FF) & 0x0F);
        }

        for ( iterator = 35 ; iterator > 0 ; iterator --)
        {
            for ( iterator2 = 0 ; iterator2 < 8 ; iterator2 ++)
            {
                temp[(short)(2*iterator2+1)] ^= sbox[temp[(short)(2*iterator2)]^ rk[(short)(iterator*8+iterator2)]];
            }

            for (iterator3 = 0 ; iterator3 < 16;iterator3++)
            {
                temp[(short)(shufinv[iterator3]+16)] = temp[(short)(iterator3)];
            }
            Util.arrayCopy(temp, (short)16, temp, (short)0, (short)16);
        }
        //FINAL
        iterator = 0;
        for (iterator2 = 0; iterator2 < 8 ;iterator2++)
        {
            temp[(short)(2*iterator2+1)] ^= sbox[temp[(short)(2*iterator2)]^ rk[(short)(iterator*8+iterator2)]];
        }

        for ( iterator = 0 ;iterator < 8 ;iterator++)
        {
            temp[(short)(24+iterator)] = (byte)(temp[(short)(2*iterator)] << 4 | temp[(short)(2*iterator + 1)]);
        }
        Util.arrayCopy(temp, (short)24, dest, (short)(ISO7816.OFFSET_CDATA), (short)8);
        return temp; // returns bytes from 24 to 32 indexes
    }

    public short process(byte type,byte[] data,short start_offset,short len_data)
    {
        Util.arrayCopy(data, start_offset, data_enc, (short) 0, len_data);
        switch(type)
        {
            case OFFSET_P1_ENC:
                encrypt(data_enc, data, len_data);
                return (short)8;
            case OFFSET_P1_DEC:
                decrypt(data_enc, data, len_data);
                return (short)8;
            case OFFSET_P1_GEN:
                expand80Key(data_enc);
                return 10;
            default:
                return (short)-1;
        }

    }

    private void unrowl80ExpandKey(byte[] key)
    {
        temp[(short)(2*0)] = (byte)((short) (key[0] & 0x00FF) >> 4);
        temp[(short)(2*0 + 1)] = (byte)((short) (key[0] & 0x00FF) & 0x0F);  

        temp[(short)(2*1)] = (byte)((short) (key[1] & 0x00FF) >> 4);
        temp[(short)(2*1 + 1)] = (byte)((short) (key[1] & 0x00FF) & 0x0F);  

        temp[(short)(2*2)] = (byte)((short) (key[2] & 0x00FF) >> 4);
        temp[(short)(2*2 + 1)] = (byte)((short) (key[2] & 0x00FF) & 0x0F);  

        temp[(short)(2*3)] = (byte)((short) (key[3] & 0x00FF) >> 4);
        temp[(short)(2*3 + 1)] = (byte)((short) (key[3] & 0x00FF) & 0x0F);  

        temp[(short)(2*4)] = (byte)((short) (key[4] & 0x00FF) >> 4);
        temp[(short)(2*4 + 1)] = (byte)((short) (key[4] & 0x00FF) & 0x0F);  

        temp[(short)(2*5)] = (byte)((short) (key[5] & 0x00FF) >> 4);
        temp[(short)(2*5 + 1)] = (byte)((short) (key[5] & 0x00FF) & 0x0F);  

        temp[(short)(2*6)] = (byte)((short) (key[6] & 0x00FF) >> 4);
        temp[(short)(2*6 + 1)] = (byte)((short) (key[6] & 0x00FF) & 0x0F);  

        temp[(short)(2*7)] = (byte)((short) (key[7] & 0x00FF) >> 4);
        temp[(short)(2*7 + 1)] = (byte)((short) (key[7] & 0x00FF) & 0x0F);  

        temp[(short)(2*8)] = (byte)((short) (key[8] & 0x00FF) >> 4);
        temp[(short)(2*8 + 1)] = (byte)((short) (key[8] & 0x00FF) & 0x0F);  

        temp[(short)(2*9)] = (byte)((short) (key[9] & 0x00FF) >> 4);
        temp[(short)(2*9 + 1)] = (byte)((short) (key[9] & 0x00FF) & 0x0F);  
    }
}

IConst.java接口(interface)

  public interface IConsts 
{
    public static final byte UNTOUCHED_VALUE = 0x50;
    public static final byte TRUE = 0x01;
    public static final byte FALSE = 0x00;

    public static final byte OFFSET_CLA_CIPHERS = (byte) 0x00;
    public static final byte OFFSET_INS_LIGHT = (byte) 0x11;


    public static final byte OFFSET_P1_ENC   = (byte) 0x21;
    public static final byte OFFSET_P1_DEC   = (byte) 0x22;
    public static final byte OFFSET_P1_GEN   = (byte) 0x23;

    public static final byte TWINE_CIPHER_80=0x30;
    public static final byte TWINE_CIPHER_128=0x31;
    public static final byte LBLOCK_CIPHER=0x32;
}

LBlockCipher.java 

   public class LBlockCipher implements IConsts {


    public static final byte  LBLOCK_NBROUNDS =  32;
    public static final byte  LBLOCK_KEY_SIZE =  80;
    public static final short MEMORY_OUTPUT=32*4;
    public static final short MEMORY_TEMPORARY=32;  

    static final byte[] S0 = { 14, 9, 15, 0, 13, 4, 10, 11, 1, 2, 8, 3, 7, 6, 12, 5};
    static final byte[] S1 = { 4, 11, 14, 9, 15, 13, 0, 10, 7, 12, 5, 6, 2, 8, 1, 3 };
    static final byte[] S2 = { 1, 14, 7, 12, 15, 13, 0, 6, 11, 5, 9, 3, 2, 4, 8, 10 };
    static final byte[] S3 = { 7, 6, 8, 11, 0, 15, 3, 14, 9, 10, 12, 13, 5, 2, 4, 1 };
    static final byte[] S4 = { 14, 5, 15, 0, 7, 2, 12, 13, 1, 8, 4, 9, 11, 10, 6, 3 };
    static final byte[] S5 = { 2, 13, 11, 12, 15, 14, 0, 9, 7, 10, 6, 3, 1, 8, 4, 5 };
    static final byte[] S6 = { 11, 9, 4, 14, 0, 15, 10, 13, 6, 12, 5, 7, 3, 8, 1, 2 };
    static final byte[] S7 = { 13, 10, 15, 0, 14, 4, 9, 11, 2, 1, 8, 3, 7, 5, 12, 6 };
    static final byte[] S8 = { 8, 7, 14, 5, 15, 13, 0, 6, 11, 12, 9, 10, 2, 4, 1, 3 };
    static final byte[] S9 = { 11, 5, 15, 0, 7, 2, 9, 13, 4, 8, 1, 12, 14, 10, 3, 6 };  

    public  byte[] output    =  JCSystem.makeTransientByteArray(MEMORY_OUTPUT,JCSystem.CLEAR_ON_DESELECT); 
    public  byte[] temp      =  JCSystem.makeTransientByteArray(MEMORY_TEMPORARY,JCSystem.CLEAR_ON_DESELECT); 

    private static LBlockCipher m_instance_Cipher = null;

    public void keySchedule(byte[] key,short start_offset)
    {
        // use for keyR offset temp [0 - 3 ]
        short i = 0 ;
        output[(short)(0*4+3)] = key[(short)(9 + start_offset)];
        output[(short)(0*4+2)] = key[(short)(8 + start_offset)];
        output[(short)(0*4+1)] = key[(short)(7 + start_offset)];
        output[(short)(0*4+0)] = key[(short)(6 + start_offset)];

        for ( i = 1;i<32;i++)
        {
            temp[3] = key[(short)(9 + start_offset)];
            temp[2] = key[(short)(8 + start_offset)];
            temp[1] = key[(short)(7 + start_offset)];
            temp[0] = key[(short)(6 + start_offset)];

            key[(short)(9 + start_offset)] = (byte) ((((key[(short)(6 + start_offset)] & 0x07) << 5) 
                                            & 0xE0) ^ (((key[(short)(5 + start_offset)] & 0xF8) >> 3) & 0x1F));
            key[(short)(8 + start_offset)] = (byte) ((((key[(short)(5 + start_offset)]
                                            & 0x07) << 5) & 0xE0) ^ (((key[(short)(4 + start_offset)] & 0xF8) >> 3) & 0x1F));
            key[(short)(7 + start_offset)] = (byte) ((((key[(short)(4 + start_offset)] 
                                            & 0x07) << 5) & 0xE0) ^ (((key[(short)(3 + start_offset)] & 0xF8) >> 3) & 0x1F));
            key[(short)(6 + start_offset)] = (byte) ((((key[(short)(3 + start_offset)] 
                                            & 0x07) << 5) & 0xE0) ^ (((key[(short)(2 + start_offset)] & 0xF8) >> 3) & 0x1F));
            key[(short)(5 + start_offset)] = (byte) ((((key[(short)(2 + start_offset)] & 0x07) << 5) 
                                            & 0xE0) ^ (((key[(short)(1 + start_offset)] & 0xF8) >> 3) & 0x1F));

            key[(short)(4 + start_offset)] = (byte) ((((key[(short)(1 + start_offset)] & 0x07) << 5) 
                                            & 0xE0) ^ (((key[(short)(0 + start_offset)] & 0xF8) >> 3) & 0x1F));
            key[(short)(3 + start_offset)] = (byte) ((((key[(short)(0 + start_offset)] & 0x07) << 5) 
                                            & 0xE0) ^ (((temp[3] & 0xF8) >> 3) & 0x1F));
            key[(short)(2 + start_offset)] = (byte) ((((temp[3] & 0x07) << 5) & 0xE0) ^ (((temp[2] & 0xF8) >> 3) & 0x1F));
            key[(short)(1 + start_offset)] = (byte) ((((temp[2] & 0x07) << 5) & 0xE0) ^ (((temp[1] & 0xF8) >> 3) & 0x1F));
            key[(short)(0 + start_offset)] = (byte) ((((temp[1] & 0x07) << 5) & 0xE0) ^ (((temp[0] & 0xF8) >> 3) & 0x1F));

            key[(short)(9 + start_offset)] = (byte) ((S9[((key[(short)(9 + start_offset)] >> 4) & 0x0F)] << 4)
                                            ^ S8[(key[(short)(9 + start_offset)] & 0x0F)]);

            key[(short)(6 + start_offset)] = (byte) (key[(short)(6 + start_offset)] ^ ((i >> 2) & 0x07));
            key[(short)(5 + start_offset)] = (byte) (key[(short)(5 + start_offset)] ^ ((i & 0x03) << 6));

            output[(short)(i*4 + 3)] =  key[(short)(9 + start_offset)];
            output[(short)(i*4 + 2)] =  key[(short)(8 + start_offset)];
            output[(short)(i*4 + 1)] =  key[(short)(7 + start_offset)];
            output[(short)(i*4 + 0)] =  key[(short)(6 + start_offset)];;
        }
    }
    public void OneRound(byte[] x,byte[] k,short offset,short offset_x)
    {
        // t  - from 5 - 8 tmp from 9 to 12
        //  u8 t[4], tmp[4];

        temp[9]  = x[(short)(4 + offset_x)];
        temp[10] = x[(short)(5 + offset_x)];
        temp[11] = x[(short)(6 + offset_x)];
        temp[12] = x[(short)(7 + offset_x)];

        x[(short)(4 + offset_x)] ^= k[offset];
        x[(short)(5 + offset_x)] ^= k[(short)(offset+1)];
        x[(short)(6 + offset_x)] ^= k[(short)(offset+2)];
        x[(short)(7 + offset_x)] ^= k[(short)(offset+3)];

        x[(short)(4 + offset_x)] = (byte) (((S1[((x[(short)(4 + offset_x)]) >> 4) & 0x0F]) << 4) 
                                ^ S0[(x[(short)(4 + offset_x)] & 0x0F)]);
        x[(short)(5 + offset_x)] = (byte) (((S3[((x[(short)(5 + offset_x)]) >> 4) & 0x0F]) << 4) 
                                ^ S2[(x[(short)(5 + offset_x)] & 0x0F)]);
        x[(short)(6 + offset_x)] = (byte) (((S5[((x[(short)(6 + offset_x)]) >> 4) & 0x0F]) << 4) 
                                ^ S4[(x[(short)(6 + offset_x)] & 0x0F)]);
        x[(short)(7 + offset_x)]= (byte) (((S7[((x[(short)(7 + offset_x)]) >> 4) & 0x0F]) << 4)
                                ^  S6[(x[(short)(7 + offset_x)] & 0x0F)]);

        temp[5] = (byte) (((x[(short)(4 + offset_x)] >> 4) & 0x0F) ^ (x[(short)(5 + offset_x)] & 0xF0));
        temp[6] = (byte) ((x[(short)(4 + offset_x)] & 0x0F) ^ ((x[(short)(5 + offset_x)] & 0x0F) << 4));
        temp[7] = (byte) (((x[(short)(6 + offset_x)] >> 4) & 0x0F) ^ (x[(short)(7 + offset_x)] & 0xF0));
        temp[8] = (byte) ((x[(short)(6 + offset_x)] & 0x0F) ^ ((x[(short)(7 + offset_x)] & 0x0F) << 4));

        x[(short)(4 + offset_x)] = (byte) (x[(short)(3 + offset_x)] ^ temp[5]);
        x[(short)(5 + offset_x)] = (byte) (x[(short)(0 + offset_x)] ^ temp[6]);
        x[(short)(6 + offset_x)] = (byte) (x[(short)(1 + offset_x)] ^ temp[7]);
        x[(short)(7 + offset_x)] = (byte) (x[(short)(2 + offset_x)] ^ temp[8]);

        x[(short)(0 + offset_x)] = temp[9];
        x[(short)(1 + offset_x)] = temp[10];
        x[(short)(2 + offset_x)] = temp[11];
        x[(short)(3 + offset_x)] = temp[12];


    }
    public void encrypt(byte[] x,short offset_x)
    {
        short i;
        for (i = 0; i<32; i++)
        {
            OneRound(x,output,(short)(4*i),offset_x);
        }
    }
    public void OneRoundInv(byte[] y, byte[] k,short offset,short offset_y)
    {
        // t  - from 5 - 8 tmp from 9 to 12
        //  u8 t[4], tmp[4];

        temp[9]  = y[(short)(0 + offset_y)];
        temp[10] = y[(short)(1 + offset_y)];
        temp[11] = y[(short)(2 + offset_y)];
        temp[12] = y[(short)(3 + offset_y)];

        y[(short)(0 + offset_y)] = (byte) (y[(short)(0 + offset_y)] ^ k[offset]);
        y[(short)(1 + offset_y)] = (byte) (y[(short)(1 + offset_y)] ^ k[(short)(offset+1)]);
        y[(short)(2 + offset_y)] = (byte) (y[(short)(2 + offset_y)] ^ k[(short)(offset+2)]);
        y[(short)(3 + offset_y)] = (byte) (y[(short)(3 + offset_y)] ^ k[(short)(offset+3)]);


        y[(short)(0 + offset_y)] = (byte) (((S1[((y[(short)(0 + offset_y)]) >> 4) & 0x0F]) << 4) ^ S0[(y[(short)(0 + offset_y)] & 0x0F)]);
        y[(short)(1 + offset_y)] = (byte) (((S3[((y[(short)(1 + offset_y)]) >> 4) & 0x0F]) << 4) ^ S2[(y[(short)(1 + offset_y)] & 0x0F)]);
        y[(short)(2 + offset_y)] = (byte) (((S5[((y[(short)(2 + offset_y)]) >> 4) & 0x0F]) << 4) ^ S4[(y[(short)(2 + offset_y)] & 0x0F)]);
        y[(short)(3 + offset_y)] = (byte) (((S7[((y[(short)(3 + offset_y)]) >> 4) & 0x0F]) << 4) ^ S6[(y[(short)(3 + offset_y)] & 0x0F)]);


        temp[5] = (byte) (((y[(short)(0 + offset_y)] >> 4) & 0x0F) ^ (y[(short)(1 + offset_y)] & 0xF0));
        temp[6] = (byte) ((y[(short)(0 + offset_y)] & 0x0F) ^ ((y[(short)(1 + offset_y)] & 0x0F) << 4));
        temp[7] = (byte) (((y[(short)(2 + offset_y)] >> 4) & 0x0F) ^ (y[(short)(3 + offset_y)] & 0xF0));
        temp[8] = (byte) ((y[(short)(2 + offset_y)] & 0x0F) ^ ((y[(short)(3 + offset_y)] & 0x0F) << 4));

        y[(short)(0 + offset_y)] = (byte) (y[(short)(5 + offset_y)] ^ temp[6]);
        y[(short)(1 + offset_y)] = (byte) (y[(short)(6 + offset_y)] ^ temp[7]);
        y[(short)(2 + offset_y)] = (byte) (y[(short)(7 + offset_y)] ^ temp[8]);
        y[(short)(3 + offset_y)] = (byte) (y[(short)(4 + offset_y)] ^ temp[5]);

        // PARTIE GAUCHE
        y[(short)(4 + offset_y)] = temp[9];
        y[(short)(5 + offset_y)] = temp[10];
        y[(short)(6 + offset_y)] = temp[11];
        y[(short)(7 + offset_y)] = temp[12];


    }
    public void decrypt(byte[] x,short offset_x)
    {
        short i;

        for (i = 31; i >= 0; i--)
        {
            OneRoundInv(x,output,(short)(i*4),offset_x);
        }
    }

    private LBlockCipher()
    {

    }
    public short process(byte type,byte[] data,short start_offset,short len_data)
    {
        Util.arrayCopy(data, start_offset, temp, (short) 16, len_data);
        switch(type)
        {
            case OFFSET_P1_ENC:
                encrypt(temp,(short)(16));
                Util.arrayCopy(temp,(short) 16, data, (short) start_offset, len_data);
                return (short)8;
            case OFFSET_P1_DEC:
                decrypt(temp,(short)(16));
                Util.arrayCopy(temp,(short) 16, data, (short) start_offset, len_data);
                return (short)8;
            case OFFSET_P1_GEN:
                keySchedule(temp,(short)(16));
                Util.arrayCopy(temp,(short) 16, data, (short) start_offset, len_data);
                return 10;
            default:
                return (short)-1;
        }

    }
    public static LBlockCipher getInstance()
    {
        if(m_instance_Cipher == null)
            m_instance_Cipher =  new LBlockCipher();
        return m_instance_Cipher;
    }

}

TestApplet.java

  public class TestApplet extends Applet 
            implements IConsts {
    private TestApplet()
    {   

    }

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

    public void process(APDU apdu) throws ISOException {
        if (selectingApplet()) {
            return;
        }
        byte[] buf = apdu.getBuffer();
        if(buf[ISO7816.OFFSET_CLA] != IConsts.OFFSET_CLA_CIPHERS)
            ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
        switch (buf[ISO7816.OFFSET_INS]) 
        {
            case IConsts.OFFSET_INS_LIGHT:
                processLight(apdu);
                return;
            default:
                break;
        }
    }

    private void processLight(APDU apdu)
    {
         //cla and ins are proccessed
        byte[] buf = apdu.getBuffer();
        byte state = (buf[ISO7816.OFFSET_P1]);
        byte type = (buf[ISO7816.OFFSET_P2]);
        byte count_data = buf[ISO7816.OFFSET_LC];
        if(count_data == 0x00)
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        short len_data = -1;
        switch(state)
        {
            case OFFSET_P1_ENC:
                switch(type)
                {
                    case TWINE_CIPHER_80:
                        TwineCipher m_instance = TwineCipher.getInstance(TwineCipher.TWINE_CIPHER_80);
                        len_data  = m_instance.process(OFFSET_P1_ENC, buf, (short)(ISO7816.OFFSET_CDATA), count_data);
                        apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, len_data);
                        return;
                    case TWINE_CIPHER_128:
                        TwineCipher.getInstance(TwineCipher.TWINE_CIPHER_80); //TODO change that
                        return;
                    case LBLOCK_CIPHER:
                        LBlockCipher m_instance_lblock= LBlockCipher.getInstance();
                        len_data  = m_instance_lblock.process(OFFSET_P1_ENC, buf, (short)(ISO7816.OFFSET_CDATA), count_data);
                        apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, len_data);
                        return;
                    default:
                        ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
                }
            case OFFSET_P1_DEC:
                switch(type)
                {
                    case TwineCipher.TWINE_CIPHER_80:
                        TwineCipher m_instance = TwineCipher.getInstance(TwineCipher.TWINE_CIPHER_80);
                        len_data  = m_instance.process(TwineCipher.OFFSET_P1_DEC, buf, (short)(ISO7816.OFFSET_CDATA), count_data);
                        apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, len_data);
                        return;
                    case TwineCipher.TWINE_CIPHER_128:
                        TwineCipher.getInstance(TwineCipher.TWINE_CIPHER_80); //TODO change that
                        return;
                    case LBLOCK_CIPHER:
                        LBlockCipher m_instance_lblock= LBlockCipher.getInstance();
                        len_data  = m_instance_lblock.process(OFFSET_P1_DEC, buf, (short)(ISO7816.OFFSET_CDATA), count_data);
                        apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, len_data);
                        return;
                    default:
                        ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
                }
            case OFFSET_P1_GEN:
                switch(type)
                {
                    case TwineCipher.TWINE_CIPHER_80:
                        TwineCipher m_instance = TwineCipher.getInstance(TwineCipher.TWINE_CIPHER_80);
                        len_data = m_instance.process(TwineCipher.OFFSET_P1_GEN, buf, (short)(ISO7816.OFFSET_CDATA), count_data);
                        apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, len_data);
                        return;
                    case TwineCipher.TWINE_CIPHER_128:
                        TwineCipher.getInstance(TwineCipher.TWINE_CIPHER_80); //TODO change that
                        return;
                    case LBLOCK_CIPHER:
                        LBlockCipher m_instance_lblock= LBlockCipher.getInstance();
                        len_data  = m_instance_lblock.process(OFFSET_P1_GEN, buf, (short)(ISO7816.OFFSET_CDATA), count_data);
                        apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, len_data);
                        return;
                    default:
                        ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
                }
                default:
                    break;
        }
    }

}

最佳答案

在尝试接收 APDU 缓冲区数据字段中的数据之前,必须调用以下方法:

setIncomingAndReceive()

在 APDU 对象上,否则您将收到错误。

看看this Q&Athis Q&A与您的问题相关。

替换:

case OFFSET_P1_GEN:
                switch(type)
                {
                    case TwineCipher.TWINE_CIPHER_80:
                        TwineCipher m_instance = TwineCipher.getInstance(TwineCipher.TWINE_CIPHER_80);
                        len_data = m_instance.process(TwineCipher.OFFSET_P1_GEN, buf, (short)(ISO7816.OFFSET_CDATA), count_data);
                        apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, len_data);
                        return;
// ......

case OFFSET_P1_GEN:
                switch(type)
                {
                    case TwineCipher.TWINE_CIPHER_80:
                        TwineCipher m_instance = TwineCipher.getInstance(TwineCipher.TWINE_CIPHER_80);
                        apdu.setIncomingAndReceive();
                        len_data = m_instance.process(TwineCipher.OFFSET_P1_GEN, buf, (short)(ISO7816.OFFSET_CDATA), count_data);
                        apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, len_data);
                        return;
//.....

TestApplet.java 将解决此命令的问题(仅适用于您在问题下的第一条评论中提到的命令,而不适用于其他命令),但效率不高实际上:D。因此,找到一个好的行并将此方法调用放在那里。

关于Java 卡 检测到与智能卡的通信错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36515744/

相关文章:

javacard - 在 gpshell 中更改全局平台默认 key 后,Java 卡管理器的身份验证失败

java - 如何将年和周转换为 Java Date 对象?

java - RMI 在本地主机中同时启动两个服务器,但端口不同

java - Eclipse IDE 能够生成 javacard cap 文件,但在命令行中我遇到此错误

java - 生成带有库的 jar 文件,但在 Eclipse 中没有可运行的 jar 文件

java - 无法在 OSX 上启动 Eclipse(版本不适合)

java - 比较带符号的十六进制数

java - 在没有模拟器的 Android 应用程序中对非 Android 特定代码进行单元测试

Java实践: returning same object which was passed as parameter

eclipse - 我可以与其他人同时在同一个项目上使用 Java 进行编程吗?