Solaris 开发者安全性指南

对称加密示例

示例 9–2 在 CBC(密码块链接)模式下使用 DES 算法为加密创建了密钥对象。此源代码执行以下步骤:

  1. 声明密钥材料。

    定义 DES 和初始化向量。以静态方式声明的初始化向量仅用于说明,初始化向量应始终以动态方式定义并且永远不会重用。

  2. 定义密钥对象。

    对于此任务,必须为密钥设置模板。

  3. 查找适用于指定加密机制的插槽。

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

  4. 在插槽中执行加密操作。

    此任务中的加密可通过以下几个步骤执行:

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

    2. 打开输入文件。

    3. 创建密钥的对象句柄。

    4. 使用机制结构将加密机制设置为 CKM_DES_CBC_PAD。

    5. 调用 C_EncryptInit() 来初始化加密操作。

    6. 使用 C_EncryptUpdate() 逐段处理数据。

    7. 使用 C_EncryptFinal() 获取最后一部分加密数据,从而结束加密过程。

  5. 在插槽中执行解密操作。

    此任务中的解密可通过以下两个步骤执行。提供解密的目的仅是为了进行测试。

    1. 调用 C_DecryptInit() 来初始化解密操作。

    2. 使用 C_Decrypt() 处理整个字符串。

  6. 结束会话。

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

以下示例中显示了对称加密示例的源代码。


注 –

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



示例 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,

	    ciphertext_space = BUFFERSIZ;

	CK_ULONG decrypttext_len;

	CK_ULONG total_encrypted = 0;

	CK_ULONG ulDatalen = BUFFERSIZ;

	CK_SLOT_ID SlotID;



	int *pi, i, bytes_read = 0;

	int error = 0;

	char inbuf[BUFFERSIZ];

	FILE *fs;

	uchar_t *ciphertext, *pciphertext, *decrypttext;



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

}