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成員返回給應用。




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