国密SKF库调用开发指南(二)

在这里插入图片描述
四、对称加解密

一次完整对称加解密分为三个步骤:密钥交换、加密及解密,这样才能做到密钥不直接传递,并且一次一密。

首先是数据传输双方进行密钥交换。

1.SKF_GenerateAgreementDataWithECC(HCONTAINER hContainer, ULONG ulAlgId,ECCPUBLICKEYBLOB* pTempECCPubKeyBlob,BYTE* pbID, ULONG ulIDLen,HANDLE *phAgreementHandle);

传输的发起方调用此方法进行密钥协商,为计算会话密钥而产生协商参数,返回临时密钥对的公钥及协商句柄。hContainer是容器句柄,任何有公私钥对的容器均可;ulAlgId是会话密钥算法标识,比如SGD_SMS4_ECB(0x00000401)即SM4算法ECB模式; pTempECCPubKeyBlob返回的发起方临时公钥,此数据要传递给响应方; pbID是发起方的ID,这个ID可根据实际情况设置;ulIDLen是发起方ID的长度,不大于32;phAgreementHandle为返回的密钥协商句柄,备用。

2.SKF_GenerateAgreementDataAndKeyWithECC(HANDLE hContainer, ULONG ulAlgId,ECCPUBLICKEYBLOB* pSponsorECCPubKeyBlob,ECCPUBLICKEYBLOB* pSponsorTempECCPubKeyBlob,ECCPUBLICKEYBLOB* pTempECCPubKeyBlob,BYTE* pbID, ULONG ulIDLen, BYTE *pbSponsorID, ULONG ulSponsorIDLen,HANDLE *phKeyHandle);

传输的响应方调用此方法,进行密钥协商,产生协商参数并计算会话密钥,输出临时密钥对公钥,并返回产生的密钥句柄。hContainer是容器句柄;ulAlgId 是会话密钥算法标识,这里要和上一个方法里设置的算法标识一致;pSponsorECCPubKeyBlob是发起方的公钥,这个公钥是发起方所使用容器里的公钥,可以采用SKF_ImportCertificate和SKF_ExportPublicKey方法从发起方的证书里获得;pSponsorTempECCPubKeyBlob为发起方的临时公钥;pTempECCPubKeyBlob返回响应方的临时公钥;pbID是响应方的ID;ulIDLen是响应方ID的长度,不大于32;pbSponsorID是发起方的ID;ulSponsorIDLen是发起方ID的长度,不大于32;phKeyHandle返回的对称算法密钥句柄。这样,响应方率先拿到了密钥句柄。

3.SKF_GenerateKeyWithECC(HANDLE hAgreementHandle, ECCPUBLICKEYBLOB* pECCPubKeyBlob, ECCPUBLICKEYBLOB* pTempECCPubKeyBlob, BYTE* pbID, ULONG ulIDLen, HANDLE *phKeyHandle);

接下来发起方调用此方法,使用自身协商句柄和响应方的协商参数计算会话密钥,同时返回会话密钥句柄。hAgreementHandle是第1步返回的密钥协商句柄;pECCPubKeyBlob是响应方的公钥,即响应方所使用容器里的公钥;pTempECCPubKeyBlob是响应方的临时公钥;pbID 为响应方的ID;ulIDLen是响应方ID的长度,不大于32;phKeyHandle是返回的密钥句柄。

传输双方完成了密钥的协商和交换过程,现在双方都有同样的密钥,可以进行加密传输了。

上述密钥交换的过程适用于加密的数据需实时解密的场景,如加密数据在网络传输。如果不需要实时解密,比如加密的数据保存在数据库,以后查询时再解密,那就无法使用密钥交换的方式确定密钥。这时可以使用下面的方法,通过给定的值产生对称密钥。

SKF_SetSymmKey(DEVHANDLE hDev, BYTE* pbKey, ULONG ulAlgID, HANDLE* phKey);

hDev是设备句柄;pbKey是输入的密钥值;ulAlgID 是会话密钥的算法标识;phKey 是返回的密钥句柄。这样,加解密双方可以通过输入同样的pbKey产生相同的密钥,进行加解密。当然,这种方法安全性较低,在国密标准里并不推荐使用。

4.SKF_EncryptInit(HANDLE hKey, BLOCKCIPHERPARAM EncryptParam)

此方法进行数据加密初始化,并设置数据加密的算法相关参数。hKey是加密密钥句柄;EncryptParam是分组密码算法相关参数,包括初始向量、初始向量长度、填充方法、和反馈值的位长度。如果采用CBC模式,就需要设置初始向量等参数。

5.SKF_Encrypt(HANDLE hKey, BYTE * pbData, ULONG ulDataLen, BYTE *pbEncryptedData, ULONG *pulEncryptedLen);

调用此方法进行数据的加密操作,hKey为加密密钥句柄;pbData是待加密数据;ulDataLen是待加密数据长度;pbEncryptedData返回加密后的数据;pulEncryptedLen输入时表示预设的加密后数据长度;输出时表示返回加密后的数据实际长度。可以将pbEncryptedData设置为NULL,得到加密数据实际长度后,再做第二次调用;也可以预先判断返回的加密数据长度(在待加密数据长度和加密算法已知情况下),给pbEncryptedData分配好长度空间,一次调用。

