Solaris 开发者安全性指南

签名和检验示例

本节中的示例生成了一个用于对简单字符串进行签名和检验的 RSA 密钥对。此示例执行以下步骤:

  1. 定义密钥对象。

  2. 设置公钥模板。

  3. 设置私钥模板。

  4. 创建样例消息。

  5. 指定用于生成密钥对象的 genmech 机制。

  6. 指定用于对密钥对进行签名的 smech 机制。

  7. 初始化 cryptoki 库。

  8. 通过用于生成和检验密钥对并对其进行签名的机制来查找插槽。此任务将使用一个名为 getMySlot() 的函数来执行以下步骤:

    1. 调用 C_GetSlotList() 函数以获取可用插槽的列表。

      与 PKCS #11 约定中所建议的一样,C_GetSlotList() 需要调用两次。第一次调用 C_GetSlotList() 用于获取进行内存分配的插槽数量,第二次调用 C_GetSlotList() 用于检索插槽。

    2. 查找可以提供所需机制的插槽。

      对于每个插槽,该函数都会调用 GetMechanismInfo() 以查找可用于生成密钥对并对其进行签名的机制。如果插槽不支持这些机制,则 GetMechanismInfo() 将返回错误。如果 GetMechanismInfo() 成功返回,则将检查机制标志,以确保这些机制可以执行所需的操作。

  9. 调用 C_OpenSession() 来打开会话。

  10. 使用 C_GenerateKeyPair() 来生成密钥对。

  11. 使用 C_GetAttributeValue() 显示公钥-仅用于说明。

  12. 签名以 C_SignInit() 开始,以 C_Sign() 结束。

  13. 检验以 C_VerifyInit() 开始,以 C_Verify() 结束。

  14. 关闭会话。

    程序使用 C_CloseSession() 关闭会话,使用 C_Finalize() 关闭库。

下面是签名和检验示例的源代码。


注 –

此示例的源代码也可以通过 Sun 下载中心获取。请访问 http://www.sun.com/download/products.xml?id=41912db5



示例 9–3 使用 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



/* 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);



}