CSP-PKCS#11-JCE互通设计

一、目标:

    CA通过CSP->PKCS#11->EToken写密钥对及证书。EToken拿到Java应用环境,比如Android,Java通过JCE->PKCS#11->EToken,能正常使用密钥对及证书。反过来也是


二、分析:

PKCS#11:
对象(CKA_CLASS):CKO_CERTIFICATE;CKO_PUBLIC_KEY;CKO_PRIVATE_KEY
属性:CKA_LABEL;CKA_ID(证书公钥密钥标识,用于关联公钥、私钥、证书对象);CKA_ENCRYPT;CKA_VERIFY;CKA_DECRYPT;CKA_SIGN

CSP:
KeyContainer名字
KeySpec :AT_KEYEXCHANGE或AT_SIGNATURE

JCE:
需要实现的接口:KeyStoreSpi;CipherSpi;SignatureSpi
KeyStoreSpi保存密钥对及证书的是KeyEntry,每个KeyEntry有个名字Alias

存在的问题:
CSP一个容器存2对密钥对2个证书,容器名唯一;JCE一个KeyEntry1对密钥对和1个证书,Alias唯一;PKCS#11没有容器的概念,只有对象的概念,公私钥及证书的关联交给应用去处理,以CKA_LABEL和CKA_ID作为标识


三、设计

CSP->PKCS#11:
KeyContainer名字 == CKA_LABEL 或 CKA_ID的Hex字符串,由一个标志idFlag来标识是用CKA_LABEL还是CKA_ID的Hex字符串,值为1时为前者,2时为后者。
AT_KEYEXCHANGE -> CKO_PUBLIC_KEY:CKA_ENCRYPT;CKO_PRIVATE_KEY:CKA_DECRYPT
AT_SIGNATURE -> CKO_PUBLIC_KEY:CKA_ENCRYPT,CKA_VERIFY;CKO_PRIVATE_KEY:CKA_DECRYPT,CKA_SIGN

1 CSP产生密钥对操作CPGenKey()
P11调用:C_GenerateKeyPair()
模板的属性:CKA_LABEL为KeyContainer名字,如果KeySpec为AT_SIGNATURE,则公钥模板CKA_ENCRYPT和CKA_VERIFY均为true,私钥模板CKA_DECRYPT和CKA_SIGN均为true。如果KeySpec为AT_KEYEXCHANGE,则公钥模板CKA_ENCRYPT为true,私钥模板CKA_DECRYPT为true。

2 CSP写入密钥对操作CPImportKey()
P11调用:C_CreateObject()
模板的属性同上

3 CSP写入证书操作CPSetKeyParam(KP_CERTIFICATE)
P11调用:C_CreateObject()
证书的公钥标识作为CKA_ID,并重新设置对应的密钥对的CKA_ID,使之关联起来

4 CSP枚举密钥容器操作CPGetProvParam(PP_ENUMCONTAINERS)
P11调用:C_GetAttributeValue()
CKA_LABEL -> KeyContainer名字,若不存在CKA_LABEL属性,则CKA_ID的Hex字符串作为KeyContainer名字。idFlag为2
如果该CKO_PUBLIC_KEY对象的CKA_VERIFY为true,则KeySpec为AT_SIGNATURE,否则为AT_KEYEXCHANGE


JCE->PKCS#11
Alias == CKA_LABEL 或 CKA_ID的Hex字符串,由一个标志idFlag来标识是用CKA_LABEL还是CKA_ID的Hex字符串,值为1时为前者,2时为后者

1 JCE的写入密钥对及证书操作engineSetKeyEntry()
P11调用:C_CreateObject()
模板的属性:CKA_LABEL为Alias,公钥模板CKA_ENCRYPT和CKA_VERIFY均为true,私钥模板CKA_DECRYPT和CKA_SIGN均为true,证书的公钥标识作为CKA_ID。
idFlag为1。

2 JCE读密钥对及证书engineAliases()
P11调用:C_GetAttributeValue()
若公钥属性CKA_VERIFY为true,则CKA_LABEL作为Alias,否则CKA_LABEL->Alias+"-1"。
idFlag为1。

若不存在CKA_LABEL属性,则CKA_ID的Hex字符串作为Alias。idFlag为2


PKCS#11作一些特别的限制
设置公钥/私钥/证书对象时,相同类型的对象,CKA_ID不能相同;相同的密钥用法下,CKA_LABEL不能相同。
至少支持以下对象:CKO_CERTIFICATE;CKO_PUBLIC_KEY;CKO_PRIVATE_KEY。
至少支持以下机制:CKM_RSA_PKCS_KEY_PAIR_GEN;CKM_RSA_X_509
至少支持以下属性:
CKA_CLASS;CKA_LABEL;CKA_ID
CKO_CERTIFICATE:CKA_VALUE
CKO_PUBLIC_KEY:CKA_MODULUS;CKA_MODULUS_BITS;CKA_PUBLIC_EXPONENT;CKA_ENCRYPT;CKA_VERIFY
CKO_PRIVATE_KEY:CKA_MODULUS;CKA_PUBLIC_EXPONENT;CKA_PRIVATE_EXPONENT;CKA_DECRYPT;CKA_SIGN
至少支持以下函数:
获取函数列表:C_GetFunctionList
初始化和释放:C_Initialize,C_Finalize
槽和令牌管理:C_GetSlotList,C_GetTokenInfo,C_InitPIN,C_SetPIN,C_GetMechanismList,C_GetMechanismInfo
会话管理:C_OpenSession,C_Login,C_Logout,C_CloseSession
对象管理:C_CreateObject,C_DestroyObject,C_FindObjectsInit,C_FindObjects,C_FindObjectsFinal,C_GetAttributeValue,C_SetAttributeValue
密钥管理:C_GenerateKeyPair
签名:C_SignInit,C_Sign
解密:C_DecryptInit,C_Decrypt




一些特别问题

PIN码重试次数的获取

P11的C_Login()函数只能返回登录是否成功,密码是否正确,并不能告诉你还可以尝试多少次,而IC卡的外部认证指令返回的状态信息是可以知道PIN重试次数的。在此建议通过C_GetSessionInfo()来做,在C_Login()失败后,把IC卡的返回状态通过CK_SESSION_INFO结构的ulDeviceError成员返回给应用。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章