卡片和终端之间的数据传输是通过命令响应的方式进行的,卡片只能被动地接收命令,并且给出响应。所有的命令都是以命令头开始,而该命令被完整地执行后(无论结果对错),必须以包含状态字(SW1 SW2)的响应结束。卡片和终端之间如何具体进行数据传输的,就依靠不同的通讯协议来实现,其中主要有T=0、T=1、T=CL。其中T=0和T=1适用于接触式卡片(7816),而T=CL适用于非接触式卡片(14443)。

  T=0是按照单个字符的方式实现智能卡和终端数据传输的通讯协议,理解协议最好的方式就是尝试自己来设计协议,我们先看看该如何实现字符的传输。

  假设让你来完成数据的正确接收,首先要解决的应该是从哪开始接收的问题。所以我们需要定义一个叫做“起始位”的标志,一旦发现“起始位”就可以确定一个全新的字符传过来了。然后就按照etu的约定逐位接收一个完整字节的数据。在接收的过程中万一有某一位识别错了,比如把“1”识别成了“0”怎么办?所以还要有一个校验位,看看之前接收的数据位是否有错误。如果有错误,则需要反馈一个出错信息,那么发送方会把刚才那个出错的字节再重新发送一次,如果接收再次出错,则要求发送方再重发,最多需要重发多少次由具体的应用规范来确定;如果没有错误,则反馈一个接收正确的状态,然后准备接收下一个字符。

  因为7816的数据传输采用的是串行半双工的方式,而且数据的收发都通过一条I/O信号线来完成,所以在I/O线上传递的数据就有两个方向:可能是从终端到卡(“命令”),也可能是从卡到终端(“响应”)。如果两个连续字符的传输方向一致则称为“同向连续字符”,反之则称为“反向连续字符”。为了保证数据的正确接收,需要规定传递两个连续字符(无论是同向还是反向)的最小和最大时间间隔,最小间隔是为了让接收方有足够的时间准备接收下一个字符,而最大间隔是为了避免接收方无限制地等待,不然就算你已痴痴地等待了千年,那个“良人”还是不来。

  那究竟需要接收多少个字符才算完成了一次完整的数据收发过程呢?怎么来判断发送方发送的动作已经“over”了呢?对于T=0协议而言,卡片和终端必须清楚彼此之间每次数据通讯需要收发多少字节的数据。可是有的时候终端在开始发送命令的那一刻是真不知道,比如在读一条记录时,终端事先可能并不知道这条记录的长度,那该怎么办?其实也没有别的好办法,只能靠试错的方式来投石问路。

  首先,终端发给卡片的命令必须包含5个字节(分别是CLA + INS + P1 + P2 + P3,其中INS表示指令,说明该命令的作用)的命令头,也就是说卡片必须要收到来自终端的5个字节的命令头,才能决定下一步该干什么,然后根据做出的决定给终端一个反馈意见。同样终端在发送完5个字节的命令头后,也需要等待来自卡片的反馈后,再决定下一步该干什么。

  这个反馈的信息一共有三类:

  1)空操作的过程字节NULL(0x60)

  2)响应字节ACK;

  3)状态字的第一个字节SW1。

  NULL字节相当于网络通信中的“心跳包”,就是告诉终端不要进行超时处理,继续等待,而且NULL字节不见得是在卡片接收5个字节的命令头后反馈,通常在卡片需要进行大量数据更新或者复杂的加解密运算时,来不及返回状态字(SW)时先发一个0x60;

  ACK是用来决定后续的数据传输的,不仅能决定传输的方向,还能决定后续传输字节的多少。如果ACK = INS,则传输剩余的全部字节,如果ACK = INS ^ FF,则传输后续的一个字节(早期版本的7816规范中还有ACK = INS ^ 01,以及ACK = INS ^ FE的定义,用来说明编程电压Vpp的,后来的版本中因为Vpp已经不再使用就把这两个值剔除了);

  SW1只能是“0x9X”以及“0x6X”(不能是空操作字节“0x60”),如果卡片返回的是SW1,那么接下来必须紧跟着另一个状态字节SW2,标志着卡片对于该命令处理的结束,如果不断电,卡片在发送完SW2之后会等待下一个命令的到来。另外,因为SW1只能是“0x6X”和“0x9X”,所以INS一定不能取值0x6X和0x9X。至于ISO/IEC JTC1/SC17 的人为什么选择6 9作为SW1的高4位,是不是他们有什么特别的偏好就不得而知了。

  ACK里面为什么会有仅传输后续一个字节的情形,而不是一次传完后续的所有字节?主要是因为如果智能卡芯片没有那么多可以用于临时缓存命令数据的RAM空间的话,就需要接收一个字节先处理一个字节,直到剩余的字节能被一次性地处理了,再反馈一个INS作为过程字节,把剩余的字节全部收进来。

  除了这5个字节的命令头之外,可能还包含终端发送给卡片的命令数据(命令数据长度表示为Lc),也可能还需要卡片返回响应数据(响应数据长度表示为Le)。于是可以把终端和卡片之间的不同命令类型分为4类:

1)只有命令头,没有命令数据也没有响应数据;

2)有命令头没有命令数据,但是有响应数据;

3)有命令头和命令数据,没有响应数据;

