一次debug到哭泣的经历。
龙云尧个人博客,转载请注明出处。
CSDN地址:http://blog.csdn.net/Michael753951/article/details/70481546
个人blog地址:http://yaoyl.cn/rfidshi-yan-san-zong-jie/
在实验过程中,需要不断翻阅实验课PPT之《04 电子钱包的功能》,word之《实验3文档》,CSDN大佬吕浪的课程总代码以及他的的Java card开发系列文章。
本次实验和前两次实验相比,代码量多很多,并且实验思路稍有区别。实验之前可以不太懂实验流程(主要是因为流程本身就太复杂了),但是一定要一遍又一遍阅读源代码,只有在读源码的过程中,才能体会整个验证过程,对项目中涉及到的函数方法的使用才能有一个更加深入的了解。接着自己不断重写代码,理解整个实现过程,才能对这个课程实验有较为深入的了解。
代码在未征得本人同意之前,请勿直接Ctrl+C,Ctrl+V,谢谢。
正式实验
实验分析
首先我们在PPT中知道本次实验的主要需要实现的功能是:
- 圈存
- 消费
- 余额查询
接下来我们开始看ppt《04 电子钱包的功能》和《实验3文档》。
首先是圈存功能的流程图。
流程图中我们可以分析出圈存一共有4个步骤:
- 终端发送消息初始化
- IC响应初始化,并且发送MAC1验证
- 终端验证MAC1,确认IC卡是否合法,然后发送包含MAC2的圈存命令
- IC卡验证终端机的合法性,执行完成以后返回TAC响应操作完成
接下来我们将一步一步仔细分析圈存是如何实现的。
step1:圈存机发送的初始信息如下所示。消息中包含了秘钥标识符,交易金额,终端机编号。
step2:
- IC卡根据秘钥标识符寻找圈存秘钥
- 生成过程秘钥。输入数据为[伪随机数||电子钱包联机交易序号||8000],秘钥为圈存秘钥,使用3DES加密算法。
- 生成MAC1。输入数据为[电子钱包余额(交易前)||交易金额||交易类型标识||终端机编号],秘钥为过程秘钥,使用我们在上一次实现的MAC生成函数gmac4,计算出MAC1用来表明身份。
- IC卡返回[余额||联机交易序列号||秘钥版本号||算法标识||伪随机数||MAC1]。
step3:
- 圈存机对IC卡发挥的MAC1信息进行校验,如果正确就说明IC卡信息合法。
- 计算MAC2。输入信息为[交易金额||交易类型标识||终端机编号||交易日期(主机)||交易时间(主机)],秘钥为过程秘钥,加密算法为依然为gmac4。用来表明自己的身份。
- 发送圈存指令。消息中包含[交易日期||交易时间||MAC2]。
step4:IC使用同样的算法计算MAC2,如果计算结果和终端返回的MAC2一致,就说明终端的身份合法。IC卡就会执行圈存命令。同时返回TAC。其中TAC计算时,输入数据为[电子钱包余额(交易后)||电子钱包联机交易序号(加1前)||交易金额||交易类型标识||终端机编号||交易日期(主机)||交易时间(主机)],密钥为TAC密码最左8个字节与TAC密码最右8个字节异或的结果。
到这里整个圈存过程就结束了。消费以及查询和圈存的实现原理一致,这里就不赘述了。
读代码
前面的分析中,我们已经对本次实验有了大致的了解,接下来就是开始读源码的过程了。不过本次实验中,因为我们只需要对IC卡的系统进行编程实现,而对终端机需要靠人脑完成,所以我们重心就会放在圈存的初始化和圈存的执行上面了。
圈存初始化
还是老样子,我们先读项目给的源码中的Purse
部分,里面有圈存初始化和圈存确认信息的处理函数。
在TA给的源代码中,init_load
和load
方法是已经给好了的,我们先读这两部分的源代码,理解整个设计思路。
首先我们需要修改Purse类,让其process
方法里面增执行圈存初始化,圈存,消费初始化,消费,以及查询的入口。
因