首页 > 其他分享 >实验一-密码引擎-3-加密API研究

实验一-密码引擎-3-加密API研究

时间:2024-04-14 15:44:35浏览次数:35  
标签:CK rv 加密 引擎 hSession 密钥 API OP

实验一-密码引擎-3-加密API研究

任务详情

密码引擎API的主要标准和规范包括:
1 微软的Crypto API
2 RAS公司的PKCS#11标准
3 中国商用密码标准:GMT 0016-2012 智能密码钥匙密码应用接口规范,GMT 0018-2012密码设备应用接口规范等

研究以上API接口,总结他们的异同,并以龙脉GM3000Key为例,写出调用不同接口的代码,提交博客链接和代码链接。
内容:
0 查找各种标准的原始文档,研究学习(至少包含Crypto API,PKCS#11,GMT 0016-2012,GMT 0018-2012)
1 总结这些API在编程中的使用方式
2 列出这些API包含的函数,进行分类,并总结它们的异同
3 以龙脉GM3000Key为例,写出调用不同接口的代码(Crypto API,PKCS#11,SKF接口),把运行截图加入博客,并提供代码链接

研究学习

0 查找各种标准的原始文档,研究学习(至少包含Crypto API,PKCS#11,GMT 0016-2012,GMT 0018-2012)

(1)微软的Crypto API:

是Microsoft 公司提出的安全加密应用服务框架,也是PKI推荐使用的加密 API。它提供了在Win32 环境下使用认证、编码、加密和签名等安全服务时的标准加密接口,用于增强应用程序的安全性与可控性。应用开发者可以在不了解复杂的加密机制和加密算法的情况下,简便、快速地开发出标准、通用和易于扩展的安全加密应用程序。CryptoAPI 提供的功能主要有:密钥管理、数据加密和解密、数字签名和验证、证书管理、可信根证书管理、数据编码和解码、数字证书编码和解码、PKCS#7 标准格式编码和解码等。利用CryptoAPI,开发者可以给基于Windows的应用程序添加安全服务,包括: ASN.1编码及解码、数据加密/解密、身份论证、数字证书管理,同时支持PKI、对称密码技术等。应用程序开发者直接使用这些安全功能而无须了解其底层实现。作为一部分 Microsoft Windows 提供的应用程序编程接口 (API),CryptoAPI 提供了一组函数。这些函数允许应用程序在对用户的敏感私钥数据提供保护时,以灵活的方式对数据进行加密或数字签名。实际的加密操作是由称为加密服务提供程序 (CSP) 的独立模块执行。

  • CryptoAPI是一组函数,为了完成数学计算,必须具有密码服务提供者模块(CSP)。Microsoft通过捆绑RSA Base Provider在操作系统级提供一个CSP,使用RSA公司的公钥加密算法,更多的CSP可以根据需要增加到应用中。事实上,CSP有可能与特殊硬件设备(如智能卡)一起来进行数据加密。CryptoAPI接口允许简单的函数调用来加密数据,交换公钥,散列一个消息来建立摘要以及生成数字签名。它还提供高级的管理操作,如从一组可能的CSP中使用一个CSP。此外,CryptoAPI还为许多高级安全性服务提供了基础,包括用于电子商务的SET,用于加密客户机/服务器消息的PCT,用于在各个平台之间来回传递机密数据和密钥的PFX,代码签名等等。
    (2)PKCS#11
  • 在密码系统中,PKCS#11是公钥加密标准(PKCS, Public-Key Cryptography Standards)中的一份子 ,由RSA实验室(RSA Laboratories)发布[1],它为加密令牌定义了一组平台无关的API ,如硬件安全模块和智能卡。

PKCS#11标准定义了与密码令牌(如硬件安全模块(HSM)和智能卡)的独立于平台的API,并将API本身命名为“Cryptoki”(来自“加密令牌接口”,发音为“crypto-key” - 但是“PKCS#11”通常用于指代API以及定义它的标准)。 API定义了最常用的加密对像类型(RSA密钥,X.509证书,DES / 三重DES密钥等)以及使用,创建/生成,修改和删除这些对象所需的所有功能。
GMT 0016-2012:

  • 本标准规定了基于PKI密码体制的智能密码钥匙密码应用接口,描述了密码应用接口的函数、数据类型、参数的定义和设备的安全要求。
    本标准适用于智能密码钥匙产品的研制、使用和检测。
    GMT 0018-2012:
  • 本标准规定了公钥密码基础设施应用技术体系下服务类密码设备的应用接口标准,
    本标准适用于服务类密码设备的研制使用,以及基于该类密码设备的应用开发,也可用于指导该类密码设备的检测

1、总结这些API在编程中的使用方式

(1)Crypto API
使用CryptoAPI编写一个文件保护程序,具有如下功能:

(1)给定明文文件,生成加密文件,同时产生文件的数字签名文件;

(2)给定密文文件,解密出明文文件,并验证签名的正确性。

在不安全的网络上进行安全的数据传输涉及三个方面的要求:信息隐藏,身份鉴别和完整性检验。CryptoAPI除了提供上述三个功能外还提供标准的ASN.1编码、解码,信息解密,数字证书和证书存储区的管理,证书信任列表、吊销列表和证书有效性检查等功能。
信息隐藏

  • 信息隐藏的意义是保障信息内容只能被特定的人获取。信息隐藏通常是使用某种形式的密码学方式。数据加密算法能保障信息的安区隐藏和传输。数据加密算法是将明文数据经过一定的变换使其看上去是一组毫无意义的数据。在没有加密密钥的情况下,对于好的加密算法想从密文获取明文信息是不可能的。被加密的数据可以是任意的ASCII编码文本文件,数据库文件,和任意需要进行安全传输的数据。这里,“信息”是指任意的一段数据,“明文”是指任意一段没有被加密的数据,“密文”是指任意一段加密的数据。被加密的数据可以在不安全的通道上进行传输而不伤害其安全性。之后,密文可以被还原成明文.

  • 数据加密和解密的概念是:对数据加密的时候需要一个加密密钥,相当于门上的一把钥匙。解密的时候,需要使用一个解密密钥来解开数据。加密密钥、解密密钥可以相同也可以不相同。

  • 加密密钥必须小心保存,给其它用户的时候也必须通过安全的通道传递。对解密密钥的访问权限必须小心控制,因为拥有解密密钥意味着可以解开所有相应加密密钥加密的信息。
    身份鉴别

  • 安全通讯的前提是通讯的双方知道对方的身份。身份鉴别的任务就是鉴别一个用户或者实体的真实身份。标识用户身份的文档通常被称为信任状或者凭证。

  • 身份鉴别有时候也用来判定接受的数据就是被发送的数据。如果A向B发送了一段数据,B需要鉴别这段数据就是A发出去的,而不是其它冒充A发出去的。为了满足这类验证的需求,CryptoAPI提供数字签名和校验函数,用来对信息进行鉴别。

  • 因为在计算机网网络上传输的数据与用户之间并没有物理连接,因此对数据进行鉴别的凭证也必须能够在网络上进行传输。这种凭证必须由受信任的凭证发行机构发行。

  • 数字证书就是平常说的证书就是这种凭证,是计算机在网络上进行身份验证的有效凭证。

  • 数字证书是由一个被称为证书机构的信任组织或实体颁发的凭证。它包含与证书对应的用户公钥以及其它一些记录证书主题和用户信息的数据。证书机构只有在验证了证书主题和证书对应的用户公钥的有效性之后才会签发证书。

  • 证书申请者和证书机构之间交换签发证书信息可以使用物理介质,比如软盘,进行传输。通常,这种信息都是在计算机网络上进行完成的。证书机构使用被信任的服务程序处理用户的请求和证书的签发工作。
    完整性检测

  • 任何通过不安全介质传输的信息都可以被意外或蓄意的修改。在现实世界中,盖章、签名就是用来提供和证明信息完整性的工具。

  • 信息的接收者不但需要确定信息是由谁发送的,还要确定自己收到的信息是发送者发送的信息,而没有任何的变化。要建立数据的完整性检测机制,不仅要发送信息本身,还要发送用来校验数据的信息,这一信息通常被称作哈希值。数据和验证信息都可以与数字签名一起发送来证明其完整性。
    (2)PKCS#11
    架构

    会话状态

    对象

    (3)GMT 0016-2012
    下列文件对于本文件的应用是必不可少的凡是注日期的引用文件,仅注日期的版本适用于本文件。凡是不注日期的引用文件,其最新版本(包括所有的修改单)适用于本文件。
    ①GM/T 0006 密码应用标识规范
    ②GM/T0009 SM2密码算法使用规范


术语和定义

下列术语和定义适用于本文件
应用 application

包括容器、设备认证密钥和文件的一种结构,具备独立的权限管理。
容器container

密码设备中用于保存密钥所划分的唯一性存储空间。
设备device

本标准中将智能密码钥匙统称为设备
设备认证 device authentication智能密码钥匙对应用程序的认证
设备认证密钥 device authentication key用于设备认证的密钥。
设备标签 label

设备的别名,可以由用户进行设定并存储于设备内部。
消息鉴别码 message authentication code; MAC消息鉴别算法的输出。
管理员PIN administrator PIN管理员的口令,为ASCII字符串
用户PIN user PIN

用户的口令,为ASCII字符串。
缩略语

下列缩略语适用于本规范: API 应用编程接口(Application Programming Interface)
PKI 公钥基础设施(Public Key Infrastructure)
PKCS#1
公钥密码使用标准系列规范中的第1部分,定义RSA公开密钥算法加密和签名机制(the Public-Key Cryptography Standard Part 1)
PKCS#5 公钥密码使用标准系列规范中的第5部分,描述一种利用从口令派生出来的安全密
钥加密字符串的方法(the Public-Key Cryptography Standard Part 5)
PIN 个人身份识别码(Personal Identification Number)
MAC 消息鉴别码(Message Authentication Code)
(4)GMT 0018-2012
规范性引用文件

下列文件对于本文件的应用是必不可少的。凡是注日期的引用文件,仅注日期的版本适用于本文件,凡是不注日期的引用文件,其最新版本(包括所有的修改单)适用于本文件。
GM/T0006密用标识规范 GM/T0009SM2密码算法使用规范
术语和定义

以下术语和定义活用干本文件
算法标识algorithm ideutifier

用于对密码算法进行唯一标识的符号。
非对称密码算法/公钥密码算法 asymmetric cryptographic algorithm/public key cryptographic algorithm加解密使用不同密钥的密码算法。
解密 decipherment/decryption加密过程对应的逆过程。
设备密钥device key pair

存储在设备内部的用于设备管理的非对称密钥对包含签名密钥对和加密密钥对。
加密encipherment/encryption

对数据进行密码变换以产生密文的过程。
密钥加密密钥key encrypt key;KEK对密钥进行加密保护的密钥。
公钥基础设施public key infrastructure;PKI

用公钥密码技术建立的普遍适用的基础设施,为用户提供证书管理和密钥管理等安全服务。
私钥访问控制码private key access password

用于验证私钥使用权限的口令字。
对称密码技术/对称密码体制 symmetric cryptographic technique

原发者和接收者均采用同秘密密钥进行变换的密码技术(体制)。其中,加密密钥与解密密钥相同或者一个密钥可以从另一个密钥导出的密码体制。
会话密钥session key

处于层次化密钥结构中的最低层,仅在一次会话中使用的密钥。
用户密钥 user key

存储在设备内部的用于应用密码运算的非对称密钥,包含签名密钥对和加密密钥对。
符号和缩略语

  • 下列缩略语适用于本部分:
    ECC 椭圆曲线算法(Elliptic Curve Cryptography)
    IPK 内部加密公钥(Internal Public Key)
    ISK
    内部加密私钥(Interal Private Key) EPK
    外部加密公钥(Extenal Public Key) KEK 密钥加密密钥(Key Encrypt Key)

2、列出这些API包含的函数,进行分类,并总结它们的异同

(1)Crypto API

  • 主要函数:

a) 主函数
void main(void)
b) 加密文件
BOOL EncryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword);
c) 解密文件
BOOL DecryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword);
d) 签名文件
BOOL SignFile (PCHAR szSource, PCHAR szDestination);
e) 验证签名
BOOL VerifyFile (PCHAR szSource, PCHAR szDestination);
f) 错误处理
void HandleError(char *s);

  • 加密文件:

