如何向卡上/从卡上信用或借记超过1个字节?

时间:2015-03-08 10:42:38

标签: java smartcard credit-card javacard apdu

我是新手小程序,我使用此链接:working with Java Card Wallet创建了一个电子钱包项目。  之前我可以通过此命令获得信用卡金额:80 30 00 00 01 1A 00

我现在想要添加'5000'到现在的金额。如你所知,十六进制中的5000等于

'1388'为2字节。所以我必须将2字节数据13和88发送到卡上。

我创建了波纹管命令并将其发送到卡但我得到'67 00错误的长度'

响应。

80 30 00 00 02 13 88 00

我如何向卡上/从卡中扣除1个字节以上的信用卡或借记卡?

3 个答案:

答案 0 :(得分:2)

您必须更改当前指向的Applet的代码:

if ((numBytes != 1) || (byteRead != 1)) {
    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); // constant with value 0x6700
}

所以你必须确保它允许发送2个字节,然后你可以使用Util.getShort方法将字节转换为16位有符号值(使用大端二补码表示法,像往常一样)。

答案 1 :(得分:1)

creadit()方法替换为此方法。但请记住,您必须使用两个字节的值来记入您今后的壁垒。 (即使是小于255或0xFF的值。即你必须使用0x00FF以255美元从钱包中扣款。

private void credit(APDU apdu) {

    // access authentication
    if (!pin.isValidated()) {
        ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
    }

    byte[] buffer = apdu.getBuffer();

    // Lc byte denotes the number of bytes in the
    // data field of the command APDU
    byte numBytes = buffer[ISO7816.OFFSET_LC];

    // indicate that this APDU has incoming data
    // and receive data starting from the offset
    // ISO7816.OFFSET_CDATA following the 5 header
    // bytes.
    byte byteRead = (byte) (apdu.setIncomingAndReceive());

    // it is an error if the number of data bytes
    // read does not match the number in Lc byte
    if ((numBytes != 2) || (byteRead != 2)) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // get the creditBytes
    byte[] creditBytes = new byte[2];
    creditBytes[0]=buffer[ISO7816.OFFSET_CDATA];
    creditBytes[1]=buffer[ISO7816.OFFSET_CDATA+1];

    // convert 2 byte of creatBytes to a single short value.
    short creditAmount = Util.getShort(creditBytes,(short)0);

    // check the credit amount
    if ((creditAmount > MAX_TRANSACTION_AMOUNT) || (creditAmount < 0)) {
        ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
    }

    // check the new balance
    if ((short) (balance + creditAmount) > MAX_BALANCE) {
        ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE);
    }

    // credit the amount
    balance = (short) (balance + creditAmount);

}

答案 2 :(得分:0)

我建议使用BCD加法和BCD减法,如下:

  1. 每个字节代表两个BCD,例如0x99代表99而不是153。
  2. 加法和减法中包含的所有数据应具有相同的长度,例如: 6个字节代表12位数。这应该涵盖大多数情况,但如果你需要更多,只需改变你的常数。
  3. 您的applet执行循环遍历字节以执行加法或减法。在操作之前和之后,需要对BCD进行编码和解码操作,反之亦然。
  4. 以下是实施示例。它尚未经过测试,但应该让您知道它是如何工作的:

    public class BCD {
    
        public static final short NUMBER_OF_BYTES = 6;
    
        static void add(byte[] augend, byte[] addend, byte[] result) {
            byte carry = 0;
            short temp = 0;
            for (short i = (short) (NUMBER_OF_BYTES - 1); i >= 0; i--) {
                temp = (short) (decode(augend[i]) + decode(addend[i]) + carry);
                carry = (byte) ((temp > 100) ? 1 : 0);
                result[i] = encode((byte) temp);
            }
    
            if (carry == 1) {
                // TODO: result more than maximum
                // you can set all digits to 9 or throw exception
            }
        }
    
        static void subtract(byte[] minuend, byte[] subtrahend, byte[] result) {
            byte borrow = 0;
            short temp = 0;
            for (short i = (short) (NUMBER_OF_BYTES - 1); i >= 0; i--) {
                temp = (short) (100 + decode(minuend[i]) - decode(subtrahend[i]) - borrow);
                borrow = (byte) ((temp < 100) ? 1 : 0);
                result[i] = encode((byte) temp);
            }
    
            if (borrow == 1) {
                // TODO: subtrahend > minuend, 
                // you can set all digits to 0 or throw exception
            }
        }
    
        static byte encode(byte value) {
            value %= 100; // only convert two digits, ignore borrow/carry
            return (byte) (((value / 10) << 4) | (value % 10));
        }
    
        static byte decode(byte bcdByte) {
            byte highNibble = (byte) ((bcdByte >> 4) & 0x0F);
            byte lowNibble = (byte) (bcdByte & 0x0F);
    
            if ((highNibble > 9) || (lowNibble > 9)) {
                // found 'A' to 'F' character which should be invalid
                // you can change this line, e.g. throwing exception
                return 0;
            }
    
            return (byte) ((highNibble * 10) + lowNibble);
        }
    
    }