ここで説明する例は、RSA 鍵ペアを生成します。そのあと、その鍵ペアで単純な文字列を署名および検証します。この例では、次の手順を実行します。
鍵オブジェクトを定義します。
公開鍵のテンプレートを設定します。
非公開鍵のテンプレートを設定します。
メッセージ例を作成します。
鍵ペアを生成する genmech 機構を指定します。
鍵ペアに署名する smech 機構を指定します。
cryptoki ライブラリを初期化します。
署名、検証、および鍵ペア生成用の機構を備えたスロットを検索します。この作業では、getMySlot() という名前の関数を使って次の手順を実行します。
関数 C_GetSlotList() を呼び出して利用可能なスロットのリストを取得します。
PKCS #11 の規約でも推奨されているように、C_GetSlotList() は 2 回呼び出されます。1 回目の C_GetSlotList() 呼び出しでは、メモリーを割り当てる目的でスロット数を取得します。そして 2 回目の C_GetSlotList() 呼び出しでは、スロットを取得します。
目的の機構を提供できるスロットを検索します。
この関数はスロットごとに、GetMechanismInfo() を呼び出して署名用の機構と鍵ペア生成用の機構を検索します。それらの機構がそのスロットでサポートされていない場合、GetMechanismInfo() はエラーを返します。GetMechanismInfo() が成功を返した場合、機構のフラグを検査し、その機構が必要な処理を実行できることを確認します。
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
/* Define key template */
static CK_BBOOL truevalue = TRUE;
static CK_BBOOL falsevalue = FALSE;
static CK_ULONG modulusbits = 1024;
static CK_BYTE public_exponent[] = {3};
boolean_t GetMySlot(CK_MECHANISM_TYPE sv_mech, CK_MECHANISM_TYPE kpgen_mech,
    CK_SLOT_ID_PTR pslot);
/* Example signs and verifies a simple string, using a public/private
 * key pair. */
void
main(int argc, char **argv)
{
	CK_RV   rv;
	CK_MECHANISM genmech, smech;
	CK_SESSION_HANDLE hSession;
	CK_SESSION_INFO sessInfo;
	CK_SLOT_ID slotID;
	int error, i = 0;
	CK_OBJECT_HANDLE privatekey, publickey;
    /* Set public key. */
	CK_ATTRIBUTE publickey_template[] = {
		{CKA_VERIFY, &truevalue, sizeof (truevalue)},
		{CKA_MODULUS_BITS, &modulusbits, sizeof (modulusbits)},
		{CKA_PUBLIC_EXPONENT, &public_exponent,
		    sizeof (public_exponent)}
	};
    /* Set private key. */
	CK_ATTRIBUTE privatekey_template[] = {
		{CKA_SIGN, &truevalue, sizeof (truevalue)},
		{CKA_TOKEN, &falsevalue, sizeof (falsevalue)},
		{CKA_SENSITIVE, &truevalue, sizeof (truevalue)},
		{CKA_EXTRACTABLE, &truevalue, sizeof (truevalue)}
	};
    /* Create sample message. */
	CK_ATTRIBUTE getattributes[] = {
		{CKA_MODULUS_BITS, NULL_PTR, 0},
		{CKA_MODULUS, NULL_PTR, 0},
		{CKA_PUBLIC_EXPONENT, NULL_PTR, 0}
	};
	CK_ULONG messagelen, slen, template_size;
	boolean_t found_slot = B_FALSE;
	uchar_t *message = (uchar_t *)"Simple message for signing & verifying.";
	uchar_t *modulus, *pub_exponent;
	char sign[BUFFERSIZ];
	slen = BUFFERSIZ;
	messagelen = strlen((char *)message);
	/* Set up mechanism for generating key pair */
	genmech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
	genmech.pParameter = NULL_PTR;
	genmech.ulParameterLen = 0;
	/* Set up the signing mechanism */
	smech.mechanism = CKM_RSA_PKCS;
	smech.pParameter = NULL_PTR;
	smech.ulParameterLen = 0;
	/* Initialize the CRYPTOKI library */
	rv = C_Initialize(NULL_PTR);
	if (rv != CKR_OK) {
		fprintf(stderr, "C_Initialize: Error = 0x%.8X\n", rv);
		exit(1);
	}
	found_slot = GetMySlot(smech.mechanism, genmech.mechanism, &slotID);
	if (!found_slot) {
		fprintf(stderr, "No usable slot was found.\n");
		goto exit_program;
	}
	fprintf(stdout, "selected slot: %d\n", slotID);
	/* Open a session on the slot found */
	rv = C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR,
	    &hSession);
	if (rv != CKR_OK) {
		fprintf(stderr, "C_OpenSession: rv = 0x%.8X\n", rv);
		error = 1;
		goto exit_program;
	}
	fprintf(stdout, "Generating keypair....\n");
	/* Generate Key pair for signing/verifying */
	rv = C_GenerateKeyPair(hSession, &genmech, publickey_template,
	    (sizeof (publickey_template) / sizeof (CK_ATTRIBUTE)),
	    privatekey_template,
	    (sizeof (privatekey_template) / sizeof (CK_ATTRIBUTE)),
	    &publickey, &privatekey);
	if (rv != CKR_OK) {
		fprintf(stderr, "C_GenerateKeyPair: rv = 0x%.8X\n", rv);
		error = 1;
		goto exit_session;
	}
	/* Display the publickey. */
	template_size = sizeof (getattributes) / sizeof (CK_ATTRIBUTE);
	rv = C_GetAttributeValue(hSession, publickey, getattributes,
	    template_size);
	if (rv != CKR_OK) {
		/* not fatal, we can still sign/verify if this failed */
		fprintf(stderr, "C_GetAttributeValue: rv = 0x%.8X\n", rv);
		error = 1;
	} else {
		/* Allocate memory to hold the data we want */
		for (i = 0; i < template_size; i++) {
			getattributes[i].pValue = 
			    malloc (getattributes[i].ulValueLen * 
				sizeof(CK_VOID_PTR));
			if (getattributes[i].pValue == NULL) {
				int j;
				for (j = 0; j < i; j++)
					free(getattributes[j].pValue);
				goto sign_cont;
			}
		}
		/* Call again to get actual attributes */
		rv = C_GetAttributeValue(hSession, publickey, getattributes,
		    template_size);
		if (rv != CKR_OK) {
			/* not fatal, we can still sign/verify if failed */
			fprintf(stderr,
			    "C_GetAttributeValue: rv = 0x%.8X\n", rv);
			error = 1;
		} else {
			/* Display public key values */
			fprintf(stdout, "Public Key data:\n\tModulus bits: "
			    "%d\n", 
			    *((CK_ULONG_PTR)(getattributes[0].pValue)));
			fprintf(stdout, "\tModulus: ");
			modulus = (uchar_t *)getattributes[1].pValue;
			for (i = 0; i < getattributes[1].ulValueLen; i++) {
				fprintf(stdout, "%.2x", modulus[i]);
			}
			fprintf(stdout, "\n\tPublic Exponent: ");
			pub_exponent = (uchar_t *)getattributes[2].pValue;
			for (i = 0; i< getattributes[2].ulValueLen; i++) {
				fprintf(stdout, "%.2x", pub_exponent[i]);
			}
			fprintf(stdout, "\n");
		}
	}
	
