
设计一个电子钱包小程序,要求至少实现电子钱包安装、选择与撤销选择、存款、借款、获取身钱包余额、身份验证的功能。
身份验证可通过PIN码来设置。
存款、借款、消费可以通过设置一余额变量Balance,通过读取相应操作指令,对变量Balance进行加、减、读取值来实现存款、借款、消费功能。
对不符合规定的操作,抛出异常来中断操作。
C-APDU
| CLA | INS | P1 | P2 | Lc | 数据 | Le | |
| Verify | 90 | 20 | 00 | 00 | 04 | 01020304 | 00 | 
| Credit | 90 | 30 | 00 | 00 | 01 | 存款数值 | 00 | 
| Debit | 90 | 40 | 00 | 00 | 01 | 借款数值 | 00 | 
| Get Balance | 90 | 50 | 00 | 00 | 00 | —— | 02 | 
R-APDU
| 指令 | 说明 | 数据 | SW1 | SW2 | 
| Verify | 验证成功 | —— | 90 | 00 | 
| PIN值错误 | —— | 63 | 00 | |
| Credit | 存款成功 | —— | 90 | 00 | 
| 需要验证身份 | —— | 63 | 01 | |
| 单次存款超出最高限制 | —— | 6A | 83 | |
| 存款数值超过最大数值 | —— | 6A | 84 | |
| Debit | 借款成功 | —— | 90 | 00 | 
| 需要身份验证 | —— | 63 | 01 | |
| 单次借款超出最高限制 | —— | 6A | 83 | |
| 余额为负值 | —— | 6A | 85 | |
| Get Balance | 返回余额数值 | (余额数据) | 90 | 00 | 
注:
采用源码为《JAVA智能卡原理与应用开发》一书中示例
电子钱包安装选择成功。
抛出异常:0x6301,pin码身份验证未通过。
抛出异常:0x6300,身份验证失败。
身份验证成功。
余额此时为0。
抛出异常:0x6A83,超出单次交易额最大值。
余额仍为0。
余额为存款金额0x70 = 112。
抛出异常:0x6A85,无效余额,借款失败;
余额不变,仍为0x70。
借款成功,余额0x50。
存款成功,余额0xC5
存款成功,余额0x0135
package wallet;import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.APDU;
import javacard.framework.*;/*** @author JiFengZ**/
public class WALLET extends Applet {final static byte Wallet_CLA = (byte)0x90;final static byte VERIFY = (byte)0x20;final static byte CREDIT = (byte)0x30;final static byte DEBIT = (byte)0x40;final static byte GET_BALANCE = (byte)0x50;final static short MAX_BALANCE = 0x7530;final static byte MAX_TRANSACTION_AMOUNT = 127;final static byte PIN_TRY_LIMIT = (byte)0x03;final static byte MAX_PIN_SIZE = (byte)0x08;final static short SW_VERIFICATION_FAILED = 0x6300;final static short SW_PIN_VERIFICATION_REQUIRED = 0x6301;final static short SW_INVALID_TRANSACTION_AMOOUNT = 0x6A83;final static short SW_EXCEED_MAXIMUM_BALANCE = 0x6A84;final static short SW_NEGATIVE_BALANCE = 0x6A85;OwnerPIN pin;short balance;/*private WALLET(byte[] bArray, short bOffset, byte bLength){pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);byte iLen = bArray[bOffset];bOffset = (short)(bOffset + iLen + 1);byte cLen = bArray[bOffset];bOffset = (short)(bOffset + cLen + 1);byte aLen = bArray[bOffset];pin.update(bArray, (short)(bOffset + 1), aLen);register();}*/public static void install(byte[] bArray, short bOffset, byte bLength) {// GP-compliant JavaCard applet registrationnew WALLET().register(bArray, (short) (bOffset + 1), bArray[bOffset]);//new WALLET(bArray, bOffset, bLength);}public boolean select(){TriesRemaining() == 0)return false;return true;}public void deselect(){set();}public void process(APDU apdu) {/*// Good practice: Return 9000 on SELECTif (selectingApplet()) {return;}*/byte[] buffer = Buffer();buffer[ISO7816.OFFSET_CLA] = (byte)(buffer[ISO7816.OFFSET_CLA] & (byte)0xFC);if((buffer[ISO7816.OFFSET_CLA] == 0) &&(buffer[ISO7816.OFFSET_INS] == (byte)(0xA4)))return;if(buffer[ISO7816.OFFSET_CLA] != Wallet_CLA)ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);switch (buffer[ISO7816.OFFSET_INS]) {case GET_BALANCE:getBalance(apdu);return;case DEBIT:debit(apdu);return;case CREDIT:credit(apdu);return;case VERIFY:verify(apdu);return;default:// good practice: If you don't know the INStruction, say so:ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);}}private void credit(APDU apdu){if(!pin.isValidated())ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);byte[] buffer = Buffer();byte numBytes = buffer[ISO7816.OFFSET_LC];byte byteRead = (byte)(apdu.setIncomingAndReceive());if((numBytes != 1) || (byteRead != 1))ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);byte creditAmount = buffer[ISO7816.OFFSET_CDATA];if((creditAmount > MAX_TRANSACTION_AMOUNT) || (creditAmount < 0))ISOException.throwIt(SW_INVALID_TRANSACTION_AMOOUNT);if((short)(balance + creditAmount) > MAX_BALANCE)ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE);balance = (short)(balance + creditAmount);		}private void debit(APDU apdu){if(!pin.isValidated())ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);byte[] buffer = Buffer();byte numBytes = buffer[ISO7816.OFFSET_LC];byte byteRead = (byte)(apdu.setIncomingAndReceive());if((numBytes != 1) || (byteRead != 1))ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);byte debitAmount = buffer[ISO7816.OFFSET_CDATA];if((debitAmount > MAX_TRANSACTION_AMOUNT) || (debitAmount < 0))ISOException.throwIt(SW_INVALID_TRANSACTION_AMOOUNT);if((short)(balance - debitAmount) < (short)0)ISOException.throwIt(SW_NEGATIVE_BALANCE);balance = (short)(balance - debitAmount);}private void getBalance(APDU apdu){byte[] buffer = Buffer();short le = apdu.setOutgoing();if(le < 2)ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);apdu.setOutgoingLength((byte)2);buffer[0] = (byte)(balance >> 8);buffer[1] = (byte)(balance & 0xFF);apdu.sendBytes((short)0, (short)2);}private void verify(APDU apdu){byte[] buffer = Buffer();byte byteRead = (byte)(apdu.setIncomingAndReceive());if(pin.check(buffer, ISO7816.OFFSET_CDATA, byteRead) == false)ISOException.throwIt(SW_VERIFICATION_FAILED);}}本文发布于:2024-03-16 06:59:06,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/1717133435272991.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
| 留言与评论(共有 0 条评论) |