a) 打开源文件
hSource = fopen(szSource,"rb")
b) 取得密钥容器(CSP)句柄
CryptAcquireContext(&hCryptProv,NULL,NULL,PROV_RSA_FULL,0)
c) 根据用户输入的密码创建一个会话密钥(即对称密钥,用于对原文件加密)
//创建一个Hash对象
CryptCreateHash(hCryptProv,CALG_MD5, 0, 0, &hHash)
//用用户输入的密码产生一个散列
CryptHashData(hHash, (BYTE *)szPassword, strlen(szPassword), 0)
//通过散列生成一个会话密钥
CryptDeriveKey(hCryptProv, ENCRYPT_ALGORITHM,hHash, KEYLENGTH, &hKey))
//销毁Hash对象
CryptDestroyHash(hHash);
注: 会话密钥即对称密钥,用于对原文件进行加密;非对称密钥由于效率非常低,所以一般不用于对数据直接加密,而是对会话密钥进行加密,然后把它传送给对方。对 方通过非对称密钥解密获得这个会话密钥,然后再对数据文件进行解密。可以看出,一个会话密钥的生存期可以限制在这次通信中,即每次通信都用不同的会话密钥 加密,而非对称密钥则必须是长期使用的。在此例中,加解密过程中没有使用到非对称 RSA密钥对,而只在数字签名及验证使用它。
d) 加密数据文件
CryptEncrypt(
hKey, //密钥
0, //如果数据同时进行散列和加密,这里传入一个散列对象
feof(hSource), //如果是最后一个被加密的块,输入TRUE.如果不是输
//入FALSE这里通过判断是否到文件尾来决定是否为最后一块
0, //保留
pbBuffer, //输入被加密数据,输出加密后的数据
&dwCount, //输入被加密数据实际长度,输出加密后数据长度
dwBufferLen) //pbBuffer的大小
注:查看完整代码时可以发现这是一个循环加密的过程,pbBuffer循环读入待加密文件的固定长度的内存块;当然你也可以将pbBuffer设得很大,一次读入整个文件,但那样浪费内存空间,而且影响扩展性(存在缓冲区溢出的可能)。
e) 清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。
if(pbBuffer)
free(pbBuffer);
if(hKey)
CryptDestroyKey(hKey);
if(hHash)
CryptDestroyHash(hHash);
if(hCryptProv)
CryptReleaseContext(hCryptProv, 0);

  • 解密文件:

