卷 6
这卷谈到了 SP 。
直奔编程接口。
SCARD
要满足 PCSC2 ,这是必须实现的接口 [4] 。
定义了支持 ICC 应用接口的方法。
通常,作为 ICCSPs 或 CSP 的一部分来实现。
属性
HANDLE hContext
方法
SCARD()
~SCARD()
RESPONSECODE CreateFileAcces(OUT FileAccess aFileAccess)
RESPONSECODE CreateCHVerification(OUT CHVerification aCHVerification)
RESPONSECODE CreateCardAuth(OUT CardAuth aCardAuth)
RESPONSECODE CreateCryptProv(OUT CryptProv aCryptProv)
先说这四个接口,分别用来产生 FileAccess , CHVerification , CardAuth , CryptProv 实例。
往下看,后面会说明这4个实例的作用。
RESPONSECODE AttachByHanlde(IN HANDLE hCard)
这里的 hCard 是 SCARDCOMM.hCard 。是从 Resource Manager 获得的已经存在
的通讯上下文。这样应用可以调用这个函数去定位感兴趣的 ICC 并在调用相关
SP 之前,打开连接。
应用要注意,使用 SCARD::Detach 释放这个通讯上下文。
RESPONSECODE AttachByIFD(IN STR ReaderName,IN DWORD Flags)
这个和上面的不一样,是自己根据特定读卡器的 friendly name ReaderName 创建
通讯上下文来和 ICC 通讯。
RESPONSECODE Detach()
释放通讯上下文。
RESPONSECODE Reconnect(IN DWORD Flags)
重新打开和已经和卡建立的连接。注意通讯上下文必须已经建立。
实际上调用了 SCARDCOMM::Reconnect()
这个 SCARDCOMM 是卷 5 的内容。
RESPONSECODE Lock();
RESPONSECODE Unlock();
独占方式访问 SCARD 提供的方法。
Lock ,加锁。 Unlock ,释放锁。
回头看看 SCARD ,应用了工厂方法。
大师说了,创建型的模式之一就是工厂方法。还是首推的方法。
根据实际的变动,可以重构到其它的创建方法。 FileAccess , CHVerification , CardAuth , CryptProv 都是产品或抽象产品。
同样的,制造型的企业需要工厂,需要有一定的方法制造产品。
不同的,制造型企业存在 exploitation 。而这在软件架构中也可见一斑。
从现实中抽象出模型,也从模型中进一步理解现实。
接着谈可选接口。
Class FILEACCESS
Class CHVERIFICATION
Class CARDAUTH
Class CRYPTPROV
Class CRYPTHASH
Class CRYPTKEY
这些都是工厂的产品了。
一个一个来。
FILEACCESS
class FILEACCESS
原文中有 “This interface exposes file system entities in a manner very familiar to application developers in the PC environment. It provides mechanisms for locating specific files and performing common operations such as selecting, reading, writing, creating and deleting. It encapsulates and masks much of the low level detail involved in performing these operations at the card level. ”
目的是为了模拟 PC 上的文件系统和文件操作方法。
体现了架构理论中的 “ 接口最小必要且易用 ” 。
看看
属性
private SCARD scard
private STR CurrentPath
方法
FILEACCESS(IN SCARD scard)
~FILEACCESS()
RESPONSECODE ChangeDir(IN REFTYPE Ref,IN STR PathSpec)
RESPONSECODE GetCurrentDir(OUT STR PathSpec // absolute path
)
RESPONSECODE Directory (IN FILETYPE Type, // type of files
OUT FILESPEC[] FileList, // list of FilesSpecs
OUT WORD Length // number of FileList entries)
RESPONSECODE GetProperties(
IN REFTYPE Ref, // type of references
IN STR PathSpec, // relative or an absolute path
IN OUT TLV[] Properties, // list of TLV_TABLE structures
IN OUT WORD Length, // number entries in Properties list
IN DWORD Flags
)
RESPONSECODE SetProperties(
IN REFTYPE Ref, // type of the references
IN STR PathSpec, // relative or absolute path
IN TLV[] Properties, // list of TLV_TABLE structures
IN WORD Length, // number of entries in Properties list
IN DWORD Flags
)
RESPONSECODE GetFileCapabilities(
IN HANDLE hFile, // handle to a file
IN OUT TLV[] Properties, // list of TLV_TABLE structures
IN OUT WORD Length, // number entries in Properties list
IN DWORD Flags
)
RESPONSECODE Open(
IN REFTYPE Ref, // type of the references
IN STR PathSpec, // relative or absolute path
OUT HANDLE hFile // handle to a file
)
RESPONSECODE Close (
IN HANDLE hFile // handle to a file
)
RESPONSECODE Seek(
IN HANDLE hFile, // handle to a file
IN OUT DWORD Offset, // relative offset value
IN DWORD SeekType // starting location
)
RESPONSECODE Write(
IN HANDLE hFile, // handle to a file
IN DWORD Length, // length of the data object to write
IN BYTE[] Buffer, // data object to be written
IN DWORD Flags
)
RESPONSECODE Read(
IN HANDLE hFile, // handle to a file
IN OUT DWORD Length, // length of the data object
OUT BYTE[] Buffer, // data read
IN DWORD Flags
)
RESPONSECODE Create(
IN REFTYPE Ref, // type of reference in PathSpec
IN STR PathSpec, // path specification for new file
IN OUT TLV[] TLVs, // list of TLV_TABLE structures,
// includes file properties
IN OUT WORD Length, // number entries in TLVs list
IN WORD Flags,
IN VOID DataBuffer // data to be pre-allocated
)
RESPONSECODE Delete (
IN REFTYPE Ref,
IN STR PathSpec, // relative path
IN WORD Flags
)
RESPONSECODE Invalidate(
IN REFTYPE Ref, // type of references
IN STR PathSpec, // relative path
IN WORD Flag
)
RESPONSECODE Rehabilitate(
IN REFTYPE Ref, // type of references
IN STR PathSpec, // relative path
IN WORD Flag
)
问:列这么多方法做什么,占用这么多版面。有掺水的嫌疑。
答案是,这里作为首次介绍 SP 的可选接口之一,就列上了。只是表明了
这些方法必要且简明, APPLICATION 很高兴。
能让 APPLICATION 高兴起来的设计就是好设计。
能让皇帝高兴起来的大臣就是好大臣。
后面还有更多的可选接口,就不列了。可以直接参考各家 SP 提供的文档。
这里主要的目的是,这个接口的设计很友好,方便 APPLICATION 使用。
因为现今的世界不再是软件艺术品的世界了。 APPLICATION 必须使用阿斗
式的调用。如果 APPLICATION 实现相当复杂,要了解很多和 APPLICATION
相关的下层实现,这样的 APPLICATION 实现还是一份好的实现吗?
APPLICATION 应该在下层,下下层等等的辅佐下,迅速实现自己的目标。
注意这是 APPLICATION 只是被辅佐,而不是事必躬亲。累死辅佐大臣,
自己落个轻松还能拥有可以载入史册的成就。
或许有人反对,认为我列了一堆 api ,也不举例供参考 ( 抄袭 ) 。我只能说这里
授人予鱼,不如授人予渔。提了接口,说了接口的设计思路和相关模式。剩
下的就直接看相关范例,实现你的 APPLICATION 了。
看到设计,要知其然,知其所以然。
侯捷在谈到 Application Framework 中说了,带有艺术气息的软件创作行为将
在 Application Framework 出现后逐渐沦为工匠艺术 [5] 。
Application Framework 就是一种设计,一种架构。
PCSC 就是一种设计,一种架构。
按照侯捷的观点,可以猜到,如果仅仅在设计之上,使用 api 编写 APPLICATION ,是没有
什么可以沾沾自喜的。需要理解框架,架构和背后的设计思想。
CHVRIFICATION
Class CHVERIFICATION
APPLICATION 可以通过调用该类的方法强制 CHV 验证或者允许用户改变 CHV
code
属性
private SCARD scard
方法
参考卷 6 吧 .
至于 CARDAUTH , CRYPTPROV , CRYPTHASH,CRYPTKEY
不再罗列属性和方法了。
CARDAUTH
这个类实现了认证服务的接口。包括常见的 GetChallenge , Internal
Authenticate , External Authenticate ,User Authenticate
其中 User Authenticate 是卡向远端实体认证,典型情况下采用对称密钥。
CRYPTPROV
所有的 CSPs 必须实现这个类接口。提供加解密服务和创建 CRYPTKEY 和
CRYPTHASH 实体。 CRYPTPROV 本身作为 SCARD 的产品,也作为工厂
方法,生产 CRYPTKEY 和 CRYPTHASH 产品。
其中包括创建 Hash ,派生密钥,随机产生密钥,取随机数,导出参数到 Blob ,
获取签名公钥,密钥交换公钥。从 Blob 导入密钥,设置 Blob 中的参数 。
CRYPTHASH
Hash 和数字签名全靠它了。
CRYPTKEY
这位也不得了。得靠它解密,加密,导出密钥到 Blob , 获取 / 设置 Blob 中的参数。
卷6结束。
提醒下,很多情况下,不能得到 SP 。所以还得依靠 ResourceManager ,
简单的说,如果有 SP 辅助 APPLICATION , APPLICATION 可以过上轻松自在的
生活。如果没有,则 APPLICATION 的生活也没有那么好过。
APPLICATION 直接面对 ResourceManger 的一堆方法,还要理解特定的卡结构和
卡上的应用。