20201321周慧琳

密码引擎

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

任务详情

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

0.研究学习原始文档

CryptoAPI

https://learn.microsoft.com/en-us/windows/win32/seccrypto/cryptography-portal

https://learn.microsoft.com/en-us/windows/win32/seccrypto/cryptography-portal

https://learn.microsoft.com/en-us/windows/win32/seccrypto/cryptographic-provider-types

https://learn.microsoft.com/en-us/windows/win32/seccrypto/microsoft-cryptographic-service-providers

PKCS#11

PKCS#11 v2.20

GM/T 0016-2012 智能密码钥匙密码应用接口规范

GM/T 0018-2012 密码设备应用接口规范

密码行业标准列表

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

CryptoAPI
微软的CryptoAPI是PKI推荐使用的加密 API。其功能是为应用程序开发者提供在Win32环境下使用加密、验证等安全服务时的标准加密接口。CryptoAPI处于应用程序和CSP(cryptographic service provider)之间。

Cryptoki 为一个或多个密码设备提供一个接口,这些设备通过大量的槽在系统中运行。每个对应于一个物理阅读器或另一个设备接口的槽可包含一个令牌。当一台密码设备存在于阅读器中,一个令牌就存在于该槽中。当然,由于Cryptoki提供槽和令牌的逻辑视图,所以可能有其它的物理译码。多个槽可能共享一个阅读器。问题在于一个系统有相当多的槽,应用程序能连接到这些槽的其中任何一个或全部槽的令牌上。

Cryptoki的令牌逻辑视图是一个能存储对象和能执行密码函数的设备。Cryptoki定义如下三个对象:数据、证书和密钥。数据对象由应用程序定义。一个证书对象存储一个证书。一个密钥对象存储一个密码密钥。密钥可以是一个公共密钥、一个私钥或是一个保密密钥,每个种类的密钥在专用机制中使用其的辅助型。令牌的这种逻辑视图如下图所示:

SKF

针对支持国密算法USB KEY设备的应用,我国颁布一个行业标准《智能密码钥匙应用接口规范》(GM/T0016-2012),市面上销售的国密算法的USB KEY设备必须支持这个接口规范。因此,只要根据这个规范开发的应用程序,就可以兼容使用不同厂家及品牌的USB KEY产品。由于此规范中函数名称都以SKF开头,所以我们一般把按照此规范提供的设备开发接口库叫做SKF库或SKF接口。

智能密码钥匙密码应用接口位于智能密码钥匙应用程序与设备之间,如下图所示

一个设备中存在设备认证密钥和多个应用,应用之间相互独立。设备的逻辑结构如下图所示

应用由管理员PIN,用户PIN、文件和容器组成,可以存在多个文件和多个容器。每个应用维护各自的与管理员PIN和用户PIN相关的权限状态。
一个应用的逻辑结构如下图所示

容器中存放加密密钥对、签名密钥对和会话密钥。其中加密密钥对用于保护会话密钥,签名密钥对用于数字签名和验证,会话密钥用于数据加解密和MAC运算。容器中也可以存放与加密密钥对对应的加密数字证书和与签名密钥对对应的签名数字证书。其中,签名密钥对由内部产生,加密密钥对由外部产生并安全导入,会话密钥可由内部产生或者由外部产生并安全导入。

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

CryptoAPI

密码服务提供者CSP函数

CryptoAPI的密码服务提供者函数主要包括6个函数。连接或断开CSP函数CryptAcquireContext、CryptReleaseContext,枚举CSP函数CryptEnumProviders,获得或设置默认CSP函数CryptGetDefaultProvider、CryptSetProvider,获取或设置CSP参数函数CryptGetProvParam、CryptSetProvParam。

连接CSP函数 CryptAcquireContext

函数功能:连接CSP,获得指定CSP的密钥容器的句柄。

枚举CSP函数 CryptEnumProviders
函数功能:枚举计算机上的所有CSP。此函数可以得到第一个或下一个可用的CSP。如果循环调用可以得到计算机上所有可用的CSP。

获得默认CSP函数 CryptGetDefaultProvider

函数功能:获得系统默认的CSP。

设置默认CSP函数 CryptSetProvider

函数功能:设置系统默认的CSP。

获得CSP参数属性函数 CryptGetProvParam

函数功能:获得CSP各种参数属性。

设置CSP参数函数 CryptSetProvParam

函数功能:设置CSP各种参数属性。

