带有 PIN 校验功能的钱包交易

一、实验题目

带有 PIN 校验功能的钱包交易

二、应用APDU命令

APDU: Application Protocol data unit,,是智能卡与智能卡读卡器之间传送的信息单元, (向智能卡发送的命令)指令(ISO 7816-4规范有定义):CLA INS P1 P2 Lc Data Le。

CLA:指令类别;

INS:指令码;

P1、P2:参数;

Lc:为Data的长度;

Le:为希望响应时回答的数据字节数,0表最大可能长度。

C-APDU:命令APDU组成如下

指令

CLA

INS

P1

P2

Lc

数据

Le

Verify

80

20

00

00

Pin值长度

010203040506

(本实验的pin值)

——

Credit

80

30

00

00

01

存款数值

——

Debit

80

40

00

00

01

借款数值

——

Get Balance

80

50

00

00

00

——

02

R-APDU:响应APDU组成如下

指令

说明

数据

SW1

SW2

Verify

验证成功

90

00

PIN值错误

63

00

Pin值的长度错误(不为6)

67

00

Credit

需要验证身份

63

01

单次存款超出最高限制

6A

83

存款数值超过最大数值

6A

84

存款成功

90

00

Debit

需要验证身份

63

01

单次借款超出最高限制

6A

83

余额为负值

6A

85

借款成功

90

00

Get Balance

返回余额数值

(余额数据)

90

00

Le值错误

67

00

注:

本实验设置的是8次错误锁定。

初始时设定PIN验证码为010203040506,身份验证时发送数据010203040506正确验证身份。

存款、借款时,设定单次交易数值不超过0x7F(127)。

余额总量限定为0x7FFF,且余额不能为负值。

三、程序设计说明

(给出程序总体结构、函数和处理流程的说明)

总体结构: 

  1. 设计一个电子钱包小程序,要求至少实现电子钱包安装、选择与撤销选择、存款、借款、获取身钱包余额、身份验证的功能。
  2. 身份验证可通过PIN码来设置
  3. 存款、借款、消费可以通过设置一余额变量Balance,通过读取相应操作指令,对变量Balance进行加、减、读取值来实现存款、借款、消费功能。
  4. 对不符合规定的操作,抛出异常来中断操作。

总体框架图如下:

函数

  1. 存款函数

  1. private void credit(APDU apdu) {  
  2.   
  3.   // access authentication  
  4.   if ( ! pin.isValidated() )  
  5. ISOException.throwIt(  
  6.        SW_PIN_VERIFICATION_REQUIRED);  
  7.   
  8.    byte[] buffer = apdu.getBuffer();  
  9.   
  10.    // Lc byte denotes the number of bytes in the  
  11.    // data field of the command APDU  
  12.    byte numBytes = buffer[ISO7816.OFFSET_LC];  
  13.   
  14.    // indicate that this APDU has incoming data  
  15.    // and receive data starting from the offset  
  16.    // ISO7816.OFFSET_CDATA following the 5 header  
  17.    // bytes.  
  18.    byte byteRead = (byte)(apdu.setIncomingAndReceive());  
  19.   
  20.    // it is an error if the number of data bytes  
  21.    // read does not match the number in Lc byte  
  22.    if ( ( numBytes != 1 ) || (byteRead != 1) )  
  23.     ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);  
  24.   
  25.    // get the credit amount  
  26.    byte creditAmount = buffer[ISO7816.OFFSET_CDATA];  
  27.   
  28.    // check the credit amount  
  29.    if ( ( creditAmount > MAX_TRANSACTION_AMOUNT)  
  30.         || ( creditAmount < 0 ) )  
  31.        ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);  
  32.   
  33.    // check the new balance  
  34.    if ( (short)( balance + creditAmount)  > MAX_BALANCE )  
  35.       ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE);  
  36.   
  37.    // credit the amount  
  38.    balance = (short)(balance + creditAmount);  
  39.   
  40.  } // end of deposit method  

存款流程框架图如下:

  1. 取款函数

  1. private void debit(APDU apdu) {  
  2.   
  3.   // access authentication  
  4.   if ( ! pin.isValidated() )  
  5.      ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);  
  6.   
  7.   byte[] buffer = apdu.getBuffer();  
  8.   
  9.   byte numBytes = (byte)(buffer[ISO7816.OFFSET_LC]);  
  10.   
  11.   byte byteRead = (byte)(apdu.setIncomingAndReceive());  
  12.   
  13.   if ( ( numBytes != 1 ) || (byteRead != 1) )  
  14.      ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);  
  15.   
  16.   // get debit amount  
  17.   byte debitAmount = buffer[ISO7816.OFFSET_CDATA];  
  18.   
  19.   // check debit amount  
  20.   if ( ( debitAmount > MAX_TRANSACTION_AMOUNT)  
  21.        ||  ( debitAmount < 0 ) )  
  22.      ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);  
  23.   
  24.   // check the new balance  
  25.   if ( (short)( balance - debitAmount ) < (short)0 )  
  26.        ISOException.throwIt(SW_NEGATIVE_BALANCE);  
  27.   
  28.   balance = (short) (balance - debitAmount);  
  29.   
  30. // end of debit method 

