减小字体
增大字体
通用问题 Q:如何在IC卡中保存和读取汉字? 逻辑加密卡 SLE 4442/4428卡 Q:什么是PSC?SLE 4442卡的初始PSC是什么? Q:为什么SLE 4442卡更改密码后,用原来的密码验证仍然能通过? Q :SLE 4442卡允许的密码尝试次数是3次。为什么密码错误计数器的初始值是07? Q:我在编写SLE 4428卡应用程序中调试写卡操作,并没有更改密码。为什么用原来的密码验证不能通过了? Q:SLE 4442/4428卡的写保护是怎么一回事? AT88SC1608/153卡 Q: AT88SC1608卡如何设置访问权限? Q: AT88SC1608卡如何设置访问权限?Q: ATMEL的AT88SC1608或153卡的安全认证怎么一回事? Q: 对于ATMEL的AT88SC1608或153卡,为什么无论我输入主口令还是其它口令,都不能正确完成安全认证? Q: 在程序中用CRR9601或CRR0202读卡器第一次读AT88SC1608的用户区第0区时,返回的所有值都是06。选择其他页后再返回第0页,再读就一切正常了。为什么? Q: 我并没有更改用户区的访问权限字节,仍然是FF,应该表示自由读写。为什么我通过口令校验之前不能写用户区? Q: 我在程序中向AT88SC1608/153写入数据时,并没有按照我指定的长度写入,只写了16或8字节。为什么?
CPU卡(社保卡) Q:初始化卡的过程中,校验传输密钥时总是返回错误‘6988’—MAC无效。是何原因? Q:如何在卡中安装密钥? Q:执行社保卡的DEBIT FOR PURCHASE 命令时,返回错误‘9403’— 不支持的索引号。是什么原因? Q:如何在IC卡中存储和读取汉字? A: 在卡中存储汉字,实际上是存储了汉字的编码。如果你是在自己开发的显示系统(例如液晶显示)中使用汉字,可以自己编码,每一个编码映射到一个点阵字库入口。 如果是在PC机操作系统下显示汉字,应当在卡中保存汉字内码(一般就是Unicode的ASCII码)。因为卡中空间有限,当中西文混合保存时,并不全用Unicode码(每字符占用2字节),而是用ANSI码保存西文字符(占用1字节)。 保存时求每个字符的ASCII码,得到的结果是中文字符2字节,西文字符1字节。 读出时,逐字节检查ASCII码值。如果大于127,就是汉字(或其他东方文字)的首字节,再取1字节,一同转换成字符;如果小于等于127,就是西文字符,直接转换即可。 Q:什么是PSC?SLE 4442卡的初始PSC是什么? A: PSC叫做“可改写安全编码”(programmable security code),就是通常所说的“密码”。 SLE 4442/4428卡具有密码验证逻辑。当未通过密钥验证之前,只能读卡中信息;只有通过了密码验证,才能改写。 制造商在提供SLE 4442/4428卡时,会将原始的PSC(也叫做传输密码)通知用户。但大批量供货的情况下,EEPROM往往会保持芯片从生产线产出的初始状态,也就是所有字节都是“FF”,当然PSC也会如此。 不过,为了慎重起见,最好还是向供应商问清楚。 Q:为什么SLE 4442卡更改密码后,用原来的密码验证仍然能通过? A: SLE 4442卡在通过密码验证后,这一“安全状态”将一直保持,直至卡下电。因此,只要通过了密码验证,并且没有下电并重新上电,无论再用什么密码验证,将始终返回“密码验证通过”。许多没有经验的开发者,常常在这种情况下不断更改密码,不断验证,在疑惑中忘记了最后更改的密码,以至于下电后无法通过密码验证,导致多次错误永久性锁卡。 因此,在更改密码后一是要记住所更改的密码(给用户的界面上要提供二次确认),二是要用动态函数库提供的设备命令函数bm_power_off和bm_power_on使卡下电并重新上电。此后可以尝试验证新的密码。 如果在调试你的程序时,已经忘记了最后更改的密码,不要慌乱,切记不要拔卡,也不要使卡下电。退出你的程序,用我们提供的工具程序“读主密码错误计数”。在通过密码验证的情况下,读出内容的后3字节就是你的密码。此时,也可以再次更改并记住密码。 SLE 4428卡也有类似情况。不过在工具程序中“读主密码错误计数”不能显示密码,你可以在“页读入”方式下察看第3页内容,最后两字节就是密码。在通过密码验证状态下,读出的是真实值;否则是“0000”。 Q:SLE 4442卡允许的密码尝试次数是3次。为什么密码错误计数器的初始值是07? A: SLE 4442卡如同许多其他卡一样,错误计数器是用Bit(位)来计数的。初始状态下,计数器用来计数的位是全“1”。 SLE 4442卡允许尝试3次,所以它的计数器字节内容是“00000111”(0x07)。 当验证密码时,首先须将错误计数器的一个“1”写为“0”(由读卡器来完成)。如果验证通过,卡的内部逻辑允许将错误计数器所有的位擦除为“1”,恢复到原始状态(擦除操作也是读卡器完成的)。如果没有通过,被改写的“0”就会保留,直至所有位全部变为“0”(卡被锁死)。 在我们读卡器的读写方式中,是按低位在前处理的。因此,当验证没有通过时,计数器从07递减,依次是06,04,00。 类似地,SLE 4428卡允许尝试8次,计数器的递减顺序是FF,FE,FC,F8,F0,E0,C0,80,00。 Q:我在编写SLE 4428卡应用程序中调试写卡操作,并没有更改密码。为什么用原来的密码验证不能通过了? A: SLE 4428卡的密码错误计数器以及密码寄存器与数据存储器使用统一地址,字节1021是密码错误计数器,字节1022、1023保存的就是两字节密码。 在写数据区时,如果不慎误写了这三个字节,就可能造成错误! 密码错误计数器字节是随时可写的,不需要通过密码验证(只能将剩余尝试次数减少)。如果误将计数器剩余次数改小,甚至减少至0,就会丧失通过密码验证的机会。 如果无意中误写了密码,而又无法确定所写的内容,也会造成同样的麻烦。 所以,在写SLE 4428卡时,一定要十分谨慎。
Q:SLE 4442/4428卡的写保护是怎么一回事? A: SLE 4442卡中有一个4字节(32 Bit)的“保护存储器”。它的每一个Bit(位),对应着卡中数据存储器最前面32个字节中的一个字节。当把保护存储器的某一位由原始的“1”写成“0”后,它所对应的数据字节就不能再改写了。 厂商提供的卡,已经将这32字节中的某些字节(ATR信息、厂商代码、用户代码)写保护了。卡应用的开发者,可以继续将剩余的字节根据需要写保护。 保护存储器是PROM存储器,只能“写”(“1”→“0”),不能“擦除”(“0”→“1”)。也就是说,一旦写保护,就是永久性的,不可挽回。因此在调试样卡时请慎重。 在工具程序中,读写保护存储器时是按16进值方式显示的,请注意与2进值的转换。 SLE 4428卡有128字节(1024 Bit)保护存储器,所以可以对整个数据区写保护。
Q:AT88SC1608卡如何设置访问条件? AT88SC1608卡有8个256字节的用户分区和1个设置分区。 设置分区中可以存放8组口令(密码)。每组有一个读口令、一个写写口令。 但是,此卡并不是只能一个分区对应一组口令,它的分区访问条件是可以自定义的。如果将多个分区指定为一组口令,就相当于将其合并为一个大分区,只需用一组口令就可以控制这些分区所有空间的读写。 卡的设置区有一个8字节的访问控制块,每字节对应一个分区的访问权限设置。通过对这些字节的设置,可以定义每一个用户区的访问控制条件: 注意,访问控制块的原始状态是全“1”,因此,不仅都指向口令组7,而且所有访问都是开放的。 要读写访问控制块所在的设置区,必须首先通过口令组7的写口令(卡的主口令)。
Q: ATMEL的AT88SC1608或153卡的安全认证怎么一回事? A: AT88SC1608或153卡在一般逻辑加密卡的口令验证安全机制的基础上,增加了安全认证(Authentication)。 这两种卡的通过Initialize Authentication和Verify Authentication命令,实现卡对终端以及终端对卡的相互认证。下面,以大家所熟悉的CPU卡认证的说法,做一个简单介绍: 在卡的设置区Gc块中,可以在发卡时写入一个密钥。这个块类似CPU卡的密钥文件,是不可读的。 与CPU卡认证不同的是,随机数不是由卡生成的,而是在终端生成。终端必须在Initialize Authentication命令中,向卡发送一个8字节的随机数。 终端使用ATMEL指定的加密算法,用Gc密钥加密随机数,得到两个认证数据。 终端在Verify Authentication命令中,把第一个认证数据发送给卡,供卡进行“外部认证”。 如果上一步认证通过,卡还会把它计算的第二个认证数据回送给终端,供终端进行“内部认证”。 卡中有一个认证错误计数器(AAC)。每错误一次,计数器加1,直至计数器满(最多8次)而锁死认证功能;如果通过认证,计数器清零。 执行完认证命令后,终端是通过专门的读AAC命令来确认是否通过认证的。 认证通过后,其安全状态有效,直至卡下电。 和CPU卡的通常做法一样,AT88SC153/1608卡也支持一卡一密。密钥分散的方法由发卡方自定义。由于设置区的卡号(Nc)是可读的,密钥往往通过卡号来分散。需要注意的是,卡号是7字节(块的首字节是AAC)。 我公司的读卡器动态连接函数库中,已经将此两种卡的安全认证过程打包为一个函数,只需调用即可。
Q: 对于ATMEL的AT88SC1608或153卡,为什么无论我输入主口令还是其它口令,都不能正确完成安全认证? A: 首先需要明确的是,安全认证过程本身与口令无关。它的过程是: 1. 主机读取卡号(Nc)。并使用预定的加密算法从卡号换算出安全认证算法所需的加密种子(Gc)。 为了实现安全认证,每张卡都必须事先存储Nc-Gc对。也就是说,卡片发行过程中,当写入卡号Nc时,就必须用发行商预定的加密算法算出Gc,并同时写入卡中。注意,Gc是无法从外部读取的,在安全认证时必须所用相同的算法从Nc求出。 2. 主机取得一个随机数(Q0),并通过认证初始化命令将其发送给卡。 3. 主机用加密种子Gc、Q0,通过ATMEL指定的认证算法求出认证数据Q1、Q2。并用认证命令将Q1发送给卡。 4. 卡将Q1与其使用相同算法求出的结果进行对比,如果相符,它将发回认证成功信息,并把它计算出的Q2发送给主机。 5. 主机将它计算的结果Q2与卡送回的结果进行比对,如果相符,则验证成功。
我们提供的动态连接库Bm32.dll中,已经将整个认证过程打包在bm_authenticate函数中,调用它即可。在这个函数中,已经嵌入了ATMEL的认证加密算法。同时,我们定义了一种从Nc求Gc的算法。 用演示程序不能成功地实现安全认证的原因,往往是没有在卡中预写正确的Nc-Gc对。解决的方法是,调用演示程序附带的Bm32.dll文件中的Get_Gc函数,以我们定义的加密算法求出Nc-Gc对,在将其写入卡设置区的Nc域(1608的地址$21,153的地址$19)和Gc域(1608的地址$30,153的地址$28)。Get_Gc函数的调用方法:
__int16 __stdcall get_gc(UC *nc,UC *gc) 说 明: 函数利用内部加密算法从AT88SC1608/153卡号(Nc)求得加密种子(Gc) 参 数: nc:卡号(Nc), 表示8字节数据的16进制字符串, 长度16个字符。 gc:返回的Gc , 表示8字节数据的16进制字符串, 长度16个字符。
当然,用户完全可以在自己的应用程序中自定义从Nc求得Gc的算法。此时,用户可以通过Bm32.dll文件中bm_authenticate函数的custom_Gc参数使用自定义的Gc。方法是,应用程序先读取Nc,用自定义的算法算出Gc,并转换成表示其16进制值的16字节字符串;将bm_authenticate函数的custom_Gc参数设置为1,将Gc字符串代入函数的第4个参数。该函数的用法如下:
__int16 __stdcall bm_authenticate(HANDLE dev_id,UC cardno,UC custom_Gc,UC *Gc) 说 明: AT88SC1608/153接触卡的安全认证 参 数: dev_id:设备句柄 cardtype:卡型, 8为1608卡, 9为153卡 custom_Gc:是否提供自定义Gc, 0 = 使用Bm32函数根据卡号计算的缺省Gc 1 = 在函数中提供自定义的Gc Gc:自定义的Gc (custom_Gc=0时忽略) 返回值: 返回 0:正确; 非0:错误 TOP
Q:在程序中用CRR9601或CRR0202读卡器第一次读AT88SC1608的用户区第0区时,返回的所有值都是06。选择其他页后再返回第0页,再读就一切正常了。为什么? A: 在首次读卡之前,必须用 bm_page() 函数选页。这实际上是设置读写的地址高位。因为AT88SC1608卡在上电后,并不是立即允许对用户区访问的,必须先向卡发送Set User Zone Address命令,说明分区地址。否则,卡将返回表示禁止读的06代码。 TOP
Q:我并没有更改用户区的访问权限字节,仍然是FF,应该表示自由读写。为什么我通过口令校验之前不能写用户区? A: 实际上,在个人化熔丝没有熔断之前,用户区的写是受运输密码(写口令7)保护的。只有熔断熔丝之后,全开放的 AR 设置才会起作用。这一点,在AT88SC1608/153的Datasheet中并没有说明。 TOP
Q:我在程序中向AT88SC1608/153写入数据时,并没有按照我指定的长度写入,只写了16或8字节。为什么? A: AT88SC1608和AT88SC153分别采用了16或8字节的“页写”方式。它从主机接收数据时,如果达到16或8字节时,将自动停止接收并进入存储器写循环。所以,它在一个写命令中,最多只能写16或8字节。当您需要写入更多数据时,应循环调用写命令。 TOP
Q:初始化卡的过程中,校验传输密钥时总是返回错误‘6988’—MAC无效。是何原因? A: 常见的原因是 1. 所用的传输密钥不正确。新卡的传输密钥可能是16 字节‘FF’或‘00’。 已经更改过传输密钥的旧卡则难以知晓。 2. MAC 算法错误。可以利用我们在社保卡演示程序中附送的小程序SecuMess.exe进行验算。特别要注意数据加密算法是否正确,否则更改后的传输密钥不可预知。 TOP
Q:如何在卡中安装密钥? A: 安装密钥使用INSTALL KEY 命令。命令报文数据中传送加密的密钥数据和MAC。 加密密钥数据和计算MAC所用的密钥,是过程密钥。而生成这些过程密钥所用的密钥是逐级控制的。 首先,安装主目录文件(MF)下的第一个密钥。这个密钥叫做主控密钥。用传输密钥生成过程密钥,用过程密钥来计算被安装密钥的密文和MAC。我们称这个过程作,在传输密钥控制下安装该主密钥。 然后,在主密钥控制下,安装主目录文件下的其他密钥。 子目录下的密钥安装,类似此种关系。在上一级目录的主控密钥控制下,安装下一级子目录的主控密钥;然后用同级主控密钥控制,安装其他密钥。 在社保卡实际发行中,计算密钥密文和MAC都是通过密钥母卡完成的。 TOP
Q:执行社保卡的DEBIT FOR PURCHASE 命令时,返回错误‘9403’— 不支持的索引号。是什么原因? A: 在医疗保险交易过程中,要用到两个密钥DPK 和DTK。 这就需要在创建医保专用ED 文件时,在命令中数据域中指定这两个密钥的标识,并与安装密钥时定义的标识相同。同时,要求这两个密钥具有相同的索引号。 为使DLK 与DPK 索引号不同,安装密钥时要安装两次DTK。其标识及值不变,但索引号分别与DLK、DPK相同。 还须在INITIALIZE FOR PURCHASE命令报文数据域的第1 个字节中,引用此索引号。 否则当执行DEBIT FOR PURCHASE命令时,COS程序找不到DTK,就会返回错误‘9403’(不支持的索引号)。
|