断开CSP函数 CryptReleaseContext
函数功能:断开CSP,释放CSP句柄,和 CryptAcquireContext相对应。

示例枚举CSP并获得默认CSP的参数处理过程如下图所示

密钥的产生与交换函数

CryptoAPI密钥产生和交换函数主要有生成密钥函数 CryptGenKey、派生密钥函数CryptDeriveKey、销毁密钥函数CryptDestoryKey、复制密钥函数CryptDuplicateKey、导出密钥函数CryptExportKey、导入密钥函数CryptImportKey、获得密钥参数函数CryptGetKeyParam、设置密钥参数函数CryptSetKeyParam、产生随机函数 CryptGenRandom。

生成函数 CryptGenKey
函数功能:产生一个随机的对称或非对称算法的密钥。

派生密钥函数 CryptDeriveKey
函数功能:根据基础数据派生一对称密钥(会话密钥)。

销毁密钥函数 CryptDestroyKey

函数功能:销毁密钥。

复制密钥函数 CryptDuplicateKey
函数功能:复制一个密钥。产生一个密钥的拷贝,包括其状态。

导出密钥函数 CryptExportKey

函数功能:从CSP导出密钥或密钥对。

导入密钥函数 CryptlmportKey
函数功能:把BLOB数据导入的CSP。该函数可以导入会话密钥、公钥、或者公/私钥对。

获得密钥参数函数 CryptGetKeyParam

函数功能:获得key句柄的各项参数。

获得密钥参数函数 CryptSetKeyParam

函数功能:设置key句柄的各项参数。

获得密钥参数函数 CryptGenRandom

函数功能:生成随机数。

示例密钥产生和交换实例处理过程如下图所示

数据的加密与解密函数

CryptoAPI利用CryptEncrypt函数实现数据加密,利用CryptDecrypt实现数据解密。调用这2个函数前必须指定一个密钥,这个密钥可以由CryptGenKey、CryptDeriveKey或CryptImportKey产生。也可用CryptSetKeyParam函数指定额外的加密参数。

数据加密函数 CryptEncrypt
函数功能:使用hKey指定的密钥和算法加密数据。
数据解密函数 CryptDecrypt
函数功能:使用hKey指定的密钥和算法对加密数据解密。
示例数据加密处理过程如下图所示


示例数据解密处理过程如下图所示

哈希和数字签名函数

CryptoAPI提供的哈希和数字签名函数包括创建哈希函数CryptCreateHash、销毁哈希CryptDestroyHash、复制哈希函数CryptDuplicateHash、获得哈希参数函数CryptGetHashParam,设置哈希参数函数CryptSetHashParam、哈希会话密钥函数 CryptHashSessionKey、哈希数据函数CryptHashData、对哈希签名函数CryptSignHash和对哈希验证签名函数CryptVerifySignature。

创建哈希函数 CryptCreateHash

函数功能:创建哈希。

销毁哈希 CryptDestroyHash

函数功能:销毁哈希对象。

复制哈希函数 CryptDuplicateHash

函数功能:复制一个哈希对象。

获得哈希参数函数 CryptGetHashParam

函数功能:获得哈希对象的参数。

设置哈希参数函数 CryptSetHashParam

函数功能:设置哈希对象的参数。

哈希会话密钥函数 CryptHashSessionKey
函数功能:对一个会话密钥进行哈希,把它加到指定的哈希对象中。

哈希数据函数 CryptHashData
函数功能:对数据进行哈希操作,此函数可以反复调用。

对哈希签名函数 CryptSignHash

函数功能:对哈希对象进行签名。

对哈希验证签名函数 CryptVerifySignature

函数功能:验证哈希签名。

示例对数据签名和验证的流程如下图所示

证书和证书库函数

CryptoAPI证书和证书库函数主要包括打开证书库函数CertOpenStore、关闭证书库函数CertCloseStore、从证书库枚举证书函数CertEnumCertificatesInStore、从证书库查找证书函数CertFindCertificateInStore、创建证书句柄函数 CertCreateCertificateContext、释放证书句柄函数CertFreeCertificateContext、获得证书句柄属性函数CertGetCertificateContextProperty、设置证书句柄属性函数CertSetCertificateContextProperty和获得证书主题名称函数CertGetNameString。

打开证书库函数 CertOpenStore

函数功能:根据证书库类型,打开证书库。

关闭证书库函数 CertCloseStore

函数功能:关闭证书库。