总结取款函数流程框架如下:

  1. Pin验证函数

  1. public boolean select() {  
  2.   
  3.   // The applet declines to be selected  
  4.   // if the pin is blocked.  
  5.   if ( pin.getTriesRemaining() == 0 )  
  6.      return false;  
  7.   else  
  8.      return true;  
  9. }  
  10.   
  11. public void deselect() {  
  12.   
  13.   // reset the pin value  
  14.   pin.reset();  
  15.   
  16. }  
  1. private void verify(APDU apdu) {  
  2.   
  3.   byte[] buffer = apdu.getBuffer();  
  4.   // retrieve the PIN data for validation.  
  5.     
  6.   byte byteRead = (byte)(apdu.setIncomingAndReceive());  
  7.   
  8. // check pin  
  9.   // the PIN data is read into the APDU buffer  
  10. // at the offset ISO7816.OFFSET_CDATA  
  11. // the PIN data length = byteRead  
  12.    
  13.   //判断输入pin值长度是否为6  
  14.   if (byteRead != 6) {  
  15.       // If the length is not 6, throw SW_WRONG_LENGTH exception  
  16.       ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);  
  17.   }  
  18.     
  19.   if ( pin.check(buffer, ISO7816.OFFSET_CDATA, byteRead) == false )  
  20.       /ISOException.throwIt(SW_VERIFICATION_FAILED);  

PIN验证流程框架如下图:

  1. 查询余额函数

  1. private void getBalance(APDU apdu) {  
  2.   
  3.   byte[] buffer = apdu.getBuffer();  
  4.   
  5.   // inform system that the applet has finished  
  6.   // processing the command and the system should  
  7.   // now prepare to construct a response APDU  
  8.   // which contains data field  
  9.   short le = apdu.setOutgoing();  
  10.   
  11.   if ( le < 2 )  
  12.      ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);  
  13.   
  14.   //informs the CAD the actual number of bytes  
  15.   //returned  
  16.   apdu.setOutgoingLength((byte)2);  
  17.   
  18.   // move the balance data into the APDU buffer  
  19.   // starting at the offset 0  
  20.   buffer[0] = (byte)(balance >> 8);  
  21.   buffer[1] = (byte)(balance & 0xFF);  
  22.   
  23.   // send the 2-byte balance at the offset  
  24.   // 0 in the apdu buffer  
  25.   apdu.sendBytes((short)0, (short)2);  
  26.   
  27. // end of getBalance method  

查询余额流程框架图如下:

  1. 测试APDU命令集

(给出测试脚本的设计说明)

#选择我们的钱包

/select 112233445501

#验证PIN值

/send 8020000006010203040506

#查询余额

/send 805000000002

#从钱包里取0x64的钱

/send 804000000164

#0x6A85 = SW_NEGATIVE_BALANCE

#往钱包里存0x64的钱

/send 803000000164

#查询余额

/send 805000000002

#0x00 0x64 0x9000 = Balance = 100 and SW_NO_ERROR

#从钱包里取0x32的钱

/send 804000000132

#0x9000 = SW_NO_ERROR

#查询余额

/send 805000000002

#0x00 0x32 0x9000 = Balance = 50 and SW_NO_ERROR

#往钱包里存0x80的钱

/send 803000000180

#0x6A83 = SW_INVALID_TRANSACTION_AMOUNT

#输入错误的pin值

/send 802000000401030266

#0x6300 = SW_VERIFICATION_FAILED

#用错误的le值取款

/send 805000000001

#0x6700 = ISO7816.SW_WRONG_LENGTH

  1. 测试运行结果

(给出实际运行结果的截图和说明)

#选择钱包,输入钱包的uid值112233445501

#返回9000,表示操作成功

#输入pin值,010203040506

#返回9000,表示pin值正确

#输入错误的pin值

#返回63 00,表示pin值错误

#输入pin值的长度不为0x06

#会抛出异常,返回67 00,表示长度错误

#尝试pin值达到上限(本实验设置的是8次)后,再次输入正确的密码,也会返回false

#进行查询余额的操作

#查到余额是0,返回9000表示操作成功

#进行从余额为0的钱包里取款0x64的操作

#返回6A 85表示取款失败,因为钱包不能为负值

#存款0x64的钱,接着查询钱包余额

#存款成功,钱包里有0x64的钱

#取0x32的钱,接着查询余额

#取款成功,余额还剩0x32

#取0x80的钱

#取款失败,因为之前设置过单次交易的金额不能超过0x7F

#想查看余额

#操作错误,因为get balance的le值是02而不是01

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值