4)有命令头、命令数据和响应数据。

  对于情形1,P3=00;

  对于情形2,P3=Le,如果事先不知道Le的具体数值,可以填“00”,卡片会返回“0x6CXY”,其中的“XY”就是Le的正确值,终端用“XY”替换原来作为Le的“00”重新再发一遍命令就能正确获得响应数据了(就是前面提到的试错);

  对于情形3,P3=Lc;

  对于情形4,P3=Lc,卡片会返回“0x61XY”,其中的“XY”用来表示Le,然后终端再利用取响应的指令,获得卡片返回的响应数据。

  上面说的这些命令和响应严格来说是属于TPDU(传输层协议数据单元)的概念,和通常智能卡规范里面说的APDU(应用层协议数据单元)概念是有差别的。因为应用层协议是不关心你的数据如何具体传输的,APDU只定义命令、命令数据、响应数据、返回状态,如何保证这些命令、数据的正确传输则是TPDU该做的事情。新的7816规范对于包含命令数据和响应数据的情形2、3、4还定义了扩展情形2E、3E、4E,用来处理数据长度Lc和Le大于256的场景,但是目前支持该扩展的卡片和终端还不多。

深入理解7816(3)-----关于T=0的更多相关文章

  1. 深入理解7816(3)-----关于T=0 【转】

    本文转载自:http://blog.sina.com.cn/s/blog_4df8400a0102vcyp.html 深入理解7816(3)-----关于T=0 卡片和终端之间的数据传输是通过命令响应 ...

  2. 深入理解7816(2)---关于ATR【转】

    本文转载自:http://blog.sina.com.cn/s/blog_4df8400a0102vcrk.html 深入理解7816(2)---关于ATR 智能卡(此处主要指接触式CPU卡)本身始终 ...

  3. 深入理解7816(1)---- 关于F/D和etu【转】

    本文转载自:http://blog.sina.com.cn/s/blog_4df8400a0101gkss.html 深入理解7816(1)---- 关于F/D和etu 对于刚接触智能卡的工程师来说, ...

  4. 如何理解Apache License, Version 2.0(整理)

    如何理解Apache License, Version 2.0(整理) 问题: 最近看到apache发布了2.0版本的License.而且微软也以此发布了部分源代码.我对OpenSource不是特熟, ...

  5. 深入理解7816(4)---关于T=1

    之前说过的T=0协议,基本上相当于是透明的数据,也就是说从应用的角度看,通过T=0传递的TPDU数据信息大都可以直接转换为对应的APD命令响应数据,“字节”是T=0协议最小的数据传输单元. 对于T=1 ...

  6. 深入理解7816(1)---- 关于F/D和etu

    对于刚接触智能卡的工程师来说,在阅读7816-3规范的时候,常常被其中的一些术语迷惑,读起来会觉得有些别扭.尤其是在看到复位应答中的F和D设置,以及对应的etu的时候,会觉得有些复杂和难以理解. 其实 ...

  7. PHP代码审计理解(二)----齐博CMS7.0文件覆盖

    0x00 前言 因为我是跟着视频操作的,这回真的没理解为什么定位到了这个存在漏洞的文件... /do/fujsarticle.php 因为没有前文,所以这里无法分析这个$FileName为什么可以$_ ...

  8. 深入理解7816(5)-----关于文件DF/EF/MF/FID/AID/SFI

    刚开始接触CPU卡的时候,对于各种文件.应用的定义容易模糊不清,通常不能准确地界定什么是文件?什么是应用?DF和EF的区别真的就像计算机里的目录和文档那样吗?FID.AID.SFI这些概念都在什么时候 ...

  9. 深入理解7816(2)---关于ATR

    智能卡(此处主要指接触式CPU卡)本身始终处于被动的状态,所以终端设备在和智能卡进行数据交互的时候,需要首先给智能卡发指令,智能卡才会对应地给出应答.而智能卡告诉终端的第一句话就是ATR,亦即“复位应 ...

随机推荐

  1. js跨越小结

    javascript跨域有几种情况: 1.基于同一父域的子域之间,如:a.c.com和b.c.com 2.基于不同的父域之间,如:www.a.com和www.b.com 3.端口的不同,如:www.a ...

  2. LINQ 内链接 左链接 右链接

    原文地址:http://blog.sina.com.cn/s/blog_46e9573c01014fx2.html 1.左连接: var LeftJoin = from emp in ListOfEm ...

  3. POJ2104-- K-th Number(主席树静态区间第k大)

    [转载]一篇还算可以的文章,关于可持久化线段树http://finaltheory.info/?p=249 无修改的区间第K大 我们先考虑简化的问题:我们要询问整个区间内的第K大.这样我们对值域建线段 ...

  4. Apache-common项目提供的工具

    ---- MD5加密与生成UUID例子(依赖于commons-io.jar):begin ------------------------------------------------------- ...

  5. nginx本地的测试环境添加SSL

    要在本地添加SSL,首先要做的是防火墙是不是放开了443端口,同时,在nginx安装时是不是支持了ssl模块,这个安装网上很容易找到相关资料 防火墙,个人还是用iptables比较直观 先将selin ...

  6. 使用awrextr.sql导出awr原始数据

    1.AWR原始数据与AWR报告的差别 AWR原始数据: 是oracle数据库mmon进程定期将统计量从内存转储至磁盘,并以结构化的形式存入若干张表组成自己主动工作负荷存储仓库(AutomaticWor ...

  7. 服务 远程服务 AIDL 进程间通讯 IPC 深化

    示例 aidl接口文件 package com.bqt.aidlservice.aidl; parcelable Person;  package com.bqt.aidlservice.aidl; ...

  8. js字符串转json

    1,eval方式解析,这是最早的解析方式了.如下: 代码如下: function strToJson(str){ var json = eval('(' + str + ')'); return js ...

  9. hdu 2101

    #include <stdio.h> int main() { int a,b; while(scanf("%d%d",&a,&b)!=EOF) { i ...

  10. C复习手记(Day4)

    1.C错误处理 errno.perror() 和sterror() perror() 函数显示您传给它的字符串,后跟一个冒号.一个空格和当前 errno 值的文本表示形式. strerror() 函数 ...