1. 程式人生 > 其它 >實驗一.加密API研究

實驗一.加密API研究

實驗一.加密API研究

20191318 王澤文

  《密碼工程》


查詢各種標準的原始文件,研究學習(至少包含Crypto API,PKCS#11,GMT 0016-2012,GMT 0018-2012)

   Crypto API:

作為一部分 Microsoft Windows 提供的應用程式程式設計介面 (API),CryptoAPI 提供了一組函式。這些函式允許應用程式在對使用者的敏感私鑰資料提供保護時,以靈活的方式對資料進行加密或數字簽名。實際的加密操作是由稱為加密服務提供程式 (CSP) 的獨立模組執行。

CryptoAPI是一組函式,為了完成數學計算,必須具有密碼服務提供者模組(CSP)。Microsoft通過捆綁RSA Base Provider在作業系統級提供一個CSP,使用RSA公司的公鑰加密演算法,更多的CSP可以根據需要增加到應用中。事實上,CSP有可能與特殊硬體裝置(如智慧卡)一起來進行資料加密。CryptoAPI介面允許簡單的函式呼叫來加密資料,交換公鑰,雜湊一個訊息來建立摘要以及生成數字簽名。它還提供高階的管理操作,如從一組可能的CSP中使用一個CSP。此外,CryptoAPI還為許多高階安全性服務提供了基礎,包括用於電子商務的SET,用於加密客戶機/伺服器訊息的PCT,用於在各個平臺之間來回傳遞機密資料和金鑰的PFX,程式碼簽名等等。

   PKCS#11:

在密碼系統中,PKCS#11是公鑰加密標準(PKCS, Public-Key Cryptography Standards)中的一份子 ,由RSA實驗室(RSA Laboratories)釋出[1],它為加密令牌定義了一組平臺無關的API ,如硬體安全模組和智慧卡。

PKCS#11標準定義了與密碼令牌(如硬體安全模組(HSM)和智慧卡)的獨立於平臺的API,並將API本身命名為“Cryptoki”(來自“加密令牌介面”,發音為“crypto-key” - 但是“PKCS#11”通常用於指代API以及定義它的標準)。 API定義了最常用的加密對像型別(RSA金鑰,X.509證書,DES / 三重DES金鑰等)以及使用,建立/生成,修改和刪除這些物件所需的所有功能。

   GMT 0016-2012:

本標準規定了基於PKI密碼體制的智慧密碼鑰匙密碼應用介面,描述了密碼應用介面的函式、資料型別、引數的定義和裝置的安全要求。
本標準適用於智慧密碼鑰匙產品的研製、使用和檢測。

   GMT 0018-2012:

本標準規定了公鑰密碼基礎設施應用技術體系下服務類密碼裝置的應用介面標準,
本標準適用於服務類密碼裝置的研製使用,以及基於該類密碼裝置的應用開發,也可用於指導該類密碼裝置的檢測


總結這些API在程式設計中的使用方式

  1. Crypto API

使用CryptoAPI編寫一個檔案保護程式,具有如下功能:

  • 給定明文檔案,生成加密檔案,同時產生檔案的數字簽名檔案;
  • 給定密文檔案,解密出明文檔案,並驗證簽名的正確性。

在不安全的網路上進行安全的資料傳輸涉及三個方面的要求:資訊隱藏,身份鑑別和完整性檢驗。CryptoAPI除了提供上述三個功能外還提供標準的ASN.1編碼、解碼,資訊解密,數字證書和證書儲存區的管理,證書信任列表、吊銷列表和證書有效性檢查等功能。

  資訊隱藏

資訊隱藏的意義是保障資訊內容只能被特定的人獲取。資訊隱藏通常是使用某種形式的密碼學方式。資料加密演算法能保障資訊的安區隱藏和傳輸。資料加密演算法是將明文資料經過一定的變換使其看上去是一組毫無意義的資料。在沒有加密金鑰的情況下,對於好的加密演算法想從密文獲取明文資訊是不可能的。被加密的資料可以是任意的ASCII編碼文字檔案,資料庫檔案,和任意需要進行安全傳輸的資料。這裡,“資訊”是指任意的一段資料,“明文”是指任意一段沒有被加密的資料,“密文”是指任意一段加密的資料。被加密的資料可以在不安全的通道上進行傳輸而不傷害其安全性。之後,密文可以被還原成明文.

資料加密和解密的概念是:對資料加密的時候需要一個加密金鑰,相當於門上的一把鑰匙。解密的時候,需要使用一個解密金鑰來解開資料。加密金鑰、解密金鑰可以相同也可以不相同。
加密金鑰必須小心儲存,給其它使用者的時候也必須通過安全的通道傳遞。對解密金鑰的訪問許可權必須小心控制,因為擁有解密金鑰意味著可以解開所有相應加密金鑰加密的資訊。

  身份鑑別

安全通訊的前提是通訊的雙方知道對方的身份。身份鑑別的任務就是鑑別一個使用者或者實體的真實身份。標識使用者身份的文件通常被稱為信任狀或者憑證。

身份鑑別有時候也用來判定接受的資料就是被髮送的資料。如果A向B傳送了一段資料,B需要鑑別這段資料就是A發出去的,而不是其它冒充A發出去的。為了滿足這類驗證的需求,CryptoAPI提供數字簽名和校驗函式,用來對資訊進行鑑別。

因為在計算機網網路上傳輸的資料與使用者之間並沒有物理連線,因此對資料進行鑑別的憑證也必須能夠在網路上進行傳輸。這種憑證必須由受信任的憑證發行機構發行。

數字證書就是平常說的證書就是這種憑證,是計算機在網路上進行身份驗證的有效憑證。

數字證書是由一個被稱為證書機構的信任組織或實體頒發的憑證。它包含與證書對應的使用者公鑰以及其它一些記錄證書主題和使用者資訊的資料。證書機構只有在驗證了證書主題和證書對應的使用者公鑰的有效性之後才會簽發證書。

證書申請者和證書機構之間交換籤發證書資訊可以使用物理介質,比如軟盤,進行傳輸。通常,這種資訊都是在計算機網路上進行完成的。證書機構使用被信任的服務程式處理使用者的請求和證書的簽發工作。

  完整性檢測

任何通過不安全介質傳輸的資訊都可以被意外或蓄意的修改。在現實世界中,蓋章、簽名就是用來提供和證明資訊完整性的工具。

資訊的接收者不但需要確定資訊是由誰傳送的,還要確定自己收到的資訊是傳送者傳送的資訊,而沒有任何的變化。要建立資料的完整性檢測機制,不僅要傳送資訊本身,還要傳送用來校驗資料的資訊,這一資訊通常被稱作雜湊值。資料和驗證資訊都可以與數字簽名一起傳送來證明其完整性。

  2. PKCS#11

  架構

  會話狀態

  物件

  機制

根據機制標記,可以分為幾類:

  • CKF_ENCRYPT:加密類
  • CKF_DECRYPT:解密類
  • CKF_DIGEST:摘要類
  • CKF_SIGN:簽名類
  • CKF_SIGN_RECOVER:可恢復簽名類
  • CKF_VERIFY:驗證類
  • CKF_VERIFY_RECOVER:可恢復驗證類
  • CKF_GENERATE:金鑰產生
  • CKF_GENERATE_KEY_PAIR:金鑰對產生
  • CKF_WRAP:金鑰封裝
  • CKF_UNWRAP:金鑰解封
  • CKF_DERIVE:金鑰派生

  3. GMT 0016-2012

密碼服務

錯誤程式碼

  4. GMT 0018-2012












這些API它們的異同

  Crypto API感覺更加易讀,但是分類較為複雜;PKCS#11為擁有密碼資訊(如加密金鑰和證書)和執行密碼學函式的單使用者裝置定義了一個應用程式介面(API)。智慧卡就是實現Cryptoki的典型裝置。但Cryptoki定義了密碼函式介面,但並未指明裝置具體如何實現這些函式。而且Cryptoki只說明瞭密碼介面,並未定義對裝置來說可能有用的其他介面,如訪問裝置的檔案系統介面,其API很全面,很模式化,讀起來有點頭暈。國密標準感覺挺複雜的,既具體地講解了裝置又分析瞭如何呼叫其介面進行加密解密,其API更側重於裝置,基本上都是基於裝置進行開發。

呼叫不同介面的程式碼

  Crypto API
HCRYPTPROV hCryptProv;
HCRYPTHASH hCryptHash;
HCRYPTKEY hCryptKey;


CPAcquireContext(
    hCryptProv, NULL,
    MS_DEF_PROV,
    PROV_RSA_FULL,
    CRYPT_VERIFYCONTEXT
)//為應用程式建立一個上下文
    
CPCreateHash(
    hCryptProv,
    CALG_MD5,
    0,
    0,
    &hCryptHash
) //為應用程式建立一個上下文
    
static char szHash[]=”PISAHASHDATA”; //原始字串
DWORD dwLen=strlen(szHash);
CPHashData(hCryptHash, (BYTE*)szHash, dwLen, 0);//雜湊輸入的資料
CPDeriveKey(hCryptProv, CALG_RC2, hCryptHash, 0, &hCryptKey);//從一個數據雜湊中生成一個會話金鑰,它保證生成的金鑰互不相同

static char szEntry[]= “PISA2002”;
DWORD dwLenIn = strlen(szEntry);
DWORD dwLenOut=dwLenIn;
CPEncrypt(hCryptKey, 0, TRUE, 0, (BYTE*)szEntry, &dwLenOut, dwLenIn);//用來加密明文
CPDecrypt(hCryptKey, 0, TRUE, 0,(BYTE*)szEntry,&dwLenOut);//用來解密先前被加密的資料
CPDestroyKey(hCryptKey);//釋放一個金鑰控制代碼,釋放後,控制代碼將無效,金鑰將無法再被訪問
CPDestroyHash(hCryptHash);//刪除一個雜湊物件控制代碼
CPReleaseContext(hCryptProv, NULL);//釋放CPAcquireContext.建立的上下文

  PKCS#11

CK_SESSION_HANDLE hSession;
CK_MECHANISM digestMechanism;
CK_ULONG ulStateLen;
CK_BYTE data1[] = {0x01, 0x03, 0x05, 0x07};
CK_BYTE data2[] = {0x02, 0x04, 0x08};
CK_BYTE data3[] = {0x10, 0x0F, 0x0E, 0x0D, 0x0C};
CK_BYTE pDigest[20];
CK_ULONG ulDigestLen;
CK_RV rv;

/* Initialize hash operation */
rv = C_DigestInit(hSession, &digestMechanism);//初始化訊息雜湊計算操作,指定計算訊息雜湊的演算法
assert(rv == CKR_OK);

/* Start hashing */
rv = C_DigestUpdate(hSession, data1, sizeof(data1));//對多個分組的訊息進行雜湊計算
assert(rv == CKR_OK);//返回成功或者失敗

/* Find out how big the state might be */
rv = C_GetOperationState(hSession, NULL_PTR, &ulStateLen);//獲取裝置是否存在的狀態
assert(rv == CKR_OK);//返回成功或者失敗

/* Allocate some memory and then get the state */
pState = (CK_BYTE_PTR) malloc(ulStateLen);
rv = C_GetOperationState(hSession, pState, &ulStateLen);//獲取裝置是否存在的狀態

/* Continue hashing */
rv = C_DigestUpdate(hSession, data2, sizeof(data2));//對多個分組的訊息進行雜湊計算
assert(rv == CKR_OK);//返回成功或者失敗

/* Restore state.  No key handles needed */
rv = C_SetOperationState(hSession, pState, ulStateLen, 0, 0);
assert(rv == CKR_OK);//返回成功或者失敗

/* Continue hashing from where we saved state */
rv = C_DigestUpdate(hSession, data3, sizeof(data3));//對多個分組的訊息進行雜湊計算
assert(rv == CKR_OK);//返回成功或者失敗

/* Conclude hashing operation */
ulDigestLen = sizeof(pDigest);
rv = C_DigestFinal(hSession, pDigest, &ulDigestLen);
if (rv == CKR_OK) {
  /* pDigest[] now contains the hash of 0x01030507100F0E0D0C */
}//返回成功或者失敗

  SKF介面

CK_FLAGS flags = 0;
CK_Dev_ID DevID;
CK_Dev_INFO DevInfo;

/* Block and wait for a slot event */
rv = SKF_WaitForSlotEvent(flags, &slotID, NULL_PTR);//等待裝置的插拔事件
assert(rv == CKR_OK);//返回成功或者失敗

/* See what’s up with that slot */
rv = SKF_GetDevInfo(slotID, &slotInfo);//獲取裝置的一些特徵資訊
assert(rv == CKR_OK);//返回成功或者失敗