和杂凑运算类似,上述加密方法只适用于单组数据,如果是分组数据,则需要使用下列方法:

SKF_EncryptUpdate(HANDLE hKey, BYTE * pbData, ULONG ulDataLen, BYTE *pbEncryptedData, ULONG *pulEncryptedLen);

SKF_EncryptFinal(HANDLE hKey, BYTE *pbEncryptedData, ULONG *ulEncryptedDataLen);

对于每一组数据使用SKF_EncryptUpdate加密,最后调用SKF_EncryptFinal返回最终的加密数据。可以看出,和杂凑不同,对一个分组数据的加密结果可单独得到。

解密

6.SKF_DecryptInit(HANDLE hKey, BLOCKCIPHERPARAM DecryptParam);

调用此方法数据解密初始化并设置解密密钥相关参数。两个参数的意义用法与SKF_EncryptInit一致。

7.SKF_Decrypt(HANDLE hKey, BYTE * pbEncryptedData, ULONG ulEncryptedLen, BYTE * pbData, ULONG * pulDataLen);

调用此方法进行数据的解密操作。hKey为解密密钥句柄; pbEncryptedData是待解密数据;ulEncryptedLen是待解密数据长度;pbData返回解密后的数据;pulDataLen是解密后的数据实际长度。可以将pbData设置为NULL,得到解密数据实际长度后,再做第二次调用;也可以预先判断返回的解密数据长度(在待解密数据长度和加密算法已知情况下),给pbData分配好长度空间,一次调用。

同样,对于分组加密结果的解密,应使用下列方法:

SKF_DecryptUpdate(HANDLE hKey, BYTE * pbEncryptedData, ULONG ulEncryptedLen, BYTE * pbData, ULONG * pulDataLen);

SKF_DecryptFinal(HANDLE hKey, BYTE *pbDecryptedData, ULONG *pulDecryptedDataLen);

对于每一组数据使用DecryptUpdate解密,最后调用SKF_ DecryptFinal返回最终的解密数据。

五、非对称加解密

SKF里的非对称加解密有两种模式:一种是对会话密钥进行加解密,一种是使用外部导入的公私钥进行加解密。很明显,第一种就是我们之前说的数字信封:只对会话密钥进行非对称加解密,用会话密钥对原文进行对称加解密。

1.SKF_ECCExportSessionKey(HCONTAINER hContainer, ULONG ulAlgId, ECCPUBLICKEYBLOB *pPubKey, PECCCIPHERBLOB pData, HANDLE *phSessionKey);

加密方调用此方法生成会话密钥并用外部公钥加密输出。hContainer是容器句柄;ulAlgID 是会话密钥的算法标识;pPubKey是用来加密的外部公钥(这个当然是解密方的加密公钥);pbData返回会话密钥密文;phSessionKey是返回的会话密钥句柄。然后加密方就可以用会话密钥对数据进行加密了,调用方法在对称加解密已经介绍过,此处不再介绍。

2.SKF_ImportSessionKey(HCONTAINER hContainer, ULONG ulAlgId,BYTE *pbWrapedData,ULONG ulWrapedLen,HANDLE *phKey);

解密方调用此方法导入会话密钥密文,并使用容器内的加密私钥解密得到会话密钥。hContainer是加密私钥所在容器句柄;ulAlgID 是会话密钥的算法标识;pbWrapedData 要导入的密文数据;ulWrapedLen密文数据长度;phKey返回会话密钥句柄。之后便可以用会话密钥句柄对加密的数据进行解密了。

至于另外一种方式,使用的是下面两个方法:

SKF_ExtECCEncrypt(DEVHANDLE hDev, ECCPUBLICKEYBLOB* pECCPubKeyBlob,BYTE* pbPlainText, ULONG ulPlainTextLen, PECCCIPHERBLOB pCipherText);

SKF_ExtECCDecrypt(DEVHANDLE hDev, ECCPRIVATEKEYBLOB* pECCPriKeyBlob, PECCCIPHERBLOB pCipherText, BYTE* pbPlainText, ULONG* pulPlainTextLen);

这种方式实际用的很少,也不是国密标准推荐的方式,这里就不详细介绍,有兴趣的同学可以自行参看标准。

六、杂凑运算

在介绍数字签名时已经包含杂凑运算相关SKF API的调用方法,代码就不再贴了。这里着重要说明的是,数字签名里的杂凑运算,按照国密标准要进行SM2算法签名预处理,即SKF_DigestInit方法 的ulAlgID、pPubKey、pucID和ulIDLen都有传值要求。因此,如果只是进行纯粹的SM3杂凑运算,则这个方法的ulAlgID参数应是SGD_SM3,pPubKey和pucID是NULL,ulIDLen是0。

上面就介绍了使用国密SKF库进行几项主要密码功能运算的方法,希望能够帮助到大家。

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_45303938

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值