a) 打开加密文件(同上)
b) 取得密钥容器(CSP)句柄(同上)
c) 根据用户输入的密码创建一个会话密钥(即对称密钥,用于对原文件解密)(同上)
注: 这里要求用户输入的密码与加密时输入的密码相同。在实际应用中,这个所谓用户输入的“密码”其实只是一个产生密钥的种子,一旦产生完会话密钥,则用户完全 可以忘记当初输入的“密码”,接收方可以使用传过来的密钥直接对加密文件进行解密,而不用再重复一次“生成密钥”的过程。
d) 解密数据文件
CryptDecrypt(
hKey, //密钥
0, //如果数据同时进行散列和加密,这里传入一个散列对象
feof(hSource), //如果是最后一个被加密的块,输入TRUE.如果不是输.
//入FALSE这里通过判断是否到文件尾来决定是否为最后一块。
0, //保留
pbBuffer, //输入被加密数据,输出加密后的数据
&dwCount)) //输入被加密数据实际长度,输出加密后数据长度
e) 清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。

  • 签名文件:

a) 打开源文件(同上)
b) 取得密钥容器(CSP)句柄(同上)
c) 取得签名用的密钥句柄(非对称RSA密钥)
CryptGetUserKey(
hCryptProv, // 我们已经得到的CSP句柄
AT_SIGNATURE, // 这里想得到signature key pair
&hKey)) // 返回密钥句柄
d) 导出签名用密钥对的公钥,保存在pbKeyBlob中
CryptExportKey(hKey, NULL,PUBLICKEYBLOB, 0, pbKeyBlob,&dwBlobLen)
e) 计算数据文件的Hash值,保存在Hash对象hHash中
//生成一个空的Hash对象
CryptCreateHash(hCryptProv,CALG_MD5,0,0,&hHash)
//计算数据文件的Hash值,保存在Hash对象中
CryptHashData(hHash,pbBuffer,dwCount,0)
f) 对数据文件的Hash值进行签名,数字签名保存在pbSignature中
CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen)
g) 清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。

  • 签名文件:

a) 打开源文件(同上)
b) 取得密钥容器(CSP)句柄(同上)
c) 取得签名用的密钥句柄(非对称RSA密钥)
CryptGetUserKey(
hCryptProv, // 我们已经得到的CSP句柄
AT_SIGNATURE, // 这里想得到signature key pair
&hKey)) // 返回密钥句柄
d) 导出签名用密钥对的公钥,保存在pbKeyBlob中
CryptExportKey(hKey, NULL,PUBLICKEYBLOB, 0, pbKeyBlob,&dwBlobLen)
e) 计算数据文件的Hash值,保存在Hash对象hHash中
//生成一个空的Hash对象
CryptCreateHash(hCryptProv,CALG_MD5,0,0,&hHash)
//计算数据文件的Hash值,保存在Hash对象中
CryptHashData(hHash,pbBuffer,dwCount,0)
f) 对数据文件的Hash值进行签名,数字签名保存在pbSignature中
CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen)
g) 清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。(同上)

  • 验证签名:

a) 打开文件(同上)
b) 取得密钥容器(CSP)句柄(同上)
c) 导入 pbKeyBlob 公钥
CryptImportKey(hCryptProv, pbKeyBlob, dwBlobLen, 0, 0, &hPubKey)
注:必须是与签名时所用的私钥配对的公钥,在此例中,这个公钥在生成数字签名时已经导出到pbKeyBlob中。
d) 计算数据文件的Hash值,保存在Hash对象hHash中。(同上)
e) 验证数字签名
CryptVerifySignature(hHash, pbSignature, dwSigLen,hPubKey,NULL, 0)
f) 清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。(同上)
(2)PKCS#11

根据机制标记,可以分为几类:
CKF_ENCRYPT:加密类
CKF_DECRYPT:解密类
CKF_DIGEST:摘要类
CKF_SIGN:签名类
CKF_SIGN_RECOVER:可恢复签名类
CKF_VERIFY:验证类
CKF_VERIFY_RECOVER:可恢复验证类
CKF_GENERATE:密钥产生
CKF_GENERATE_KEY_PAIR:密钥对产生
CKF_WRAP:密钥封装
CKF_UNWRAP:密钥解封
CKF_DERIVE:密钥派生

(3)GMT 0016-2012

(4)GMT 0018-2012

下列文件对于本文件的应用是必不可少的。凡是注日期的引用文件,仅注日期的版本适用于本文件,凡是不注日期的引用文件,其最新版本(包括所有的修单)适用于本文件,
GM/T0006 密码应用标识规范 和GM/T0009 SM2密码算法使用规范

