实验一-密码引擎-加密API研究
实验一-密码引擎-加密API研究
API:应用程序接口(API:Application Program Interface)是一组定义、程序及协议的集合,通过 API 接口实现计算机软件之间的相互通信。API 的一个主要功能是提供通用功能集。程序员通过使用 API 函数开发应用程序,从而可以避免编写无用程序,以减轻编程任务。
密码引擎API的主要标准和规范包括:
1 微软的Crypto API
2 RAS公司的PKCS#11标准
3 中国商用密码标准:GMT 0016-2012 智能密码钥匙密码应用接口规范,GMT 0018-2012密码设备应用接口规范等
0 、查找各种标准的原始文档,研究学习(至少包含Crypto API,PKCS#11,GMT 0016-2012,GMT 0018-2012)
(1)Crypto API:
作为一部分 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标准定义了与密码令牌(如硬件安全模块(HSM)和智能卡)的独立于平台的API,并将API本身命名为“Cryptoki”(来自“加密令牌接口”,发音为“crypto-key” - 但是“PKCS#11”通常用于指代API以及定义它的标准)。 API定义了最常用的加密对像类型(RSA密钥,X.509证书,DES / 三重DES密钥等)以及使用,创建/生成,修改和删除这些对象所需的所有功能。
在密码系统中,PKCS#11是公钥加密标准(PKCS, Public-Key Cryptography Standards)中的一份子 ,由RSA实验室(RSA Laboratories)发布[1],它为加密令牌定义了一组平台无关的API ,如硬件安全模块和智能卡。
由于没有一个真正的标准加密令牌,这个API已经发展成为一个通用的加密令牌的抽象层。 PKCS#11 API定义最常用的加密对象类型( RSA密钥,X.509证书,DES /三重DES密钥等)和所有需要使用的功能,创建/生成,修改和删除这些对象。注意:pkcs#11只提供了接口的定义, 不包括接口的实现,一般接口的实现是由设备提供商提供的,如usbkey的生产厂商会提供 符合PKCS#11接口标准的API的实现。这样你只要通过接口调用API函数即可实现其功能。
(3)GMT 0016-2012:
本标准规定了基于PKI密码体制的智能密码钥匙密码应用接口,描述了密码应用接口的函数、数据类型、参数的定义和设备的安全要求。
本标准适用于智能密码钥匙产品的研制、使用和检测。
(4)GMT 0018-2012:
本标准规定了公钥密码基础设施应用技术体系下服务类密码设备的应用接口标准,
本标准适用于服务类密码设备的研制使用,以及基于该类密码设备的应用开发,也可用于指导该类密码设备的检测
1、总结这些API在编程中的使用方式
(1)Crypto API
使用CryptoAPI编写一个文件保护程序,具有如下功能:
(1)给定明文文件,生成加密文件,同时产生文件的数字签名文件;
(2)给定密文文件,解密出明文文件,并验证签名的正确性。
在不安全的网络上进行安全的数据传输涉及三个方面的要求:信息隐藏,身份鉴别和完整性检验。CryptoAPI除了提供上述三个功能外还提供标准的ASN.1编码、解码,信息解密,数字证书和证书存储区的管理,证书信任列表、吊销列表和证书有效性检查等功能。
信息隐藏
信息隐藏也称作数据隐藏(Data+Hiding),是集多学科理论与技术于一身的新兴技术领域。信息隐藏技术主要是指将特定的信息嵌入数字化宿主信息(如文本,数字化的声音、图像、视频信号等)中,信息隐藏的目的不在于限制正常的信息存取和访问,而在于保证隐藏的信息不引起监控者的注意和重视,从而减少被攻击的可能性,在此基础上再使用密码术来加强隐藏信息的安全性,因此信息隐藏比信息加密更为安全。应该注意到,密码术和信息隐藏技术不是互相矛盾、互相竞争的技术,而是相互补充的技术,他们的区别在于应用的场合不同,对算法的要求不同,但可能在实际应用中需要互相配合。特定的信息一般就是保密信息,信息隐藏的历史可以追溯到古老的隐写术,但推动了信息隐藏的理论和技术研究始于1996年在剑桥大学召开的国际第一届信息隐藏研究会,之后国际机构在信息隐藏领域中的隐写术、数字水印、版权标识,可视密码学等方面取得大量成果。
身份鉴别
标识是实体身份的一种计算机表达。
信息系统在执行操作时,首先要求用户标识自己的身份,并提供证明自己身份的依据,不同的系统使用不同的方式表示实体的身份,同一实体可以有多个不同的身份。
鉴别是将标识和实体联系在一起的过程。鉴别是信息系统的第一道安全防线,也为其他安全服务提供支撑。访问控制机制的正确执行依赖于对用户身份的正确识别,标识和鉴别作为访问控制的必要支持,以实现对资源机密性、完整性、可用性及合法使用的支持。如果与数据完整性机制结合起来使用,可以作为数据源认证的一种方法。
身份鉴别包括单向鉴别、双向鉴别以及第三方鉴别。
在一个给定的网络中,客户A需要访问服务器S的服务,客户A必须被服务器鉴别,这个鉴别过程称为单向鉴别。如果客户A也需要鉴别服务器S,则称为双向鉴别。还有一些情况要求由双方信任的第三方进行鉴别,以确认用户和服务器的身份。
单向鉴别是当用户希望在应用服务器上注册时,用户仅需被应用服务器鉴别。常见的单向鉴别是用户发送其用户名和口令给应用服务器,应用服务器收到的用户名和口令进行验证,确认用户名和口令是由合法用户发出。
双向鉴别是一种相互鉴别,其过程在单向鉴别的基础上还要增加两个步骤:服务器向客户端发送服务器名和口令,客户端确认服务器身份的合法性。这种基于口令的双向鉴别一般不常使用,假如有50个用户(或应用服务器),每个用户若均可与其它用户通信,则每个用户都应有能力鉴别其他用户。在双向鉴别的情况下,还应能被其它用户鉴别,这样每个用户需要保存49个口令。一旦用户增加、减少或改变口令,都要调整口令清单,管理繁琐且效率低。
第三方鉴别是基于可信的第三方存储验证标识和鉴别信息。每个用户或应用服务器都向可信第三方发送身份标识和口令,提高了口令存储和使用的安全性,并且具有较高的效率。
完整性检测
任何通过不安全介质传输的信息都可以被意外或蓄意的修改。在现实世界中,盖章、签名就是用来提供和证明信息完整性的工具。
信息的接收者不但需要确定信息是由谁发送的,还要确定自己收到的信息是发送者发送的信息,而没有任何的变化。要建立数据的完整性检测机制,不仅要发送信息本身,还要发送用来校验数据的信息,这一信息通常被称作哈希值。数据和验证信息都可以与数字签名一起发送来证明其完整性。
(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句柄等。(同上)
(4)GMT 0018-2012
下列文件对于本文件的应用是必不可少的。凡是注日期的引用文件,仅注日期的版本适用于本文件,凡是不注日期的引用文件,其最新版本(包括所有的修单)适用于本文件,
GM/T0006 密码应用标识规范 和GM/T0009 SM2密码算法使用规范
- 设备信息定义
字段名称 | 数据长度(字节) | 含 义 |
---|---|---|
IssuerName | 40 | 设备生产厂商名称 |
DeviceName | 设备型号 | |
DeviceSerial | 设备编打期阳牙符)、批次号(3字符)、流水号 (5字符) | |
Device Version | 密码设备内部软件的版本号 | |
Standard Version | 4 | 密码设备支持的接口规范版本号 |
AsymAlgAbility | 8 | 前4字节表示支持的算法,表示方法为非对称算法标识按 位或的结果;后4字节表示算法的最大模长,表示方法为 支持的模长按位或的结果 |
SymAlgAbility | 4 | 所有支持的对称算法,表示方法为对称算法标识按位或 运算结果 |
HashAlgAbility | 4 | 所有支持的杂凑算法,表示方法为杂凑算法标识按位或 运算结果 |
BufferSize | 4 | 支持的最大文件存储空间(单位字节) |
- 实际数据结构定义
typedef struct Devicelnfo_st{
unsigned char IssuerName[40]; unsigned char DeviceName[16]; unsigned char DeviceSerial[16]; unsigned int DeviceVersion; unsigned int StandardVersion ; unsigned int AsymAlgAbility[2]; unsigned int SymAlgAbility; unsigned int HashAlgAbility ; unsigned int BufferSize
) DEVICEINFO;
RSA密钥结构定义
RSA密钥结构存储时顺序为从高到低,即密钥存放时从密钥结构数组的最高位开始,最高字节填在最高位,不足位填充数据0。
- 公钥数据结构定义
字段名称 | 数据长度(字节) | 含义 |
---|---|---|
bits | 4 | 模长 |
M | 256 | 模N |
E | 256 | 公钥指数 |
私钥数据结构定义 | ||
字段名称 | 数据长度 | 含义 |
bits | 4 | 模长 |
M | 256 | 模N |
E | 256 | 公钥指数 |
D | 256 | 私钥指数 |
prime[2] | 128X2 | 素数P和q |
pexp[2] | 128X2 | Dp 和 Dq |
coef | 128 | 系数i |
- 实际数据结构定义
# define RSAref_MAX_BITS 2048 | ||
---|---|---|
# define RSAref_MAX_LEN ((RSAref_MAX.BITS +7)/8) | ||
井 define RSAref_MAX_PBITS ((RSAref_MAX_BITS +1)/2) | ||
# define RSAref_MAX_PLEN ((RSAref_MAX_PBITS + 7)/ 8) | ||
typedef struct RSArefPublicKey_st | ||
unsigned int bits;
unsigned char m[RSAref_MAX_LEN];
unsigned char e[RSAref_MAX_LEN];
} RSArefPublicKey ;
typedef struct RSArefPrivateKey_st
{
unsigned int bits;
unsigned char m[RSAref_MAX_LEN];
unsigned char e[RSAref_MAX_LEN];
unsigned char d[RSAref_MAX_LEN];
unsigned char prime[2][RSAref_MAX_PLEN];
unsigned char pexp[2][RSAref_MAX_PLEN]; unsigned char coef[RSAref_MAX_PLEN];
} RSArefPrivateKey ;
- ECC密钥数据结构定义
公钥数据结构定义
字段名称 | 数据长度(字节) | 含义 |
---|---|---|
bits | 4 | 密钥位长 |
X | ECCre£_MAX_LEN | 公钥X坐标 |
y | ECCref_MAX_LEN | 公钥V坐标 |
私钥数据结构定义 | ||
字段名称 | 数据长度(字节) | 含义 |
bits | 4 | 密钥位长 |
K | ECCref_MAX_LEN | 私钥 |
- ECC加密数据结构定义
加密数据结构定义 | ||
---|---|---|
字段名称 | 数据长度(字节) | 含义 |
X | ECCref_MAX_LENP | X分量 |
V | ECCref_MAX_LEN | Y分量 |
M | 32 | 明文的杂凑值 |
L | 4 | 密文数据长度 |
C | L | 密文数据 |
- 数据项描述
数据项 | 类型 | 意义 | 备注 |
---|---|---|---|
ulAsymmAlgID | unsigned long | 保护对称密钥的非对称算法标识 | |
ulSymmAlgID | unsigned long | 对称算法标识 | 必须为ECB模式 |
ECCCipherBlob | ECCCIPHERBLOB | 对称密钥密文 | |
PubKey | ECCPUBLICKEYBLOB | 加密密钥对的公钥 | |
cbEncryptedPrivKey | 无符号数组 | 加密密钥对的私钥密文,其有效 长度为原文的(ulBits + 7)/8 | 私钥原文为ECCPRI- VATEKEYBLOB 结构中 的 PrivateKey |
3、以龙脉GM3000Key为例,写出调用不同接口的代码(Crypto API,PKCS#11,SKF接口),把运行截图加入博客,并提供代码链接
(1)PKCS#11
g++ -o gettokeninfo main.cpp -L./ -lgm3000_pkcs11 -Wl,-rpath .
这里由于动态库出现版本不符合的问题,建议将makefile以及.cpp文件中的x86改为x64。
(2)skf
(3)csp