例 9–2 は、DES アルゴリズムの CBC モードを使って暗号化するための鍵オブジェクトを作成します。このソースコードは次の手順を実行します。
鍵データを宣言します。
DES と初期化ベクトルを定義します。ここでは初期化ベクトルを静的に宣言していますが、これはあくまでもデモ用です。初期化ベクトルは常に動的に定義し、決して再利用しないでください。
鍵オブジェクトを定義します。
この作業では、鍵のテンプレートを設定する必要があります。
指定された暗号化機構をサポートするスロットを検索します。
この例では、Sun の簡易関数 SUNW_C_GetMechSession() を使用しています。SUNW_C_GetMechSession() は、cryptoki ライブラリをオープンします。このライブラリには、Solaris 暗号化フレームワークで使用されるすべての PKCS #11 関数が含まれています。続いて SUNW_C_GetMechSession() は、目的の機構を備えたスロットを検索します。そして、セッションが開始されます。この簡易関数は事実上、C_Initialize() 呼び出し、C_OpenSession() 呼び出し、および指定された機構をサポートするスロットの検索に必要なすべてのコードと同等の機能を備えています。
このスロットで暗号化処理を実行します。
この作業における暗号化の実行手順は次のとおりです。
このスロットで復号化処理を実行します。
この作業における復号化の実行手順は次のとおりです。この復号化処理は、テスト目的でのみ提供されています。
セッションを終了します。
このプログラムは、C_CloseSession() を使ってセッションをクローズし、C_Finalize() を使ってライブラリをクローズします。
対称暗号化のソースコード例を、次に示します。
このソースコード例は、Sun ダウンロードセンターからダウンロードすることも可能です。http://www.sun.com/download/products.xml?id=41912db5 を参照してください。
#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); }