3、以龙脉GM3000Key为例,写出调用不同接口的代码(Crypto API,PKCS#11,SKF接口),把运行截图加入博客,并提供代码链接

  • Crypto API: 对于Windows平台上的Crypto API,通常用于加密解密、签名验证等操作。
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

#include "generic.h"

bool DecryptFile(const string &strSource,
		const string &strDestination,
		const string &strPassword); 

void main(void)
{
	char szSrcFile[1024] = {0};
	char szTgtFile[1024] = {0};
	char szPassword[1024] = {0};

	printf("\nDecrypt a file.\n\nEnter the name of the file to be decrypt:\n");
	scanf("%s", szSrcFile);

	printf("Enter the name of the output file:\n");
	scanf("%s", szTgtFile);

	printf("Enter the password to encrypt the file:\n");
	scanf("%s", szPassword);

	if(DecryptFile(szSrcFile, szTgtFile, szPassword))
	{
		printf("Decrypt file successfully.\n");
	}
	else
	{
		printf("Decrypt file failed.\n");
	}
} // End of main

//--------------------------------------------------------------------
//    Define the function Decryptfile.

bool DecryptFile(const string &strSource,
		const string &strDestination,
		const string &strPassword)
{
	FILE *hSource = NULL; 
	FILE *hDestination = NULL;

	//--------------------------------------------------------------------
	// Open source file. 
	BeginAction("Open source file for read");
	if(NULL != (hSource = fopen(strSource.c_str(), "rb")))
	{
		ActionSuccess();
	}
	else
	{
		ActionFailed(GetLastError());
		return FALSE;
	}

	//--------------------------------------------------------------------
	// Open destination file. 
	BeginAction("Open target file for write");
	if(NULL != (hDestination = fopen(strDestination.c_str(), "wb")))
	{
		ActionSuccess();
	}
	else
	{
		ActionFailed(GetLastError());
		return FALSE;
	}

	HCRYPTPROV hCryptProv = NULL;
	HCRYPTKEY hKey = NULL;
	HCRYPTHASH hHash = NULL;

	//--------------------------------------------------------------------
	// Get a handle to the provider. 
	BeginAction("CryptAcquireContext()");
	if(CryptAcquireContext(&hCryptProv,
			TEST_CONTAINER,
			CSP_NAME,  
			PROV_RSA_FULL,
			0))
	{
		ActionSuccess();
	}
	else
	{
		ActionFailed(GetLastError());
		return FALSE;
	}

	HCRYPTPROV_Holder holder(hCryptProv);

	//--------------------------------------------------------------------
	// Create a hash object. 
	BeginAction("CryptCreateHash()");
	if(CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash))
	{
		ActionSuccess();
	}
	else
	{
		ActionFailed(GetLastError());
		return FALSE;
	}  
	//--------------------------------------------------------------------
	// Hash in the password data. 

	BeginAction("CryptHashData()");
	if(CryptHashData(hHash,
			(BYTE *) strPassword.c_str(),
			strPassword.length(),
			0))
	{
		ActionSuccess();
	}
	else
	{
		ActionFailed(GetLastError());
		return FALSE;
	}

	//--------------------------------------------------------------------
	// Derive a session key from the hash object. 
	BeginAction("CryptDeriveKey()");
	if(CryptDeriveKey(hCryptProv, ENCRYPT_ALGORITHM, hHash, KEYLENGTH, &hKey))
	{
		ActionSuccess();
	}
	else
	{
		ActionFailed(GetLastError());
		return FALSE;
	}

	//--------------------------------------------------------------------
	// Destroy the hash object. 
	BeginAction("CryptDestroyHash()");
	if(CryptDestroyHash(hHash))
	{
		hHash = NULL; 
		ActionSuccess();
	}
	else
	{
		ActionFailed(GetLastError());
		return FALSE;
	}

	//--------------------------------------------------------------------
	//   The decryption key is now available, either having been imported
	//   from a BLOB read in from the source file or having been created 
	//   using the password. This point in the program is not reached if 
	//   the decryption key is not available.

	//--------------------------------------------------------------------
	// Determine the number of bytes to decrypt at a time. 
	// This must be a multiple of ENCRYPT_BLOCK_SIZE. 

	DWORD dwBlockLen = 0;
	DWORD dwBufferLen = 0;
	DWORD dwCount = 0;

	dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE; 
	dwBufferLen = dwBlockLen; 

	vector<BYTE> pbBuffer;
	pbBuffer.resize(dwBufferLen);

	//--------------------------------------------------------------------
	// Decrypt source file, and write to destination file. 

	do
	{
		//--------------------------------------------------------------------
		// Read up to dwBlockLen bytes from source file. 
		dwCount = fread(&pbBuffer[0], 1, dwBlockLen, hSource); 
		if(ferror(hSource))
		{
			ShowSysError("Read cipher text", GetLastError());
			return FALSE;
		}

		//--------------------------------------------------------------------
		// Decrypt data. 
		if(!CryptDecrypt(hKey, 0, feof(hSource), 0, &pbBuffer[0], &dwCount))
		{
			ShowSysError("CryptDecrypt()", GetLastError());
			return FALSE;
		}

		//--------------------------------------------------------------------
		// Write data to destination file. 
		fwrite(&pbBuffer[0], 1, dwCount, hDestination); 
		if(ferror(hDestination))
		{
			ShowSysError("Write plain text", GetLastError());
			return FALSE;
		}
	}
	while(!feof(hSource)); 

	//--------------------------------------------------------------------
	// Close files. 
	if(hSource)
	{
		fclose(hSource);
	} 
	if(hDestination)
	{
		fclose(hDestination);
	} 

	//--------------------------------------------------------------------
	// Destroy session key. 
	if(hKey)
	{
		CryptDestroyKey(hKey);
	} 

	return TRUE;
}
  • PKCS#11: 广泛应用于智能卡和硬件安全模块(HSM)的标准接口。
    AEStest:
/*
[]=========================================================================[]

	Copyright(C) Feitian Technologies Co., Ltd.
	All rights reserved.

FILE:
	BaseAll.cpp

DESC:
	implementation of the DesTest class.
[]=========================================================================[]
*/

#include "AESTest.h"
#include "common.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

AESTest::AESTest(char* dll_file_path):CBaseAll(dll_file_path)
{
	m_hKey = 0;
}

AESTest::~AESTest()
{

}


void AESTest::Test()
{
	if(CKR_OK != BaseAllStart())
		return;
	GenerateKey();
	if(m_hKey == 0)
	{
		BaseAllEnd();
		return ;
	}
	crypt_Single();
	crypt_Update();
	BaseAllEnd();
}
void AESTest::GenerateKey()
{
	do{
		SHOW_INFO("Generate Des key to test...");
		CK_OBJECT_CLASS oClass = CKO_SECRET_KEY;
		CK_KEY_TYPE keyType = CKK_AES; 
		CK_BBOOL bTrue = true;
		CK_BBOOL bFalse = false;
		CK_ULONG ulLen = 16;
		CK_MECHANISM mechanism = {CKM_AES_KEY_GEN, NULL_PTR, 0};
		CK_ATTRIBUTE Destem[] = {
			{CKA_CLASS, &oClass, sizeof(CK_OBJECT_CLASS)},
			{CKA_KEY_TYPE, &keyType, sizeof(CK_KEY_TYPE)},
			{CKA_TOKEN, &bFalse, sizeof(CK_BBOOL)},
			{CKA_PRIVATE, &bTrue, sizeof(CK_BBOOL)},
			{CKA_ENCRYPT, &bTrue, sizeof(CK_BBOOL)},
			{CKA_DECRYPT, &bTrue, sizeof(CK_BBOOL)},
			{CKA_VALUE_LEN, &ulLen, sizeof(CK_ULONG)}, 
		};
		CK_ULONG ulCount = 7;
		//generate key:
		START_OP("generate AES key...")
			CK_RV rv =  m_gToken->C_GenerateKey(hSession, &mechanism, Destem, ulCount, &m_hKey); 
		CHECK_OP(rv)
	}while(0);
}
void AESTest::crypt_Single()
{
	const CK_ULONG DATA_LENGTH = 1024*3;
	CK_BYTE bIn[DATA_LENGTH] = {0}, bTemp[DATA_LENGTH] = {0}, bOut[DATA_LENGTH] = {0};
	CK_ULONG ulIn = 0, ulOut = 0, ulTemp = 0;
	CK_ULONG Mechanism[3] = {CKM_AES_CBC, CKM_AES_ECB, CKM_AES_CBC_PAD};
	CK_BYTE_PTR bHint[3] = {(CK_BYTE_PTR)"CKM_AES_CBC: ",\
							(CK_BYTE_PTR)"CKM_AES_ECB: ",
							(CK_BYTE_PTR)"CKM_AES_CBC_PAD: "};
	SHOW_INFO("\nAES: C_Encrypt/C_Decrypt: \n");
	for(int i=0;i<3;i++)
	{
		ulIn = 1024;
		if(i==2)//pad
			ulIn = 1000;
		for(register CK_ULONG i0 = 0;i0<ulIn;i0++)
			bIn[i0] = (CK_BYTE)i0;
		
		
		SHOW_INFO("\n*	*	*	*	*	*	*	*	*	*	*	\n");
		SHOW_INFO(bHint[i]);
		//ecnrypt init:
		CK_BYTE iv[16] = {'*','2','1','0','4','z','y','b','*','2','1','0','4','z','y','b'};
		CK_MECHANISM ckMechanism = {Mechanism[i], iv, 16};
		START_OP("Encrypting initialize.")  
		CK_RV rv =  m_gToken->C_EncryptInit(hSession, &ckMechanism, m_hKey); 
		CHECK_OP(rv)

		START_OP("Encrypt the message.")
		//Get the encrypted buffer's size:
		//{{{Here, I do not invoke "C_Encrypt" twice for I had declared bTemp with a size=1024.
		//If you do not declare the result's buffer previous,
		//you should invoke twice to get the buffer's size, such as:[Decrypt is similar]
		rv =  m_gToken->C_Encrypt(hSession, bIn, ulIn, NULL, &ulTemp);
		//}}}
		CheckRV("C_Encrypt[get buffer's size]", rv);
		//encrypt:
		rv =  m_gToken->C_Encrypt(hSession, bIn, ulIn, bTemp, &ulTemp);
		CheckRV("C_Encrypt", rv);
		CHECK_OP(rv);
		SHOW_INFO("Data encrypted: \n");
		ShowData(bTemp, ulTemp);

		START_OP("Decrypting initialize.");
		rv =  m_gToken->C_DecryptInit(hSession, &ckMechanism, m_hKey);
		CHECK_OP(rv);
		START_OP("Decrypt the message.");
		//Get buffer's size:
		rv =  m_gToken->C_Decrypt(hSession, bTemp, ulTemp, NULL, &ulOut);
		//Get decrypted data:
		rv =  m_gToken->C_Decrypt(hSession, bTemp, ulTemp, bOut, &ulOut);
		CHECK_OP(rv);
		SHOW_INFO("Data decrypted: \n");
		ShowData(bOut, ulOut);
		
		START_OP("Compare the original message and decrypted data: ");
		if(0 == memcmp(bIn, bOut, ulOut))
		{
			CHECK_OP(CKR_OK);
		}
		else
		{
			SHOW_INFO("....[FAILED]\n");
		}
	}
}