sign_cont:	
	rv = C_SignInit(hSession, &smech, privatekey);
	if (rv != CKR_OK) {
		fprintf(stderr, "C_SignInit: rv = 0x%.8X\n", rv);
		error = 1;
		goto exit_session;
	}
	rv = C_Sign(hSession, (CK_BYTE_PTR)message, messagelen,
	    (CK_BYTE_PTR)sign, &slen);
	if (rv != CKR_OK) {
		fprintf(stderr, "C_Sign: rv = 0x%.8X\n", rv);
		error = 1;
		goto exit_session;
	}
	fprintf(stdout, "Message was successfully signed with private key!\n");
	rv = C_VerifyInit(hSession, &smech, publickey);
	if (rv != CKR_OK) {
		fprintf(stderr, "C_VerifyInit: rv = 0x%.8X\n", rv);
		error = 1;
		goto exit_session;
	}
	rv = C_Verify(hSession, (CK_BYTE_PTR)message, messagelen,
	    (CK_BYTE_PTR)sign, slen);
	if (rv != CKR_OK) {
		fprintf(stderr, "C_Verify: rv = 0x%.8X\n", rv);
		error = 1;
		goto exit_session;
	}
	fprintf(stdout, "Message was successfully verified with public key!\n");
exit_session:
	(void) C_CloseSession(hSession);
exit_program:
	(void) C_Finalize(NULL_PTR);
	for (i = 0; i < template_size; i++) {
		if (getattributes[i].pValue != NULL)
			free(getattributes[i].pValue);
	}
	exit(error);
}
/* Find a slot capable of:
 * . signing and verifying with sv_mech
 * . generating a key pair with kpgen_mech
 * Returns B_TRUE when successful. */
boolean_t GetMySlot(CK_MECHANISM_TYPE sv_mech, CK_MECHANISM_TYPE kpgen_mech,
    CK_SLOT_ID_PTR pSlotID)
{
	CK_SLOT_ID_PTR pSlotList = NULL_PTR;
	CK_SLOT_ID SlotID;
	CK_ULONG ulSlotCount = 0;
	CK_MECHANISM_INFO mech_info;
	int i;
	boolean_t returnval = B_FALSE;
	CK_RV rv;
	/* Get slot list for memory alloction */
	rv = C_GetSlotList(0, NULL_PTR, &ulSlotCount);
	if ((rv == CKR_OK) && (ulSlotCount > 0)) {
		fprintf(stdout, "slotCount = %d\n", ulSlotCount);
		pSlotList = malloc(ulSlotCount * sizeof (CK_SLOT_ID));
		if (pSlotList == NULL) {
			fprintf(stderr, "System error: unable to allocate "
			    "memory\n");
			return (returnval);
		}
		/* Get the slot list for processing */
		rv = C_GetSlotList(0, pSlotList, &ulSlotCount);
		if (rv != CKR_OK) {
			fprintf(stderr, "GetSlotList failed: unable to get "
			    "slot count.\n");
			goto cleanup;
		}
	} else {
		fprintf(stderr, "GetSlotList failed: unable to get slot "
		    "list.\n");
		return (returnval);
	}
	/* Find a slot capable of specified mechanism */
	for (i = 0; i < ulSlotCount; i++) {
		SlotID = pSlotList[i];
		/* Check if this slot is capable of signing and
		 * verifying with sv_mech. */
		rv = C_GetMechanismInfo(SlotID, sv_mech, &mech_info);
		if (rv != CKR_OK) {
			continue;
		}
		if (!(mech_info.flags & CKF_SIGN &&
			mech_info.flags & CKF_VERIFY)) {
			continue;
		}
		/* Check if the slot is capable of key pair generation
		 * with kpgen_mech. */
		rv = C_GetMechanismInfo(SlotID, kpgen_mech, &mech_info);
		if (rv != CKR_OK) {
			continue;
		}
		if (!(mech_info.flags & CKF_GENERATE_KEY_PAIR)) {
			continue;
		}
		/* If we get this far, this slot supports our mechanisms. */
		returnval = B_TRUE;
		*pSlotID = SlotID;
		break;
	}
cleanup:
	if (pSlotList)
		free(pSlotList);
	return (returnval);
}