Example 9–2 在 CBC 模式下使用 DES 算法创建要加密的密钥对象。此源代码执行以下步骤:
声明密钥材料。
定义 DES 和初始化向量。以静态方式声明的初始化向量仅用于说明,初始化向量应始终以动态方式定义并且永远不会重用。
定义密钥对象。
对于此任务,必须为密钥设置模板。
查找适用于指定加密机制的插槽。
此示例使用 Oracle Solaris 的便利函数 SUNW_C_GetMechSession()。SUNW_C_GetMechSession() 用于打开 cryptoki 库,该库存放着 Oracle Solaris 加密框架中所使用的全部 PKCS #11 函数。SUNW_C_GetMechSession() 随后使用所需的机制来查找插槽。然后,将会启动会话。这个便利函数可有效地替换 C_Initialize() 调用、C_OpenSession() 调用以及查找支持指定机制的插槽所需的任何代码。
在插槽中执行加密操作。
在插槽中执行解密操作。
结束会话。
程序使用 C_CloseSession() 关闭会话,使用 C_Finalize() 关闭库。
以下示例中显示了对称加密示例的源代码。
示例 9-2 使用 PKCS #11 函数创建加密密钥对象#include <stdio.h> #include <fcntl.h> #include <errno.h> #include <sys/types.h> #include <security/cryptoki.h> #include <security/pkcs11.h> #define BUFFERSIZ 8192 /* Declare values for the key materials. DO NOT declare initialization * vectors statically like this in real life!! */ uchar_t des_key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; uchar_t des_cbc_iv[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef}; /* Key template related definitions. */ static CK_BBOOL truevalue = TRUE; static CK_BBOOL falsevalue = FALSE; static CK_OBJECT_CLASS class = CKO_SECRET_KEY; static CK_KEY_TYPE keyType = CKK_DES; /* Example encrypts and decrypts a file provided by the user. */ void main(int argc, char **argv) { CK_RV rv; CK_MECHANISM mechanism; CK_OBJECT_HANDLE hKey; CK_SESSION_HANDLE hSession; CK_ULONG ciphertext_len = 64, lastpart_len = 64; long ciphertext_space = BUFFERSIZ; CK_ULONG decrypttext_len; CK_ULONG total_encrypted = 0; CK_ULONG ulDatalen = BUFFERSIZ; int i, bytes_read = 0; int error = 0; char inbuf[BUFFERSIZ]; FILE *fs; uchar_t ciphertext[BUFFERSIZ], *pciphertext, decrypttext[BUFFERSIZ]; /* Set the key object */ CK_ATTRIBUTE template[] = { {CKA_CLASS, &class, sizeof (class) }, {CKA_KEY_TYPE, &keyType, sizeof (keyType) }, {CKA_TOKEN, &falsevalue, sizeof (falsevalue) }, {CKA_ENCRYPT, &truevalue, sizeof (truevalue) }, {CKA_VALUE, &des_key, sizeof (des_key) } }; /* Set the encryption mechanism to CKM_DES_CBC_PAD */ mechanism.mechanism = CKM_DES_CBC_PAD; mechanism.pParameter = des_cbc_iv; mechanism.ulParameterLen = 8; /* Use SUNW convenience function to initialize the cryptoki * library, and open a session with a slot that supports * the mechanism we plan on using. */ rv = SUNW_C_GetMechSession(mechanism.mechanism, &hSession); if (rv != CKR_OK) { fprintf(stderr, "SUNW_C_GetMechSession: rv = 0x%.8X\n", rv); exit(1); } /* Open the input file */ if ((fs = fopen(argv[1], "r")) == NULL) { perror("fopen"); fprintf(stderr, "\n\tusage: %s filename>\n", argv[0]); error = 1; goto exit_session; } /* Create an object handle for the key */ rv = C_CreateObject(hSession, template, sizeof (template) / sizeof (CK_ATTRIBUTE), &hKey); if (rv != CKR_OK) { fprintf(stderr, "C_CreateObject: rv = 0x%.8X\n", rv); error = 1; goto exit_session; } /* Initialize the encryption operation in the session */ rv = C_EncryptInit(hSession, &mechanism, hKey); if (rv != CKR_OK) { fprintf(stderr, "C_EncryptInit: rv = 0x%.8X\n", rv); error = 1; goto exit_session; } /* Read in the data and encrypt this portion */ pciphertext = &ciphertext[0]; while (!feof(fs) && (ciphertext_space > 0) && (ulDatalen = fread(inbuf, 1, ciphertext_space, fs)) > 0) { ciphertext_len = ciphertext_space; /* C_EncryptUpdate is only being sent one byte at a * time, so we are not checking for CKR_BUFFER_TOO_SMALL. * Also, we are checking to make sure we do not go * over the alloted buffer size. A more robust program * could incorporate realloc to enlarge the buffer * dynamically. */ rv = C_EncryptUpdate(hSession, (CK_BYTE_PTR)inbuf, ulDatalen, pciphertext, &ciphertext_len); if (rv != CKR_OK) { fprintf(stderr, "C_EncryptUpdate: rv = 0x%.8X\n", rv); error = 1; goto exit_encrypt; } pciphertext += ciphertext_len; total_encrypted += ciphertext_len; ciphertext_space -= ciphertext_len; bytes_read += ulDatalen; } if (!feof(fs) || (ciphertext_space < 0)) { fprintf(stderr, "Insufficient space for encrypting the file\n"); error = 1; goto exit_encrypt; } /* Get the last portion of the encrypted data */ lastpart_len = ciphertext_space; rv = C_EncryptFinal(hSession, pciphertext, &lastpart_len); if (rv != CKR_OK) { fprintf(stderr, "C_EncryptFinal: rv = 0x%.8X\n", rv); error = 1; goto exit_encrypt; } total_encrypted += lastpart_len; fprintf(stdout, "%d bytes read and encrypted. Size of the " "ciphertext: %d!\n\n", bytes_read, total_encrypted); /* Print the encryption results */ fprintf(stdout, "The value of the encryption is:\n"); for (i = 0; i < ciphertext_len; i++) { if (ciphertext[i] < 16) fprintf(stdout, "0%x", ciphertext[i]); else fprintf(stdout, "%2x", ciphertext[i]); } /* Initialize the decryption operation in the session */ rv = C_DecryptInit(hSession, &mechanism, hKey); /* Decrypt the entire ciphertext string */ decrypttext_len = sizeof (decrypttext); rv = C_Decrypt(hSession, (CK_BYTE_PTR)ciphertext, total_encrypted, decrypttext, &decrypttext_len); if (rv != CKR_OK) { fprintf(stderr, "C_Decrypt: rv = 0x%.8X\n", rv); error = 1; goto exit_encrypt; } fprintf(stdout, "\n\n%d bytes decrypted!!!\n\n", decrypttext_len); /* Print the decryption results */ fprintf(stdout, "The value of the decryption is:\n%s", decrypttext); fprintf(stdout, "\nDone!!!\n"); exit_encrypt: fclose(fs); exit_session: (void) C_CloseSession(hSession); exit_program: (void) C_Finalize(NULL_PTR); exit(error); }