void AESTest::crypt_Update()
{
	const CK_ULONG DATA_LENGTH = 1024*3;
	CK_BYTE bIn[DATA_LENGTH] = {0}, bTemp[DATA_LENGTH] = {0}, bOut[DATA_LENGTH] = {0};
	CK_ULONG ulIn = 0, ulOut = 0, ulTemp = 0;
	CK_ULONG Mechanism[3] = {CKM_AES_CBC, CKM_AES_ECB, CKM_AES_CBC_PAD};
	CK_BYTE_PTR bHint[3] = {(CK_BYTE_PTR)"CKM_AES_CBC: ",\
									(CK_BYTE_PTR)"CKM_AES_ECB: ",\
									(CK_BYTE_PTR)"CKM_AES_CBC_PAD: "};
	SHOW_INFO("\n*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*\n");
	for(int i=0;i<3;i++)
	{
		ulIn = 1024;
		if(i == 2)
		{//PAD
			ulIn = 1000;
		}
		for(register CK_ULONG i0 = 0;i0<ulIn;i0++)
			bIn[i0] = (CK_BYTE)i0;

		SHOW_INFO("\n");
		SHOW_INFO("\nAES: C_EncryptUpdate/C_DecryptUpdate: \n");
		SHOW_INFO(bHint[i]);
		//ecnrypt init:
		CK_BYTE iv[16] = {'*','2','1','0','4','z','y','b','*','2','1','0','4','z','y','b'};
		CK_MECHANISM ckMechanism = {Mechanism[i], iv, sizeof(iv)};
		START_OP("Encrypting initialize.")  
			CK_RV rv =  m_gToken->C_EncryptInit(hSession, &ckMechanism, m_hKey); 
		CHECK_OP(rv)
		
		CK_ULONG ulEncrypted = 0;
		START_OP("Encrypt the message.");
		//invoked twice:
		const CK_ULONG ulEnc1stPice = 33;
		rv =  m_gToken->C_EncryptUpdate(hSession, bIn, ulEnc1stPice, NULL, &ulTemp);//get buffer's size.
		rv =  m_gToken->C_EncryptUpdate(hSession, bIn, ulEnc1stPice, bTemp, &ulTemp);
		//}}}
		CheckRV("C_Encrypt[get buffer's size]", rv);
		ulEncrypted+=ulTemp;
		ulTemp = 0;
		//encrypt:
		//invoked twice:
		rv =  m_gToken->C_EncryptUpdate(hSession,  &(bIn[ulEnc1stPice]), ulIn-ulEnc1stPice, NULL, &ulTemp);//get buffer's size.
		rv =  m_gToken->C_EncryptUpdate(hSession, &(bIn[ulEnc1stPice]), ulIn-ulEnc1stPice, &(bTemp[ulEncrypted]), &ulTemp);
		CheckRV("C_Encrypt", rv);
		CHECK_OP(rv);
		ulEncrypted+=ulTemp;
		ulTemp = 0;
		START_OP("C_EncryptFinal...");
		rv = m_gToken->C_EncryptFinal(hSession, NULL, &ulTemp);//Get buffer's size:
		rv = m_gToken->C_EncryptFinal(hSession, &(bTemp[ulEncrypted]), &ulTemp);
		CHECK_OP(rv);
		ulEncrypted+=ulTemp;
		ulTemp = 0;
		SHOW_INFO("Data encrypted: \n");
		ShowData(bTemp, ulEncrypted);
		 
		START_OP("Decrypting initialize.");
		rv =  m_gToken->C_DecryptInit(hSession, &ckMechanism, m_hKey);
		CHECK_OP(rv);
		START_OP("Decrypt the message.");
		
		CK_ULONG ulDecrypt = 0;
		const CK_ULONG ulDec1stPice = 17;
		rv =  m_gToken->C_DecryptUpdate(hSession, bTemp, ulDec1stPice, NULL, &ulOut);//Get buffer's size
		rv =  m_gToken->C_DecryptUpdate(hSession, bTemp, ulDec1stPice, bOut, &ulOut);
		ulDecrypt +=ulOut;
		ulOut = 0;
		//Get decrypted data:
		rv =  m_gToken->C_DecryptUpdate(hSession, &(bTemp[ulDec1stPice]), ulEncrypted-ulDec1stPice, NULL, &ulOut);//Get buffer's size
		rv =  m_gToken->C_DecryptUpdate(hSession, &(bTemp[ulDec1stPice]), ulEncrypted-ulDec1stPice, &(bOut[ulDecrypt]), &ulOut);
		CHECK_OP(rv);
		ulDecrypt +=ulOut;
		ulOut = 0;
		START_OP("C_DecryptFinale...");
		rv = m_gToken->C_DecryptFinal(hSession, NULL, &ulOut);//Get buffer's size
		rv = m_gToken->C_DecryptFinal(hSession, &(bOut[ulDecrypt]), &ulOut);
		CHECK_OP(rv);
		ulDecrypt +=ulOut;
		
		SHOW_INFO("Data decrypted: \n");
		ShowData(bOut, ulDecrypt);
		
		START_OP("Compare the original message and decrypted data: ");
		if(0 == memcmp(bIn, bOut, ulDecrypt))
		{
			CHECK_OP(CKR_OK);
		}
		else
		{
			SHOW_INFO("....[FAILED]\n");
		}
	}
}

RSAtest

/*
[]=========================================================================[]

	Copyright(C) Feitian Technologies Co., Ltd.
	All rights reserved.

FILE:
	rsatest.cpp

DESC:
	implementation of the RSATest class.
[]=========================================================================[]
*/

#include "RSATest.h"
#include "common.h"
RSATest::RSATest(char* dll_file_path):CBaseAll(dll_file_path)
{
}

RSATest::~RSATest()
{
}

