面向开发者的 Oracle® Solaris 11 安全性指南

退出打印视图

更新时间: 2014 年 7 月
 
 

消息摘要示例

    此示例使用 PKCS #11 函数基于输入文件创建摘要。此示例执行以下步骤:

  1. 指定摘要机制。

    此示例中使用的是 CKM_MD5 摘要机制。

  2. 查找适用于指定摘要算法的插槽。

    此示例使用 Oracle Solaris 的便利函数 SUNW_C_GetMechSession()SUNW_C_GetMechSession() 用于打开 cryptoki 库,该库存放着 Oracle Solaris 加密框架中所使用的全部 PKCS #11 函数。SUNW_C_GetMechSession() 随后使用所需的机制来查找插槽。然后,将会启动会话。这个便利函数可有效地替换 C_Initialize() 调用、C_OpenSession() 调用以及查找支持指定机制的插槽所需的任何代码。

  3. 获取 cryptoki 信息。

    本部分实际上不是创建消息摘要所必需的,之所以将其包括在内是为了说明 C_GetInfo() 函数的用法。此示例中将获取制造商 ID。其他信息选项用于检索版本和库数据。

  4. 针对插槽执行摘要操作。

      此任务中的消息摘要可通过以下几个步骤创建:

    1. 打开输入文件。

    2. 通过调用 C_DigestInit() 来初始化摘要操作。

    3. 使用 C_DigestUpdate() 逐段处理数据。

    4. 使用 C_DigestFinal() 获取完整的摘要,从而结束摘要操作过程。

  5. 结束会话。

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

以下示例中显示了消息摘要示例的源代码。

示例 9-1  使用 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 MAXDIGEST    64

/* Calculate the digest of a user supplied file. */
void
main(int argc, char **argv)
{
	CK_BYTE digest[MAXDIGEST];
	CK_INFO info;
	CK_MECHANISM mechanism;
	CK_SESSION_HANDLE hSession;
	CK_SESSION_INFO Info;
	CK_ULONG ulDatalen = BUFFERSIZ;
	CK_ULONG ulDigestLen = MAXDIGEST;
	CK_RV rv;
	CK_SLOT_ID SlotID;

	int i, bytes_read = 0;
	char inbuf[BUFFERSIZ];
	FILE *fs;
	int error = 0;

	/* Specify the CKM_MD5 digest mechanism as the target */
	mechanism.mechanism = CKM_MD5;
	mechanism.pParameter = NULL_PTR;
	mechanism.ulParameterLen = 0;

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

	/* Get cryptoki information, the manufacturer ID */
	rv = C_GetInfo(&info);
	if (rv != CKR_OK) {
		fprintf(stderr, "WARNING: C_GetInfo: rv = 0x%.8X\n", rv);
	}
	fprintf(stdout, "Manufacturer ID = %s\n", info.manufacturerID);

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

	/* Initialize the digest session */
	if ((rv = C_DigestInit(hSession, &mechanism)) != CKR_OK) {
		fprintf(stderr, "C_DigestInit: rv = 0x%.8X\n", rv);
		error = 1;
		goto exit_digest;
	}

	/* Read in the data and create digest of this portion */
	while (!feof(fs) && (ulDatalen = fread(inbuf, 1, BUFFERSIZ, fs)) > 0) {
		if ((rv = C_DigestUpdate(hSession, (CK_BYTE_PTR)inbuf,
				    ulDatalen)) != CKR_OK) {
			fprintf(stderr, "C_DigestUpdate: rv = 0x%.8X\n", rv);
			error = 1;
			goto exit_digest;
		}
		bytes_read += ulDatalen;
	}
	fprintf(stdout, "%d bytes read and digested!!!\n\n", bytes_read);

	/* Get complete digest */
	ulDigestLen = sizeof (digest);
	if ((rv = C_DigestFinal(hSession, (CK_BYTE_PTR)digest,
			    &ulDigestLen)) != CKR_OK) {
		fprintf(stderr, "C_DigestFinal: rv = 0x%.8X\n", rv);
		error = 1;
		goto exit_digest;
	}

	/* Print the results */
	fprintf(stdout, "The value of the digest is: ");
	for (i = 0; i < ulDigestLen; i++) {
		fprintf(stdout, "%.2x", digest[i]);
	}
	fprintf(stdout, "\nDone!!!\n");

exit_digest:
	fclose(fs);

exit_session:
	(void) C_CloseSession(hSession);

exit_program:
	(void) C_Finalize(NULL_PTR);

	exit(error);

}