主页
微信公众号:密码应用技术实战
博客园首页:https://www.cnblogs.com/informatics/
GIT地址:https://github.com/warm3snow
本文组织
- 简介:现代密码学应用背景
- 密码技术应用体系
- 加密硬件
- 加密软件
- 密钥体系
- 关键密码接口
- 总结
- 参考资料
简介
现代密码学应用:现代密码学是信息安全领域的重要分支,主要研究数据加密、身份认证、数据完整性保护等安全技术。现代密码学应用广泛,涉及网络通信、电子商务、金融支付、物联网、云计算等多个领域,是信息安全的基础和核心技术。由于密码技术实现极为复杂、并且安全性要求较高,因此需要专门的密码产品和密码服务来支持其应用。
在《一文入门现代密码学》中,我们已经介绍了现代密码学的基础知识和发展历程,本文将进一步介绍现代密码学的应用技术体系,希望帮助大家在选择密码产品或密码库时提供一些参考。
密码技术应用体系
通过总结当前主流的软硬件加密产品、密码库在实际产品中的应用,密码技术应用体系如下:
- 密码技术应用主要有两种方式:加密硬件、加密软件
- 加密硬件包含多类密码产品:密码芯片、密码卡、智能密码钥匙、密码机以及KMS密码系统等。加密硬件一般遵循密码接口规范,为上层提供基本的密码运算功能。
- 加密软件主要包含两类实现:开源密码库和开发语言安全库,加密软件运行在CPU处理器上,不需要特殊的硬件支持;并且加密软件根据自己的开发语言分别提供不同的SDK。
- 不管是加密硬件还是加密软件,都提供了丰富的基础密码功能,如:随机数生成、密钥生成、加解密、签名验证以及哈希摘要等
- 由于硬件产品的特殊性,一般会提供额外的设备访问、会话管理等功能。
加密硬件和加密软件对比如下:
对比项目 | 加密软件 | 加密硬件 |
---|---|---|
特点 | 灵活,易更新,成本低,操作方便 | 性能优,安全强,专用性高,可靠 |
性能 | 依赖 CPU,加密慢,多任务弱 | 专用芯片,加密快,多任务强 |
安全性 | 易受软件攻击,代码易被分析 | 抗攻击,密钥管理安全 |
密钥保护 | 存储易受威胁,管理复杂 | 硬件存储安全,管理简单 |
应用场景 | 个人、小型企业一般加密需求 | 金融、政府等高标准场景 |
部署难度 | 安装配置简单 | 需专业人员物理安装 |
可扩展性 | 软件升级扩展,有性能局限 | 增加模块扩展,成本高 |
加密硬件
加密硬件也被成为密码设备,包含众多的密码产品,如:密码芯片、密码卡、密码机、密码钥匙以及密码系统等。
加密硬件介绍
- 密码芯片是一种专门用于密码运算的集成电路芯片。它集成了加密算法、密钥管理、随机数生成等功能模块,能够为各种设备提供安全的密码服务。其体积小、功耗低、集成度高,广泛应用于智能卡、物联网设备、移动终端等领域,为数据的保密性、完整性和真实性提供基础保障。
- 密码卡
密码卡是一种基于 PCIe 接口的密码设备。它将密码芯片集成在 PCIe 卡上,通过 PCIe 接口与计算机或服务器进行高速数据传输。这种卡可以提供强大的密码运算能力,支持多种加密算法和密钥管理功能,适用于对性能要求较高的服务器、数据中心等环境,可用于加密存储、网络通信加密等应用场景。 - 密码机
密码机是一种专门设计用于实现密码功能的设备,通常由硬件、软件和固件组成。它可以独立完成数据的加密、解密、签名、验证等操作,具备强大的密码运算能力和密钥管理系统。密码机一般应用于金融、政府、军队等对信息安全要求极高的领域,为关键业务系统提供安全可靠的密码服务。 - 智能密码钥匙
智能密码钥匙是一种小型的、便携式的密码设备,通常采用 USB 接口与计算机或其他设备连接。它内置密码芯片,具有存储密钥、执行密码运算等功能。用户可以通过智能密码钥匙进行身份认证、数据加密等操作,其安全性高、便于携带,常用于网上银行、电子政务等领域,保障用户的身份安全和数据安全。 - 密钥管理系统(KMS):
KMS(Key Management System)是一种用于管理密钥生命周期的系统,涵盖了密钥的生成、存储、分发、更新、撤销等环节。它通过一套安全的策略和机制,确保密钥在整个生命周期内的保密性、完整性和可用性。密钥管理系统是保障密码体系安全运行的核心,它与各种密码设备和应用系统紧密配合,为其提供密钥支持和管理服务。
加密硬件设备具有如下关系:
graph TD; subgraph "密码芯片" cryptoChip[密码芯片] algo[加密算法模块] keyMgmt[密钥管理模块] randGen[随机数生成模块] algo --> cryptoChip keyMgmt --> cryptoChip randGen --> cryptoChip end subgraph "密码卡" pcieCard[基于 PCIe 接口的密码卡] cryptoChip --> pcieCard end subgraph "密码机" cryptoMachine[密码机] hardware[硬件] software[软件] firmware[固件] hardware --> cryptoMachine software --> cryptoMachine firmware --> cryptoMachine end subgraph "智能密码钥匙" usbKey[智能密码钥匙(USB 接口)] cryptoChip --> usbKey end pcieCard --> cryptoMachine usbKey --> cryptoMachine- 密码芯片是基础:是其他密码设备的核心组成部分,为密码卡、密码钥匙等提供基本的密码运算能力。没有密码芯片,这些设备就无法实现加密、解密等安全功能。
- 密码卡和密码钥匙是基于密码芯片的应用产品:它们以不同的形态呈现,满足不同用户和应用场景的需求。密码卡可以是插入式的智能卡,用于特定设备或系统的身份认证和数据加密;密码钥匙则以 USB 接口的形式为主,方便用户随身携带和使用。
- 密码机是更强大的密码处理设备:相较于密码卡和密码钥匙,密码机具有更高的性能和处理能力,能够满足大规模数据加密和复杂安全应用的需求。它可以与多个密码卡、密码钥匙或其他设备进行交互,为整个系统提供集中的密码服务。
- 密钥管理系统是核心支撑:确保密钥的安全生成、存储和分发,并对外提供基本的密码运算能力,一般需要结合加密硬件,并提供集群式加密设备的管理、安全的密钥生命周期管理等。
密码接口规范
加密硬件与上层业务的对接,需要遵循一定的密码接口规范,以确保设备之间的兼容性和安全性。
常见的密码接口规范有:PKCS#11、SDF/SKF、KMIP等。
对比项目 | SDF | SKF | PKCS11 | KMIP |
---|---|---|---|---|
定义 | 《密码设备应用接口规范》基于国密算法,针对服务器密码机等设备的应用接口规范,规定了密钥操作、加密解密等函数原型与参数 | 《智能密码钥匙密码应用接口规范》国密标准中智能密码钥匙的C语言应用开发接口标准,涵盖设备管理、密钥容器管理等功能接口 | 《PKCS#11 Cryptographic Token Interface规范》国际通用的加密设备接口标准,定义了与加密设备交互的函数,用于密钥管理、密码运算等 | 《The Key Management Interoperability Protocol 》用于管理密钥的接口,包含密钥创建、使用、管理等功能定义,常用于规范密钥管理系统 |
区别 | 面向高性能密码设备,侧重大量数据处理与复杂密钥管理 | 针对智能密码钥匙,通过容器管理密钥,有两级认证机制 | 通用标准,不依赖特定设备,灵活性高,可与多种硬件和软件模块配合 | 依赖云服务提供商,侧重云环境下密钥集中管理及与云服务集成 |
应用场景 | 金融、政府等对数据安全要求极高的核心业务系统,保障敏感数据安全 | 电子政务、CA认证等领域,用于身份认证、数字签名等操作 | 企业级加密应用系统,与不同厂商加密设备集成实现统一密钥管理 | 云服务平台上的应用,为云应用提供密钥管理与数据加密服务 |
特点 | 安全性高,性能强,支持国密算法,设备兼容性相对弱 | 统一接口,支持国密算法,不同厂商实现有差异,可移植性受限 | 通用性和扩展性好,适配多种设备和算法,特定场景性能可能受限 | 与云服务深度集成,提供丰富密钥管理功能,KMS API在实现时可遵循KMIP标准 |
PKCS#11接口
PKCS#11是一种国际通用密码设备接口标准,定义了密码设备与应用程序之间的通信接口。它包括一系列的函数和数据结构,用于实现密码设备的初始化、密钥管理、加密、解密等操作。PKCS#11接口广泛应用于密码卡、密码机等密码设备,为应用程序提供了统一的密码服务接口。
示例:
// 初始化 PKCS11 库,设置初始参数
CK_RV C_Initialize(CK_VOID_PTR pInitArgs);
// 获取系统中所有可用的插槽列表,可选择仅获取有令牌(如智能卡)插入的插槽
CK_RV C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount);
// 在指定的插槽上打开一个会话,用于后续的密码操作
CK_RV C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession);
// 在指定的会话中,根据给定的机制和模板生成密钥
CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_CLASS keyType, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey);
// 在指定会话中生成随机数
CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, unsigned char* randomData, CK_ULONG dataLength);
// 参数:hSession 为会话句柄,randomData 用于存储生成的随机数,dataLength 是要生成的随机数长度
// 返回值:成功返回 `CKR_OK`,失败返回其他错误码
// 使用指定会话进行对称加密
CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, const unsigned char* plaintext, CK_ULONG plaintextLength,
unsigned char* ciphertext, CK_ULONG_PTR ciphertextLength);
// 参数:hSession 为会话句柄,plaintext 是待加密的明文,plaintextLength 是明文长度,
// ciphertext 用于存储加密后的密文,ciphertextLength 指向存储密文实际长度的变量
// 返回值:成功返回 `CKR_OK`,失败返回其他错误码
// 使用指定会话进行对称解密
CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, const unsigned char* ciphertext, CK_ULONG ciphertextLength,
unsigned char* plaintext, CK_ULONG_PTR plaintextLength);
// 参数:hSession 为会话句柄,ciphertext 是待解密的密文,ciphertextLength 是密文长度,
// plaintext 用于存储解密后的明文,plaintextLength 指向存储明文实际长度的变量
// 返回值:成功返回 `CKR_OK`,失败返回其他错误码
// 使用指定会话进行签名
CK_RV C_Sign(CK_SESSION_HANDLE hSession, const unsigned char* data, CK_ULONG dataLength,
unsigned char* signature, CK_ULONG_PTR signatureLength);
// 参数:hSession 为会话句柄,data 是待签名的数据,dataLength 是数据长度,
// signature 用于存储签名结果,signatureLength 指向存储签名实际长度的变量
// 返回值:成功返回 `CKR_OK`,失败返回其他错误码
// 使用指定会话进行签名验证
CK_RV C_Verify(CK_SESSION_HANDLE hSession, const unsigned char* data, CK_ULONG dataLength,
const unsigned char* signature, CK_ULONG signatureLength);
// 参数:hSession 为会话句柄,data 是待验证签名的数据,dataLength 是数据长度,
// signature 是待验证的签名,signatureLength 是签名长度
// 返回值:成功返回 `CKR_OK`,失败返回其他错误码
// 关闭会话
CK_RV C_CloseSession(CK_SESSION_HANDLE hSession);
// 参数:hSession 为要关闭的会话句柄
// 返回值:成功返回 `CKR_OK`,失败返回其他错误码
SDF/SKF接口
SDF/SKF是中国密码设备接口标准(简称国密接口标准),用于实现国密算法与密码设备之间的通信。SDF/SKF接口包括一系列的函数和数据结构,用于实现密码算法的初始化、密钥管理、加密、解密等操作。密码机和密码卡等国产密码设备通常支持SDF,智能密码钥匙等设备支持SKF。
SDF接口示例:
// 初始化 SDF 库,加载配置文件
int SDF_Init(const char* configFilePath);
// 打开指定 ID 的智能密码设备
int SDF_OpenDevice(const char* deviceID, SDF_HANDLE* phDevice);
// 关闭指定句柄的智能密码设备
int SDF_CloseDevice(SDF_HANDLE hDevice);
// 在指定设备上生成随机数
int SDF_GenerateRandom(SDF_HANDLE hDevice, unsigned char* randomData, int dataLength);
// 参数:hDevice 为设备句柄,randomData 用于存储生成的随机数,dataLength 是要生成的随机数长度
// 返回值:成功返回 0,失败返回错误码
// 使用指定设备进行对称加密
int SDF_SymmetricEncrypt(SDF_HANDLE hDevice, const unsigned char* plaintext, int plaintextLength,
unsigned char* ciphertext, int* ciphertextLength, const unsigned char* key);
// 参数:hDevice 为设备句柄,plaintext 是待加密的明文,plaintextLength 是明文长度,
// ciphertext 用于存储加密后的密文,ciphertextLength 指向存储密文实际长度的变量,key 是加密密钥
// 返回值:成功返回 0,失败返回错误码
// 使用指定设备进行对称解密
int SDF_SymmetricDecrypt(SDF_HANDLE hDevice, const unsigned char* ciphertext, int ciphertextLength,
unsigned char* plaintext, int* plaintextLength, const unsigned char* key);
// 参数:hDevice 为设备句柄,ciphertext 是待解密的密文,ciphertextLength 是密文长度,
// plaintext 用于存储解密后的明文,plaintextLength 指向存储明文实际长度的变量,key 是解密密钥
// 返回值:成功返回 0,失败返回错误码
// 使用指定设备进行签名
int SDF_Sign(SDF_HANDLE hDevice, const unsigned char* data, int dataLength,
unsigned char* signature, int* signatureLength, const unsigned char* privateKey);
// 参数:hDevice 为设备句柄,data 是待签名的数据,dataLength 是数据长度,
// signature 用于存储签名结果,signatureLength 指向存储签名实际长度的变量,privateKey 是私钥
// 返回值:成功返回 0,失败返回错误码
// 使用指定设备进行签名验证
int SDF_Verify(SDF_HANDLE hDevice, const unsigned char* data, int dataLength,
const unsigned char* signature, int signatureLength, const unsigned char* publicKey);
// 参数:hDevice 为设备句柄,data 是待验证签名的数据,dataLength 是数据长度,
// signature 是待验证的签名,signatureLength 是签名长度,publicKey 是公钥
// 返回值:成功返回 0,失败返回错误码
SKF接口示例:
// 设备管理接口
ULONG DEVAPI SKF_WaitForDevEvent(LPSTR szDevName, ULONG *pulDevNameLen, ULONG *pulEvent);
// 功能:等待设备插入或者拔除事件,返回发生事件的设备名称和事件类型。
// 参数:
// szDevName:[OUT]发生事件的设备名称。
// pulEvent:[OUT]事件类型,1表示插入,2表示拔出。
// 返回值:SAR_OK表示成功,其他为错误码。
ULONG DEVAPI SKF_ConnectDev(LPSTR szName, DEVHANDLE *phDev);
// 功能:通过设备名称连接设备,返回设备的句柄。
// 参数:
// szName:[IN]设备名称。
// phDev:[OUT]返回设备操作句柄。
// 返回值:SAR_OK表示成功,其他为错误码。
ULONG DEVAPI SKF_DisConnectDev(DEVHANDLE hDev);
// 功能:断开一个已经连接的设备,并释放句柄。
// 参数:
// hDev:[IN]连接设备时返回的设备句柄。
// 返回值:SAR_OK表示成功,其他为错误码。
ULONG DEVAPI SKF_GetDevInfo(DEVHANDLE hDev, DEVINFO *pDevInfo);
// 功能:获取设备的一些特征信息,包括设备标签、厂商信息、支持的算法等。
// 参数:
// hDev:[IN]连接设备时返回的设备句柄。
// pDevInfo:[OUT]返回设备信息。
// 返回值:SAR_OK表示成功,其他为错误码。
ULONG DEVAPI SKF_ChangePIN(HAPPLICATION hApplication, ULONG ulPINType, LPSTR szOldPin, LPSTR szNewPin, ULONG *pulRetryCount);
// 功能:修改Administrator PIN和User PIN的值。
// 参数:
// hApplication:[IN]应用句柄。
// ulPINType:[IN]PIN类型,可为ADMIN_TYPE或USER_TYPE。
// szOldPin:[IN]原PIN值。
// szNewPin:[IN]新PIN值。
// pulRetryCount:[OUT]出错后重试次数。
// 返回值:SAR_OK表示成功,其他为错误码。
ULONG DEVAPI SKF_GetPINInfo(HAPPLICATION hApplication, ULONG ulPINType, ULONG pulMaxRetryCount, ULONG* pulRemainRetryCount, BOOL *pbDefaultPin);
// 功能:获取PIN码信息,包括最大重试次数、当前剩余重试次数以及当前PIN码是否为出厂默认PIN码。
// 参数:
// hApplication:[IN]应用句柄。
// ulPINType:[IN]PIN类型。
// pulMaxRetryCount:[OUT]最大重试次数。
// pulRemainRetryCount:[OUT]当前剩余重试次数,为0时表示已锁死。
// pbDefaultPin:[OUT]是否为出厂默认PIN码。
// 返回值:SAR_OK表示成功,其他为错误码。
ULONG DEVAPI SKF_VerifyPIN(HAPPLICATION hApplication, ULONG ulPINType, LPSTR szPIN, ULONG *pulRetryCount);
// 功能:校验PIN码,校验成功后获得相应权限,若错误则返回PIN码的重试次数,为0时表示PIN码已锁死。
// 参数:
// hApplication:[IN]应用句柄。
// ulPINType:[IN]PIN类型。
// szPIN:[IN]PIN值。
// pulRetryCount:[OUT]出错后返回的重试次数。
// 返回值:SAR_OK表示成功,其他为错误码。
ULONG DEVAPI SKF_UnblockPIN(HAPPLICATION hApplication, LPSTR szAdminPIN, LPSTR szNewUserPIN, ULONG *pulRetryCount);
// 功能:当用户的PIN码锁死后,解锁用户PIN码,解锁后用户PIN码被设置成新值,重试次数恢复原值。
// 参数:
// hApplication:[IN]应用句柄。
// szAdminPIN:[IN]管理员PIN码。
// szNewUserPIN:[IN]新的用户PIN码。
// pulRetryCount:[OUT]管理员PIN码错误时,返回剩余重试次数。
// 返回值:SAR_OK表示成功,其他为错误码。
// 应用管理接口
ULONG DEVAPI SKF_CreateApplication(DEVHANDLE hDev, LPSTR szAppName, LPSTR szAdminPin, DWORD dwAdminPinRetryCount, LPSTR szUserPin, DWORD dwUserPinRetryCount, DWORD dwCreateFileRights, HAPPLICATION *phApplication);
// 功能:创建一个应用。
// 参数:
// hDev:[IN]连接设备时返回的设备句柄。
// szAppName:[IN]应用名称。
// szAdminPin:[IN]管理员PIN。
// dwAdminPinRetryCount:[IN]管理员PIN最大重试次数。
// szUserPin:[IN]用户PIN。
// dwUserPinRetryCount:[IN]用户PIN最大重试次数。
// dwCreateFileRights:[IN]在该应用下创建文件和容器的权限,为各种权限的或值。
// phApplication:[OUT]应用的句柄。
// 返回值:SAR_OK表示成功,其他为错误码。
// 加解密相关接口
ULONG DEVAPI SKF_Encrypt(HANDLE hKey, BYTE *pbData, ULONG ulDataLen, BYTE *pbEncryptedData, ULONG *pulEncryptedLen);
// 功能:单组数据加密,用指定加密密钥对指定数据进行加密。
// 参数:
// hKey:[IN]加密密钥句柄。
// pbData:[IN]待加密数据。
// ulDataLen:[IN]待加密数据长度。
// pbEncryptedData:[OUT]加密后的数据缓冲区指针,可为NULL,用于获得加密后数据长度。
// pulEncryptedLen:[IN,OUT]输入时表示结果数据缓冲区长度,输出时表示结果数据实际长度。
// 返回值:SAR_OK表示成功,其他为错误码。
ULONG DEVAPI SKF_Decrypt(HANDLE hKey, BYTE *pbEncryptedData, ULONG ulEncryptedLen, BYTE *pbData, ULONG *pulDataLen);
// 功能:单个分组数据的解密操作,用指定解密密钥对指定数据进行解密,在调用前必须先调用SKF_DecryptInit。
// 参数:
// hKey:[IN]解密密钥句柄。
// pbEncryptedData:[IN]待解密数据。
// ulEncryptedLen:[IN]待解密数据长度。
// pbData:[OUT]指向解密后的数据缓冲区指针,当为NULL时可获得解密后的数据长度。
// pulDataLen:[IN,OUT]输入时表示结果数据缓冲区长度,输出时表示结果数据实际长度。
// 返回值:SAR_OK表示成功,其他为错误码。
// 签名验证相关接口
ULONG DEVAPI SKF_RSASignData(HCONTAINER hContainer, BYTE *pbData, ULONG ulDataLen, BYTE *pbSignature, ULONG *pulSignLen);
// 功能:使用指定容器的签名私钥对数据进行数字签名。
// 参数:
// hContainer:[IN]用来签名的私钥所在容器句柄。
// pbData:[IN]被签名的数据。
// ulDataLen:[IN]签名数据长度,应不大于RSA密钥模长 - 11。
// pbSignature:[OUT]存放签名结果的缓冲区指针,若为NULL,用于取得签名结果长度。
// pulSignLen:[IN,OUT]输入时表示签名结果缓冲区大小,输出时表示签名结果长度。
// 返回值:SAR_OK表示成功,其他为错误码。
ULONG DEVAPI SKF_RSAVerify(DEVHANDLE hDev, RSAPUBLICKEYBLOB *pRSAPubKeyBlob, BYTE *pbData, ULONG ulDataLen, BYTE *pbSignature, ULONG ulSignLen);
// 功能:使用RSA公钥对签名进行验证。
// 参数:
// hDev:[IN]设备句柄。
// pRSAPubKeyBlob:[IN]RSA公钥数据结构。
// pbData:[IN]待验证签名的数据。
// ulDataLen:[IN]数据长度,应不大于公钥模长 - 11。
// pbSignature:[IN]待验证的签名值。
// ulSignLen:[IN]签名值长度,必须为公钥模长。
// 返回值:SAR_OK表示成功,其他为错误码。
ULONG DEVAPI SKF_ECCSignData(HCONTAINER hContainer, BYTE *pbData, ULONG ulDataLen, PECCSIGNATUREBLOB pSignature);
// 功能:使用ECC算法和指定私钥对数据进行数字签名。
// 参数:
// hContainer:[IN]密钥容器句柄。
// pbData:[IN]待签名数据(输入数据为待签数据的杂凑值,当使用SM2算法时,为待签数据经过SM2签名预处理的结果)。
// ulDataLen:[IN]待签名数据长度。
// pSignature:[OUT]签名值。
// 返回值:SAR_OK表示成功,其他为错误码。
ULONG DEVAPI SKF_ECCVerify(DEVHANDLE hDev, ECCPUBLICKEYBLOB *pECCPubKeyBlob, BYTE *pbData, ULONG ulDataLen, PECCSIGNATUREBLOB pSignature);
// 功能:用ECC公钥对数据进行验签。
// 参数:
// hDev:[IN]设备句柄。
// pECCPubKeyBlob:[IN]ECC公钥数据结构。
// pbData:[IN]待验证签名的数据(输入数据为待签数据的杂凑值,当使用SM2算法时,为待签数据经过SM2签名预处理的结果)。
// ulDataLen:[IN]数据长度。
// pSignature:[IN]待验证签名值。
// 返回值:SAR_OK表示成功,其他为错误码。
KMIP协议
KMIP是密钥管理互操作性协议,用于实现不同厂商的密钥管理系统之间的互操作。KMIP协议定义了一系列的消息格式和操作流程,用于实现密钥的生成、存储、分发、更新、撤销等操作。KMIP协议是密钥管理系统之间的通信标准,为不同厂商的密钥管理系统提供了互操作性支持。KMIP为KMS实现互操作性提供了技术手段,通过遵循 KMIP 协议,不同厂商的 KMS 可以更方便地与其他系统进行集成和交互,实现密钥管理功能的共享和协同。
KMS API示例:
// 在 KMS 系统中创建一个新的密钥
CreateKeyResponse CreateKey(CreateKeyRequest request);
// 从 KMS 系统中获取指定密钥的信息
GetKeyResponse GetKey(GetKeyRequest request);
// 使用 KMS 系统中的密钥对数据进行加密
EncryptResponse Encrypt(EncryptRequest request);
// 使用 KMS 系统中的密钥对加密数据进行解密
DecryptResponse Decrypt(DecryptRequest request);
// 在 KMS 系统中生成随机数
GenerateRandomResponse GenerateRandom(GenerateRandomRequest request);
// 参数:GenerateRandomRequest 是包含随机数生成相关参数(如长度等)的请求结构体
// 返回值:GenerateRandomResponse 是包含生成的随机数及相关状态信息的响应结构体
// 使用 KMS 系统中的密钥对数据进行签名
SignResponse Sign(SignRequest request);
// 参数:SignRequest 是包含待签名数据、密钥 ID 等信息的请求结构体
// 返回值:SignResponse 是包含签名结果及相关状态信息的响应结构体
// 使用 KMS 系统中的密钥对签名进行验证
VerifyResponse Verify(VerifyRequest request);
// 参数:VerifyRequest 是包含待验证数据、签名、密钥 ID 等信息的请求结构体
// 返回值:VerifyResponse 是包含验证结果及相关状态信息的响应结构体
加密软件
加密软件主要包含两类实现:开源密码库和开发语言安全库,加密软件运行在CPU处理器上,不需要特殊的硬件支持;并且加密软件根据自己的开发语言分别提供不同的SDK。
开源密码库
开源密码库是一种通用的密码算法实现库,提供了多种常用的密码算法和协议实现,如:对称加密、非对称加密、哈希函数、消息认证码等。开源密码库具有开放源代码、免费使用、社区支持等特点,广泛应用于各种软件和系统中,为应用程序提供了基础的密码功能支持。常见的开源软件库比较多,如:国际开源安全库OpenSSL、Libgcrypt、Bouncy Castle、Botan,国内开源安全库GMSSL、TASSL等。
对比项目 | OpenSSL | GMSSL | TASSL | mbedtls |
---|---|---|---|---|
成熟度 | 成熟,全球广泛应用,经长期实践检验,稳定性、可靠性高,且大多数Linux系统内置 | 较成熟,专注国密算法,在国内政务、金融等领域有应用,随国密推广发展。 | 基于 OpenSSL 定制,在特定企业级安全场景有应用,成熟度较好。 | 成熟度高,广泛用于嵌入式系统和其他资源受限环境,经受实践考验。 |
开源 star 量(截至 2024 年 12 月) | GitHub 超 26k star,社区关注度和认可度高。 | GitHub 约5k star,国密受众较多。 | GitHub 几百 star 左右,由特定公司维护,与硬件深度集成,定制性和特定场景限制关注度。 | 在 GitHub上有超5k的star,在嵌入式相关社区受关注。 |
语言 | C 语言,高效底层操作,适配多平台实现高性能运算。 | C 语言,便于底层交互,适配国密算法应用需求。 | C 语言,继承 OpenSSL 特性,满足特定场景性能要求。 | C 语言,轻量级适合资源受限环境的开发。 |
完善度 | 功能全面,涵盖对称、非对称加密、哈希、数字证书等,支持多种标准算法协议,文档丰富。 | 专注国密算法,对 SM1、SM2、SM3、SM4 等实现完整,国密功能完善。 | 基于 OpenSSL 定制扩展,支持国密算法,并支持接入加密硬件。 | 提供基本和常用的密码功能,适合嵌入式场景需求,对常见算法和协议有良好支持。 |
活跃程度 | 社区活跃,大量开发者参与,持续更新维护,紧跟技术和安全需求。 | 随国密推广活跃度提升,国内开发者和企业参与完善。 | 活跃度相对低,特定应用和定制性质导致参与人员有限,更新慢。 | Java 社区活跃,众多开发者使用和贡献,不断更新适应发展。 |
OpenSSL
OpenSSL 是一个开源的密码库,提供了多种密码算法和协议的实现,包括对称加密、非对称加密、哈希函数、消息认证码、数字证书等。OpenSSL 是一个功能全面、成熟稳定的密码库,广泛应用于各种软件和系统中,为应用程序提供了基础的密码功能支持。OpenSSL 是一个 C 语言实现的密码库,支持多种操作系统和平台,具有高效、稳定、可靠的特点。
OpenSSL加解密示例:
#include <stdio.h>
#include <string.h>
#include <openssl/aes.h>
void encrypt_aes(const unsigned char *plaintext, int plaintext_len, const unsigned char *key, unsigned char *ciphertext) {
AES_KEY aes_key;
AES_set_encrypt_key(key, 128, &aes_key);
AES_encrypt(plaintext, ciphertext, &aes_key);
}
void decrypt_aes(const unsigned char *ciphertext, int ciphertext_len, const unsigned char *key, unsigned char *decrypted_text) {
AES_KEY aes_key;
AES_set_decrypt_key(key, 128, &aes_key);
AES_decrypt(ciphertext, decrypted_text, &aes_key);
}
int main() {
const unsigned char key[] = "1234567890123456";
const unsigned char plaintext[] = "Hello, World!";
unsigned char ciphertext[16];
unsigned char decrypted_text[16];
encrypt_aes(plaintext, strlen((char *)plaintext), key, ciphertext);
printf("Ciphertext: ");
for (int i = 0; i < 16; i++) {
printf("%02x ", ciphertext[i]);
}
printf("\n");
decrypt_aes(ciphertext, 16, key, decrypted_text);
printf("Decrypted Text: %s\n", decrypted_text);
return 0;
}
GMSSL
GMSSL 是一个国密算法实现库,专注于国密算法的实现和应用,包括 SM1、SM2、SM3、SM4 等国密算法的实现。GMSSL 是一个 C 语言实现的密码库,支持多种操作系统和平台,具有高效、稳定、可靠的特点。GMSSL 是国内政务、金融等领域广泛应用的密码库,为国密算法的推广和应用提供了技术支持。
GMSSL加解密示例:
#include <stdio.h>
#include <string.h>
#include <gmssl/sm4.h>
void encrypt_sm4(const unsigned char *plaintext, int plaintext_len, const unsigned char *key, unsigned char *ciphertext) {
SM4_KEY sm4_key;
sm4_set_encrypt_key(&sm4_key, key);
sm4_crypt_ecb(&sm4_key, SM4_ENCRYPT, plaintext_len / 16, plaintext, ciphertext);
}
void decrypt_sm4(const unsigned char *ciphertext, int ciphertext_len, const unsigned char *key, unsigned char *decrypted_text) {
SM4_KEY sm4_key;
sm4_set_decrypt_key(&sm4_key, key);
sm4_crypt_ecb(&sm4_key, SM4_DECRYPT, ciphertext_len / 16, ciphertext, decrypted_text);
}
int main() {
const unsigned char key[] = "1234567890123456";
const unsigned char plaintext[] = "Hello, World!";
unsigned char ciphertext[16];
unsigned char decrypted_text[16];
encrypt_sm4(plaintext, strlen((char *)plaintext), key, ciphertext);
printf("Ciphertext: ");
for (int i = 0; i < 16; i++) {
printf("%02x ", ciphertext[i]);
}
printf("\n");
decrypt_sm4(ciphertext, 16, key, decrypted_text);
printf("Decrypted Text: %s\n", decrypted_text);
return 0;
}
TASSL
TASSL 是基于 OpenSSL 定制扩展的密码库,支持国密算法,并支持接入加密硬件。TASSL 是一个 C 语言实现的密码库,具有高效、稳定、可靠的特点。TASSL 主要应用于特定企业级安全场景,为特定应用提供了定制化的密码功能支持。
TASSL加解密示例:
#include <stdio.h>
#include <string.h>
#include <tassl/aes.h> // 假设 TASSL 头文件路径
void encrypt_aes(const unsigned char *plaintext, int plaintext_len, const unsigned char *key, unsigned char *ciphertext) {
AES_KEY aes_key;
AES_set_encrypt_key(key, 128, &aes_key);
AES_encrypt(plaintext, ciphertext, &aes_key);
}
void decrypt_aes(const unsigned char *ciphertext, int ciphertext_len, const unsigned char *key, unsigned char *decrypted_text) {
AES_KEY aes_key;
AES_set_decrypt_key(key, 128, &aes_key);
AES_decrypt(ciphertext, decrypted_text, &aes_key);
}
int main() {
const unsigned char key[] = "1234567890123456";
const unsigned char plaintext[] = "Hello, World!";
unsigned char ciphertext[16];
unsigned char decrypted_text[16];
encrypt_aes(plaintext, strlen((char *)plaintext), key, ciphertext);
printf("Ciphertext: ");
for (int i = 0; i < 16; i++) {
printf("%02x ", ciphertext[i]);
}
printf("\n");
decrypt_aes(ciphertext, 16, key, decrypted_text);
printf("Decrypted Text: %s\n", decrypted_text);
return 0;
}
Bouncy Castle
Bouncy Castle 是一个 Java 语言实现的密码库,提供了多种密码算法和协议的实现,包括对称加密、非对称加密、哈希函数、消息认证码、数字证书等。Bouncy Castle 是 Java 安全领域的知名密码库,为 Java 项目提供了安全功能支持。Bouncy Castle 是一个功能全面、成熟稳定的密码库,广泛应用于 Java 项目中。
Bouncy Castle加密示例:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.Security;
import java.util.Base64;
public class BouncyCastleAesExample {
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
String key = "1234567890123456";
SecretKey secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes(), "AES");
Cipher encryptCipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC");
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey);
Cipher decryptCipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKey);
String plaintext = "Hello, World!";
byte[] encryptedBytes = encryptCipher.doFinal(plaintext.getBytes());
String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
System.out.println("Encrypted Text: " + encryptedText);
byte[] decryptedBytes = decryptCipher.doFinal(Base64.getDecoder().decode(encryptedText));
String decryptedText = new String(decryptedBytes);
System.out.println("Decrypted Text: " + decryptedText);
}
}
mbedtls
mbedtls 是一个轻量级的密码库,适合资源受限环境的开发,提供了基本和常用的密码功能支持,包括对称加密、非对称加密、哈希函数、消息认证码等。mbedtls 是一个 C 语言实现的密码库,支持多种操作系统和平台,具有高效、稳定、可靠的特点。mbedtls 主要应用于嵌入式系统和其他资源受限环境,为这些环境提供了密码功能支持。
mbedtls加解密示例:
#include <stdio.h>
#include <string.h>
#include <mbedtls/aes.h>
void encrypt_aes(const unsigned char *plaintext, int plaintext_len, const unsigned char *key, unsigned char *ciphertext) {
mbedtls_aes_context aes_ctx;
mbedtls_aes_init(&aes_ctx);
mbedtls_aes_setkey_enc(&aes_ctx, key, 128);
mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, plaintext, ciphertext);
mbedtls_aes_free(&aes_ctx);
}
void decrypt_aes(const unsigned char *ciphertext, int ciphertext_len, const unsigned char *key, unsigned char *decrypted_text) {
mbedtls_aes_context aes_ctx;
mbedtls_aes_init(&aes_ctx);
mbedtls_aes_setkey_dec(&aes_ctx, key, 128);
mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_DECRYPT, ciphertext, decrypted_text);
mbedtls_aes_free(&aes_ctx);
}
int main() {
const unsigned char key[] = "1234567890123456";
const unsigned char plaintext[] = "Hello, World!";
unsigned char ciphertext[16];
unsigned char decrypted_text[16];
encrypt_aes(plaintext, strlen((char *)plaintext), key, ciphertext);
printf("Ciphertext: ");
for (int i = 0; i < 16; i++) {
printf("%02x ", ciphertext[i]);
}
printf("\n");
decrypt_aes(ciphertext, 16, key, decrypted_text);
printf("Decrypted Text: %s\n", decrypted_text);
return 0;
}
开发语言
开发语言安全库是一种通用的密码算法实现库,提供了多种常用的密码算法和协议实现,如:对称加密、非对称加密、哈希函数、消息认证码等。开发语言安全库是开发语言自带的密码库,提供了基础的密码功能支持,为开发者提供了便捷的密码功能调用接口。开发语言安全库根据开发语言不同提供了不同的密码功能支持。
开发语言 | 密码库 | 主要功能 | 特点 | 复杂度 | 性能 |
---|---|---|---|---|---|
java | jca/jce/bc | 提供加密、解密、数字签名、密钥管理等功能 | 是Java标准的加密框架,具有可扩展性和通用性,bc(BouncyCastle)提供更多算法实现 | 中等,对于初学者可能较复杂 | 性能良好,但取决于具体算法和实现方式 |
js | CryptoJS | 支持多种加密算法,如AES、DES、SHA等,可用于数据加密和哈希计算 | 纯JavaScript实现,便于在浏览器端使用 | 相对较低,使用简单 | 性能一般,在处理大量数据时可能较慢 |
python | pycryptodome | 提供加密、哈希、签名、密钥交换等功能 | 是Python的一个强大的加密库,支持多种算法 | 适中,易于使用 | 性能较好,经过优化处理 |
golang | crypto | 提供对称加密、非对称加密、哈希函数等功能 | 是Go标准库的一部分,简洁高效 | 较低,Go语言本身简单 | 性能较高,Go语言在性能上有优势 |
这些密码库在各自的开发语言中都有重要的应用,开发人员可以根据项目需求和语言环境选择合适的密码库来保障数据的安全性。
Java加解密示例
- JCE加解密示例:
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class JavaAESExample {
public static void main(String[] args) throws Exception {
String key = "1234567890123456";
String plaintext = "hello world";
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
// 加密
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encrypted = cipher.doFinal(plaintext.getBytes());
String encryptedText = Base64.getEncoder().encodeToString(encrypted);
System.out.println("加密后: " + encryptedText);
// 解密
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
System.out.println("解密后: " + new String(decrypted));
}
}
- BC(BouncyCastle)加解密示例
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;
import java.util.Base64;
public class JavaBCAESExample {
public static void main(String[] args) throws Exception {
// 注册Bouncy Castle提供程序
Security.addProvider(new BouncyCastleProvider());
String key = "1234567890123456";
String plaintext = "hello world";
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
// 加密
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encrypted = cipher.doFinal(plaintext.getBytes());
String encryptedText = Base64.getEncoder().encodeToString(encrypted);
System.out.println("加密后: " + encryptedText);
// 解密
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
System.out.println("解密后: " + new String(decrypted));
}
}
JS加解密示例
使用CryptoJS加解密示例:
var CryptoJS = require("crypto - js");
var key = "1234567890123456";
var plaintext = "hello world";
// 加密
var encrypted = CryptoJS.AES.encrypt(plaintext, CryptoJS.enc.Utf8.parse(key), {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
var encryptedText = encrypted.toString();
console.log("加密后: " + encryptedText);
// 解密
var decrypted = CryptoJS.AES.decrypt(encryptedText, CryptoJS.enc.Utf8.parse(key), {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
console.log("解密后: " + decrypted.toString(CryptoJS.enc.Utf8));
Python加解密示例
使用 pycryptodome加解密示例:
from Crypto.Cipher import AES
import base64
key = b"1234567890123456"
plaintext = b"hello world"
# 填充函数
def pad(s):
return s + ((16 - len(s) % 16) * chr(16 - len(s) % 16)).encode()
# 去填充函数
def unpad(s):
return s[:-s[-1]]
# 加密
cipher = AES.new(key, AES.MODE_ECB)
encrypted = cipher.encrypt(pad(plaintext))
encrypted_text = base64.b64encode(encrypted).decode()
print("加密后: ", encrypted_text)
# 解密
decrypted = cipher.decrypt(base64.b64decode(encrypted_text))
print("解密后: ", unpad(decrypted).decode())
Golang加解密示例
使用Golang标准库Crypto加解密示例:
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
)
func main() {
key := []byte("1234567890123456")
plaintext := []byte("hello world")
// 加密
block, err := aes.NewCipher(key)
if err!= nil {
panic(err)
}
plaintext = pkcs7Padding(plaintext, block.BlockSize())
ciphertext := make([]byte, len(plaintext))
mode := cipher.NewECBEncrypter(block)
mode.CryptBlocks(ciphertext, plaintext)
encryptedText := base64.StdEncoding.EncodeToString(ciphertext)
fmt.Println("加密后: ", encryptedText)
// 解密
decodedText, _ := base64.StdEncoding.DecodeString(encryptedText)
block, _ = aes.NewCipher(key)
mode = cipher.NewECBDecrypter(block)
mode.CryptBlocks(decodedText, decodedText)
decryptedText := pkcs7Unpadding(decodedText)
fmt.Println("解密后: ", string(decryptedText))
}
func pkcs7Padding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(data, padtext...)
}
func pkcs7Unpadding(data []byte) []byte {
length := len(data)
unpadding := int(data[length-1])
return data[:(length - unpadding)]
}
结语
本文详细介绍了现代密码学(基础密码技术)的应用技术体系,并分别对常见的加密硬件和加密软件进一步展开介绍。通过对比分析,我们可以看到,加密硬件和加密软件在应用场景、技术特点、性能表现等方面存在一定的差异,开发人员可以根据项目需求和实际情况选择合适的加密技术方案。在实际开发中,加密硬件和加密软件可以结合使用,充分发挥各自的优势,提高数据的安全性和可靠性。同时我们对于加密硬件的密码接口规范和加密软件的密码库进行了详细的介绍,希望对大家有所帮助。
注:本文中的代码示例仅供参考,实际开发中需要根据具体需求和环境进行调整和优化。如:示例中加密模式使用了ECB,改模式已经被认为不安全,不推荐使用。
参考文献
- 【1】OpenSSL
- 【2】GMSSL
- 【4】mbedtls
- 【5】Bouncy Castle
- 【6】crypto-js
- 【7】pycryptodome
- 【8】Golang crypto
- 【9】SKF接口规范
- 【10】KMIP协议文档
- 【11】Java JCE
- 【12】SDF接口规范
- 【13】PKCS#11