void RSATest::RsaKeyGenerationTest(void)
{
	if(CKR_OK != BaseAllStart())
		return;
	
	SHOW_INFO("\n\nThe next demo will generate a RSA key pair on UsbToken.")
	CK_RV rv = CKR_OK;
	CK_BBOOL bTrue = TRUE;
	CK_ULONG ulModulusBits = MODULUS_BIT_LENGTH;
	CK_BYTE subject[] = "Sample RSA Key Pair";
	CK_ULONG keyType = CKK_RSA;
	
	CK_OBJECT_HANDLE hPubKey = 0;
	CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
	CK_ATTRIBUTE pubTemplate[] =
	{ 
		{CKA_CLASS,			&pubClass,		sizeof(pubClass)},
		{CKA_KEY_TYPE,		&keyType,		sizeof(keyType)},
		{CKA_SUBJECT,		subject,		sizeof(subject)},
		{CKA_MODULUS_BITS,	&ulModulusBits, sizeof(ulModulusBits)},
		{CKA_ENCRYPT,		&bTrue,			sizeof(bTrue)},
		{CKA_TOKEN,			&bTrue,			sizeof(bTrue)},
		{CKA_WRAP,			&bTrue,			sizeof(bTrue)},
	};	
	CK_OBJECT_HANDLE hPriKey		= 0;
	CK_OBJECT_CLASS priClass	= CKO_PRIVATE_KEY;
	CK_ATTRIBUTE priTemplate[] = {
		{CKA_CLASS,			&priClass,	sizeof(priClass)},
		{CKA_KEY_TYPE,		&keyType,	sizeof(keyType)},
		{CKA_SUBJECT,		subject,	sizeof(subject)},
		{CKA_DECRYPT,		&bTrue,		sizeof(bTrue)},
		{CKA_PRIVATE,		&bTrue,		sizeof(bTrue)},
		{CKA_SENSITIVE,		&bTrue,		sizeof(bTrue)},
		{CKA_TOKEN,			&bTrue,		sizeof(bTrue)},
		{CKA_EXTRACTABLE,	&bTrue,		sizeof(bTrue)},
		{CKA_UNWRAP,		&bTrue,		sizeof(bTrue)},
	};
    CK_MECHANISM keyGenMechanism = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0};
	CK_MECHANISM ckMechanism = {CKM_RSA_PKCS, NULL_PTR, 0};
	CK_BYTE pbMsg[] = "UsbToken RunRsaKeyGenerationTest...";
	CK_ULONG ulMsgLen = strlen((const char *)pbMsg);
	CK_BYTE bSignatureBuffer[MODULUS_BIT_LENGTH] = {0};
	CK_ULONG ulSignatureLen = 0;
	CK_BYTE_PTR pbCipherBuffer = NULL;
	CK_ULONG ulCipherLen = 0;
	CK_BYTE_PTR pbRestoredMsg = NULL;
	CK_ULONG ulRestoredMsgLen = 0;
	
	do {
		START_OP("Generating public/private key pair...");
		rv =  m_gToken->C_GenerateKeyPair(hSession, &keyGenMechanism,
								   pubTemplate, countof(pubTemplate),
								   priTemplate, countof(priTemplate),
								   &hPubKey, &hPriKey);
		CHECK_OP(rv)
			
    	// Try Sign and Verify operations with the key pair.
		// Sign a message. 
		SHOW_INFO("\nThe message to be signed is \"")
		ShowData(pbMsg, ulMsgLen);
		
		ulSignatureLen	= sizeof(bSignatureBuffer);
		START_OP("Signing initialize.");
		rv =  m_gToken->C_SignInit(hSession, &ckMechanism, hPriKey);
		CHECK_OP(rv);
		
		START_OP("Sign the message.")
		rv =  m_gToken->C_Sign(hSession, 
							pbMsg,
							ulMsgLen, 
							bSignatureBuffer, &ulSignatureLen);
		CHECK_OP(rv)
		SHOW_INFO("\nSignature is:\n");	
		ShowData(bSignatureBuffer, ulSignatureLen);

		// Verify the previously signed message.
		START_OP("Verifying initialize.")
		rv =  m_gToken->C_VerifyInit(hSession, &ckMechanism, hPubKey);
		CHECK_OP(rv)
			
		START_OP("Verify the message.")
		rv =  m_gToken->C_Verify(hSession, 
									pbMsg, ulMsgLen, 
									bSignatureBuffer, ulSignatureLen);
		CHECK_OP(rv)
			
		// Encrypt a message. 
		SHOW_INFO("\nThe message to be Encrypt is: ")
		ShowData(pbMsg, ulMsgLen);
		
		START_OP("Encrypting initialize.")
			rv =  m_gToken->C_EncryptInit(hSession,
											&ckMechanism,
											hPubKey);
		CHECK_OP(rv)
			
		START_OP("Obtain the size of the encrypted message....")
		rv =  m_gToken->C_Encrypt(hSession, pbMsg, ulMsgLen, NULL_PTR, &ulCipherLen);
		CHECK_OP(rv)
			
		START_OP("Allocate buffer for the encrypted message.")
		pbCipherBuffer = (CK_BYTE_PTR)malloc(ulCipherLen);
		if (! pbCipherBuffer)
			CHECK_OP(CKR_HOST_MEMORY)
		else
			CHECK_OP(CKR_OK);
		
		START_OP("Encrypt the message....");
		memset(pbCipherBuffer, 0, ulCipherLen);
		rv =  m_gToken->C_Encrypt(hSession, pbMsg, ulMsgLen, 
											pbCipherBuffer, &ulCipherLen);
		CHECK_OP(rv);
		SHOW_INFO("Data encrypted: ");
		ShowData(pbCipherBuffer, ulCipherLen);
		
		START_OP("Decrypting initialize....")
		rv =  m_gToken->C_DecryptInit(hSession,
										&ckMechanism,
										hPriKey);
		CHECK_OP(rv)
			
			START_OP("Obtain the size of the decrypted message....")
			rv =  m_gToken->C_Decrypt(hSession, pbCipherBuffer, 
										ulCipherLen, NULL_PTR, &ulRestoredMsgLen);
		CHECK_OP(rv)
		START_OP("Allocate buffer for the decrypted message.")
		pbRestoredMsg = (CK_BYTE_PTR)malloc(ulRestoredMsgLen + 1);
		if (! pbRestoredMsg)
			CHECK_OP(CKR_HOST_MEMORY)
			else
			CHECK_OP(CKR_OK);
		memset(pbRestoredMsg, 0, ulRestoredMsgLen + 1);
		
		START_OP("Decrypt the message.")
		rv =  m_gToken->C_Decrypt(hSession, pbCipherBuffer, ulCipherLen, 
									pbRestoredMsg, &ulRestoredMsgLen);
		CHECK_OP(rv)
			
		// Decrypt a message. 
		SHOW_INFO("\nThe message decrypted is \n")
		ShowData(pbRestoredMsg, ulRestoredMsgLen);
		
		START_OP("Verify the message.");
		if(0 == memcmp(pbMsg, pbRestoredMsg, ulRestoredMsgLen))
			CHECK_OP(CKR_OK)
		else
			SHOW_INFO("....[FAILED]\n")
			
		// Remove the RSA key pair from the UsbToken.
		START_OP("Proceed to remove the RSA key pair from the token.");
		rv =  m_gToken->C_DestroyObject(hSession, hPubKey);
		CHECK_OP(rv);
		
		START_OP("Remove private key obeject.");
		rv =  m_gToken->C_DestroyObject(hSession, hPriKey);
		CHECK_OP(rv);
		
		START_OP("Logout normally...")
			rv = m_gToken->C_Logout(hSession);
		CHECK_OP(rv);
	}while (0);
		
		// Release the memory.
		if(pbCipherBuffer)
		{
			free(pbCipherBuffer);
			pbCipherBuffer = NULL;
		}
		if(pbRestoredMsg)
		{
			free(pbRestoredMsg);
			pbCipherBuffer = NULL;
		}
		BaseAllEnd();
}
``
DEStest