从证书库枚举证书函数 CertEnumCertificateslnStore
函数功能:枚举证书库中的证书。该函数通过循环调用,可以枚举证书库内的全部证书,上一次的返回,是下一次的pPrevCertContext,直到返回值为NULL。

从证书库查找证书函数 CertFindCertificatelnStore

函数功能:从证书库中查找指定的证书。

创建证书句柄函数 CertCreateCertificateContext

函数功能:由证书数据创建证书句柄。

释放证书句柄函数 CertFreeCertificateContext

函数功能:释放证书句柄。

获得证书句柄属性函数 CertGetCertificateContextProperty

函数功能:获得证书句柄属性。

设置证书句柄属性函数 CertSetCertificateContextProperty

函数功能:设置证书句柄属性。

获得证书主题名称函数 CertGetNameString

函数功能:从证书中获得主题或颁发者的名称。

示例枚举证书库并输出其属性的处理流程如下图所示

SKF

设备管理函数

访问控制函数


应用管理函数

文件管理函数

容器管理函数

得到国密证书

根据国密标准,一种设备类型可以有多个设备(Device),每一个设备内可以有多个应用(Application),每一个应用里可以有多个容器(Container),每个容器里可以有一对证书(Certificate):签名证书和加密证书。

数字签名

在数字签名时,要指定签名所使用的证书。通过遍历本机上的证书,与签名用的证书进行对比,定位到签名证书在USBKEY中的位置,得到设备、应用和容器的句柄,然后使用证书的私钥进行签名。遍历对比的过程可参见上一节的内容。另外,由于数字签名会用到私钥,因此这里需要验证口令。

验证签名

1.SKF_CreateContainer(HAPPLICATION hApplication, LPSTR szContainerName, HCONTAINER *phContainer)

调用此方法创建一个临时容器。hApplication为容器所在的应用句柄;szContainerName是ASCII字符串,表示所建立容器的名称,最大长度不能超过64字节;phContainer是返回所建立容器的容器句柄。

2.SKF_ImportCertificate(HCONTAINER hContainer, BOOL bSignFlag, BYTE* pbCert, ULONG ulCertLen);

将签名用的证书导入到容器中。hContainer为容器句柄,即用上一方法创建的临时容器;bSignFlag为证书类型,TRUE表示签名证书,FALSE表示加密证书,这里选TRUE;pbCert,是证书数据;ulCertLen为证书数据长度;

3.SKF_ExportPublicKey(HCONTAINER hContainer, BOOL bSignFlag, BYTE* pbBlob, ULONG* pulBlobLen);

导出公钥。

4.SKF_DigestInit(DEVHANDLE hDev, ULONG ulAlgID, ECCPUBLICKEYBLOB *pPubKey, unsigned char *pucID, ULONG ulIDLen, HANDLE *phHash);

杂凑初始化。

5.SKF_Digest(HANDLE hHash, BYTE *pbData, ULONG ulDataLen, BYTE *pbHashData, ULONG *pulHashLen);

杂凑运算。

6.SKF_ECCVerify(DEVHANDLE hDev , ECCPUBLICKEYBLOB* pECCPubKeyBlob, BYTE *pbData, ULONG ulDataLen, PECCSIGNATUREBLOB pSignature);

进行签名验证。hDev是设备句柄;pECCPubKeyBlob是公钥数据结构,即第3步得到的公钥; pbData为待验证签名的数据;ulDataLen是待验证签名数据长度;pbSignature待验证的签名值。

7.SKF_DeleteContainer(HAPPLICATION hApplication, LPSTR szContainerName);

删除临时容器。hApplication为容器所在的应用句柄;szContainerName为容器名称。

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

CryptoAPI

需要使用x64编译

EncryptDecryptFile

EncrypteFile

DecryptFile


原始C文件和加密后二进制文件和解密出来的文件

EnumCerts

枚举证书

Sign_Verify

PKCS#11

需要使用win32编译

EnumObj


这里登入显示需要输入PIN码,但其实输入Key的密钥就行了。

exportcert


这里登入显示需要输入PIN码,但其实输入Key的密钥就行了。

public key object

代码链接

https://gitee.com/xieyi23333/information_security_xieyi/tree/master/GM3000Key

GetUSBInfos


可以看到正确显示了key的信息

PKCSDemo


RSA Sign

posted on 2023-04-04 10:43  20201321周慧琳  阅读(52)  评论(0编辑  收藏  举报