加密API研究

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

(1)CryptoAPI

Crypto 接口提供了当前上下文中可用的基本的加密功能。它允许访问一个密码学安全的随机数生成器和密码学原语(cryptographic primitive)。Web Crypto API 可以通过 crypto 属性(一个 Crypto 对象)来访问。有些浏览器实现了叫作 Crypto 的接口,但是它缺乏良好的定义,或在密码学上是不健全的。为了避免混乱,这个接口的方法和属性已经被实现 Web Crypto API 的浏览器所移除,并且所有的 Web Crypto API 方法都可以在新的接口中使用:SubtleCryptoCrypto.subtle 属性可以获取到一个实现了新接口的对象。

(2)PKCS#11

PKCS#11是公钥加密标准Public-Key Cryptography Standards中的一份子,由RSA实验室发布。PKCS#11标准定义了与密码令牌的独立于平台的API,API本身命名为Cryptoki,这个API已经发展成为一个通用的加密令牌的抽象层,主要是应用于智能卡和HSM。PKCS#11为使用加密Token的应用程序提供统一的编程接口,独立于设备,屏蔽加密设备的复杂性,应用程序可以方便地更换设备。

(3) 中国商用密码标准

1 总结这些API在编程中的使用方式(5分)

(1) CryptoAPI

CryptoAPI (Cryptography API) 是微软提供的一套加密服务接口,用于在Windows操作系统上实现加密和解密功能。

使用方式

  • 初始化:在开始使用CryptoAPI之前,需要调用相关函数进行初始化。
  • 创建密钥对:使用CryptoAPI的函数可以生成公钥和私钥对。
  • 加密和解密:CryptoAPI提供了一系列函数用于数据加密和解密。
  • 数字签名和验证:可以使用CryptoAPI进行数字签名和验证,确保数据的完整性和真实性。
  • 证书管理:CryptoAPI还支持证书管理,包括证书的创建、导入、导出和验证。

(2)PKCS#11

PKCS#11 (Public-Key Cryptography Standards #11) 是一个定义加密令牌的接口标准,这些令牌可能包括硬件安全模块(HSM)或其他加密设备。

使用方式

  • 加载库:编程时需要加载PKCS#11库,这通常涉及到动态链接库(DLL)或共享对象(SO)的加载。
  • 初始化:使用PKCS#11函数进行初始化,包括创建会话和连接到加密令牌。
  • 操作令牌:通过PKCS#11接口,可以执行诸如生成密钥对、加密解密、签名验证等操作。
  • 管理对象:PKCS#11也提供了管理存储在令牌上的对象(如证书、密钥等)的功能。

(3)GMT 0016-2012

使用方式

  • 了解标准内容:首先,需要了解它规定的加密算法、协议、接口等。
  • 选择或使用库:根据标准内容,选择或使用符合该标准的密码库。
  • 编程实现:在编程时,按照标准的要求调用相应的库函数或API,实现加密、解密、签名等操作。

(4) GMT 0018-2012

使用方式

  • 阅读和理解标准:首先,阅读标准,理解其规定的算法、协议等。
  • 选择或开发实现:根据标准内容,选择已有的密码库或自行开发实现符合该标准的代码。
  • 集成到应用中:将实现的密码功能集成到具体的应用程序中,按照标准的要求调用相应的函数或API。

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

(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密码算法使用规范













异同总结

相同点

  • 这些接口或标准都是为了实现密码学相关的功能,如加密、解密、签名、验证等。
  • 它们都提供了对密钥的管理和操作功能。
  • 在某些情况下,它们可能使用或支持相同的加密算法。

不同点

  • 适用范围:CryptoAPI主要适用于Windows操作系统;PKCS#11则是一个跨平台的接口标准,适用于各种加密令牌和硬件安全模块;GMT 0016-2012和GMT 0018-2012是中国国家密码管理局发布的密码标准或规范,适用于特定的密码应用场景。
  • 功能重点:CryptoAPI和GMT系列标准可能更侧重于特定算法的实现和应用;而PKCS#11则更侧重于与加密令牌的交互和管理。
  • 实现方式:这些接口或标准的实现方式可能有所不同,例如CryptoAPI是微软提供的API集合,而PKCS#11则通过动态链接库或共享对象与加密令牌进行交互。GMT系列标准则可能需要开发者根据标准内容进行具体的实现。

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

代码链接:https://gitee.com/kcf03/gm3000

(1)Crypto API

加密结果:

(2)PCKS#11

a.DES

b.DES3


c.RC2

d.RC4

e.RSA

f.AES

(3)SKF

posted @ 2024-04-10 13:05  20211113  阅读(58)  评论(0)    收藏  举报