/*
[]=========================================================================[]

Copyright(C) Feitian Technologies Co., Ltd.
All rights reserved.

FILE:
BaseAll.cpp

DESC:
implementation of the DesTest class.
[]=========================================================================[]
*/

include "DesTest.h"

include "common.h"

DesTest::DesTest(char* dll_file_path):CBaseAll(dll_file_path)
{
m_hKey = 0;
}

DesTest::~DesTest()
{
}

void DesTest::Test()
{
if(CKR_OK != BaseAllStart())
return;
GenerateKey();
if(m_hKey == 0)
{
BaseAllEnd();
return ;
}
crypt_Single();
crypt_Update();
BaseAllEnd();
}
void DesTest::GenerateKey()
{
do{
SHOW_INFO("Generate Des key to test...");
CK_OBJECT_CLASS oClass = CKO_SECRET_KEY;
CK_KEY_TYPE keyType = CKK_DES;
CK_BBOOL bTrue = true;
CK_BBOOL bFalse = false;
CK_ULONG ulLen = 8;
CK_MECHANISM mechanism = {CKM_DES_KEY_GEN, NULL_PTR, 0};
CK_ATTRIBUTE Destem[] = {
{CKA_CLASS, &oClass, sizeof(CK_OBJECT_CLASS)},
{CKA_KEY_TYPE, &keyType, sizeof(CK_KEY_TYPE)},
{CKA_TOKEN, &bFalse, sizeof(CK_BBOOL)},
{CKA_PRIVATE, &bTrue, sizeof(CK_BBOOL)},
{CKA_ENCRYPT, &bTrue, sizeof(CK_BBOOL)},
{CKA_DECRYPT, &bTrue, sizeof(CK_BBOOL)},
{CKA_VALUE_LEN, &ulLen, sizeof(CK_ULONG)},
};
CK_ULONG ulCount = 7;
//generate key:
START_OP("generate DES key...")
CK_RV rv = m_gToken->C_GenerateKey(hSession, &mechanism, Destem, ulCount, &m_hKey);
CHECK_OP(rv)
}while(0);
}
void DesTest::crypt_Single()
{
const CK_ULONG DATA_LENGTH = 1024*3;
CK_BYTE bIn[DATA_LENGTH] = {0}, bTemp[DATA_LENGTH] = {0}, bOut[DATA_LENGTH] = {0};
CK_ULONG ulIn = 0, ulOut = 0, ulTemp = 0;
CK_ULONG Mechanism[3] = {CKM_DES_CBC, CKM_DES_ECB, CKM_DES_CBC_PAD};
CK_BYTE_PTR bHint[3] = {(CK_BYTE_PTR)"CKM_DES_CBC: ",
(CK_BYTE_PTR)"CKM_DES_ECB: ",
(CK_BYTE_PTR)"CKM_DES_CBC_PAD: "};
SHOW_INFO("\nDES: C_Encrypt/C_Decrypt: \n");
for(int i=0;i<3;i++)
{
ulIn = 1000;
if(i==2)
ulIn = 1000;
for(register CK_ULONG i0 = 0;i0<ulIn;i0++)
bIn[i0] = (CK_BYTE)i0;

	SHOW_INFO("\n*	*	*	*	*	*	*	*	*	*	*	\n");
	SHOW_INFO(bHint[i]);
	//ecnrypt init:
	CK_BYTE iv[8] = {'*','2','1','0','4','z','y','b'};
	CK_MECHANISM ckMechanism = {Mechanism[i], iv, 8};
	START_OP("Encrypting initialize.")  
	CK_RV rv =  m_gToken->C_EncryptInit(hSession, &ckMechanism, m_hKey); 
	CHECK_OP(rv)

	START_OP("Encrypt the message.")
	//Get the encrypted buffer's size:
	//{{{Here, I do not invoke "C_Encrypt" twice for I had declared bTemp with a size=1024.
	//If you do not declare the result's buffer previous,
	//you should invoke twice to get the buffer's size, such as:[Decrypt is similar]
	rv =  m_gToken->C_Encrypt(hSession, bIn, ulIn, NULL, &ulTemp);
	//}}}
	CheckRV("C_Encrypt[get buffer's size]", rv);
	//encrypt:
	rv =  m_gToken->C_Encrypt(hSession, bIn, ulIn, bTemp, &ulTemp);
	CheckRV("C_Encrypt", rv);
	CHECK_OP(rv);
	SHOW_INFO("Data encrypted: \n");
	ShowData(bTemp, ulTemp);

	START_OP("Decrypting initialize.");
	rv =  m_gToken->C_DecryptInit(hSession, &ckMechanism, m_hKey);
	CHECK_OP(rv);
	START_OP("Decrypt the message.");
	//Get buffer's size:
	rv =  m_gToken->C_Decrypt(hSession, bTemp, ulTemp, NULL, &ulOut);
	//Get decrypted data:
	rv =  m_gToken->C_Decrypt(hSession, bTemp, ulTemp, bOut, &ulOut);
	CHECK_OP(rv);
	SHOW_INFO("Data decrypted: \n");
	ShowData(bOut, ulOut);
	
	START_OP("Compare the original message and decrypted data: ");
	if(0 == memcmp(bIn, bOut, ulOut))
	{
		CHECK_OP(CKR_OK);
	}
	else
	{
		SHOW_INFO("....[FAILED]\n");
	}
}

}

void DesTest::crypt_Update()
{
const CK_ULONG DATA_LENGTH = 10243;
CK_BYTE bIn[DATA_LENGTH] = {0}, bTemp[DATA_LENGTH] = {0}, bOut[DATA_LENGTH] = {0};
CK_ULONG ulIn = 0, ulOut = 0, ulTemp = 0;
CK_ULONG Mechanism[3] = {CKM_DES_CBC, CKM_DES_ECB, CKM_DES_CBC_PAD};
CK_BYTE_PTR bHint[3] = {(CK_BYTE_PTR)"CKM_DES_CBC: ",
(CK_BYTE_PTR)"CKM_DES_ECB: ",
(CK_BYTE_PTR)"CKM_DES_CBC_PAD: "};
SHOW_INFO("\n
* * * * * * * * * * * * * * *\n");
for(int i=0;i<3;i++)
{
ulIn = 1000;
if(i == 2)
{//CKM_RC2_CBC_PAD
ulIn = 0xF1;
}
for(register CK_ULONG i0 = 0;i0<ulIn;i0++)
bIn[i0] = (CK_BYTE)i0;

	SHOW_INFO("\n");
	SHOW_INFO("\nDES: C_EncryptUpdate/C_DecryptUpdate: \n");
	SHOW_INFO(bHint[i]);
	//ecnrypt init:
	CK_BYTE iv[8] = {'*','2','1','0','4','z','y','b'};
	CK_MECHANISM ckMechanism = {Mechanism[i], iv, sizeof(iv)};
	START_OP("Encrypting initialize.")  
		CK_RV rv =  m_gToken->C_EncryptInit(hSession, &ckMechanism, m_hKey); 
	CHECK_OP(rv)
	
	CK_ULONG ulEncrypted = 0;
	START_OP("Encrypt the message.");
	//invoked twice:
	const CK_ULONG ulEnc1stPice = 33;
	rv =  m_gToken->C_EncryptUpdate(hSession, bIn, ulEnc1stPice, NULL, &ulTemp);//get buffer's size.
	rv =  m_gToken->C_EncryptUpdate(hSession, bIn, ulEnc1stPice, bTemp, &ulTemp);
	//}}}
	CheckRV("C_Encrypt[get buffer's size]", rv);
	ulEncrypted+=ulTemp;
	ulTemp = 0;
	//encrypt:
	//invoked twice:
	rv =  m_gToken->C_EncryptUpdate(hSession,  &(bIn[ulEnc1stPice]), ulIn-ulEnc1stPice, NULL, &ulTemp);//get buffer's size.
	rv =  m_gToken->C_EncryptUpdate(hSession, &(bIn[ulEnc1stPice]), ulIn-ulEnc1stPice, &(bTemp[ulEncrypted]), &ulTemp);
	CheckRV("C_Encrypt", rv);
	CHECK_OP(rv);
	ulEncrypted+=ulTemp;
	ulTemp = 0;
	START_OP("C_EncryptFinal...");
	rv = m_gToken->C_EncryptFinal(hSession, NULL, &ulTemp);
	rv = m_gToken->C_EncryptFinal(hSession, &(bTemp[ulEncrypted]), &ulTemp);
	CHECK_OP(rv);
	ulEncrypted+=ulTemp;
	ulTemp = 0;
	SHOW_INFO("Data encrypted: \n");
	ShowData(bTemp, ulEncrypted);
	 
	START_OP("Decrypting initialize.");
	rv =  m_gToken->C_DecryptInit(hSession, &ckMechanism, m_hKey);
	CHECK_OP(rv);
	START_OP("Decrypt the message.");
	//Get buffer's size:
	CK_ULONG ulDecrypt = 0;
	const CK_ULONG ulDec1stPice = 11;
	rv =  m_gToken->C_DecryptUpdate(hSession, bTemp, ulDec1stPice, NULL, &ulOut);
	rv =  m_gToken->C_DecryptUpdate(hSession, bTemp, ulDec1stPice, bOut, &ulOut);
	ulDecrypt +=ulOut;
	ulOut = 0;
	//Get decrypted data:
	rv =  m_gToken->C_DecryptUpdate(hSession, &(bTemp[ulDec1stPice]), ulEncrypted-ulDec1stPice, NULL, &ulOut);
	rv =  m_gToken->C_DecryptUpdate(hSession, &(bTemp[ulDec1stPice]), ulEncrypted-ulDec1stPice, &(bOut[ulDecrypt]), &ulOut);
	CHECK_OP(rv);
	ulDecrypt +=ulOut;
	ulOut = 0;
	START_OP("C_DecryptFinale...");
	rv = m_gToken->C_DecryptFinal(hSession, NULL, &ulOut);
	rv = m_gToken->C_DecryptFinal(hSession, &(bOut[ulDecrypt]), &ulOut);
	CHECK_OP(rv);
	ulDecrypt +=ulOut;
	
	SHOW_INFO("Data decrypted: \n");
	ShowData(bOut, ulDecrypt);
	
	START_OP("Compare the original message and decrypted data: ");
	if(0 == memcmp(bIn, bOut, ulDecrypt))
	{
		CHECK_OP(CKR_OK);
	}
	else
	{
		SHOW_INFO("....[FAILED]\n");
	}
}

}

![](/i/l/?n=24&i=blog/2554135/202404/2554135-20240414151118431-876228705.png)
![](/i/l/?n=24&i=blog/2554135/202404/2554135-20240414151857127-1829955113.png)
![](/i/l/?n=24&i=blog/2554135/202404/2554135-20240414151924125-1895640334.png)
![](/i/l/?n=24&i=blog/2554135/202404/2554135-20240414151956996-966096746.png)

标签:CK,rv,加密,引擎,hSession,密钥,API,OP
From: https://www.cnblogs.com/lizhuotong/p/18120765

相关文章

  • TextIn.com API使用心得
    我们参加了本次大学生创新创业服务外包大赛,在项目中大量使用到了合合信息所提供的api进行相关功能实现,所以在这里写一篇博客分享一下我们在项目的实际推进中关于TextIn.comAPI使用心得我们的产品是一款面向公司管理的REP微信小程序,由于需要覆盖大部分的企业办公需求,我们使用到了......
  • 10-接口测试工具(PostMan和ApiPost)
    在前后端分离的开发模式下,通常需要使用接口测试工具进行开发,这里介绍两种比较好用的1)PostManPostman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件,常用于接口测试官方下载网址:DownloadPostman|GetStartedforFree安装教程:PostMan——安装使用教程(图文详解)_po......
  • FastAPI-MySQL-Cookie代码实现
    连接数据库fromsqlalchemyimportcreate_enginefromsqlalchemy.ext.declarativeimportdeclarative_basefromsqlalchemy.ormimportsessionmakerfromurllib.parseimportquote_pluspassword='123456'encoded_password=quote_plus(password)SQLALCHEM......
  • 实验一-密码引擎-3-加密API研究
    任务要求密码引擎API的主要标准和规范包括:1微软的CryptoAPI2RAS公司的PKCS#11标准3中国商用密码标准:GMT0016-2012智能密码钥匙密码应用接口规范,GMT0018-2012密码设备应用接口规范等研究以上API接口,总结他们的异同,并以龙脉GM3000Key为例,写出调用不同接口的代码,提交博客......
  • 密码引擎-加密API研究
    任务详细密码引擎API的主要标准和规范包括:1微软的CryptoAPI2RAS公司的PKCS#11标准3中国商用密码标准:GMT0016-2012智能密码钥匙密码应用接口规范,GMT0018-2012密码设备应用接口规范等研究以上API接口,总结他们的异同,并以龙脉GM3000Key为例,写出调用不同接口的代码,提交......
  • 实验一-密码引擎-3-加密API研究
    一、微软的CryptoAPI参考网站:https://learn.microsoft.com/zh-cn/windows/win32/seccrypto/cryptoapi-system-architecturehttps://developer.mozilla.org/zh-CN/docs/Web/API/Web_Crypto_APIhttps://www.w3.org/TR/2017/REC-WebCryptoAPI-20170126/https://blog.csdn.net/l......
  • 02_Web Api使用Jwt
    JWT(JSONWebToken)是一种用于在网络应用之间传递信息的开放标准(RFC7519)。它使用JSON对象在安全可靠的方式下传递信息,通常用于身份验证和信息交换。在WebAPI中,JWT通常用于对用户进行身份验证和授权。当用户登录成功后,服务器会生成一个Token并返回给客户端,客户端在接下来的请求......
  • 国密 SM2 的非对称加密解密过程
    国密SM2的非对称加密解密过程椭圆曲线椭圆曲线是由一组方程描述的点的集合:y2=x3+ax+b其中a,b满足(4a3+27b2≠0)SM2定义了一个sm2p256v1的椭圆曲线方程各种参数BigIntegerp=FromHex("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFF......
  • 云场景下的代理重加密 Proxy Re-Encryption
    目录主页引言代理重加密代理重加密关键流程实践&应用总结参考资料主页个人微信公众号:密码应用技术实战个人博客园首页:https://www.cnblogs.com/informatics/引言2022年12月,人工智能迎来了一件大事,OpenAI的ChatGPT横空诞生,成为了现象级产品。如果说算力是人工智能的发动机,那......
  • php rsa长文加密解密
    密钥类型:1024bit:分段加密字节数为117,分段解密字节数为128。2048bit:分段加密字节数为245,分段解密字节数为256。 classRsaBill{private$public_key_resource;private$private_key_resource;publicfunction__construct(){$this->public_key......