一文入门现代密码学(应用篇)

主页

微信公众号:密码应用技术实战
博客园首页:https://www.cnblogs.com/informatics/
GIT地址:https://github.com/warm3snow

本文组织

  • 简介:现代密码学应用背景
  • 密码技术应用体系
  • 加密硬件
  • 加密软件
  • 密钥体系
  • 总结
  • 参考资料

简介

现代密码学应用:现代密码学是信息安全领域的重要分支,主要研究数据加密、身份认证、数据完整性保护等安全技术。现代密码学应用广泛,涉及网络通信、电子商务、金融支付、物联网、云计算等多个领域,是信息安全的基础和核心技术。由于密码技术实现极为复杂、并且安全性要求较高,因此需要专门的密码产品和密码服务来支持其应用。
在《一文入门现代密码学》中,我们已经介绍了现代密码学的基础知识和发展历程,本文将进一步介绍现代密码学的应用技术体系,希望帮助大家在选择密码产品或密码库时提供一些参考。

密码技术应用体系

通过总结当前主流的软硬件加密产品、密码库在实际产品中的应用,总结密码技术应用体系如下:

image

  • 密码技术应用主要有两种方式:加密硬件加密软件
  • 加密硬件包含多类密码产品:密码芯片、密码卡、智能密码钥匙、密码机以及KMS密码系统等。加密硬件一般遵循密码接口规范,为上层提供基本的密码运算功能。
  • 加密软件主要包含两类实现:开源密码库和开发语言安全库,加密软件运行在CPU处理器上,不需要特殊的硬件支持;并且加密软件根据自己的开发语言分别提供不同的SDK。
  • 不管是加密硬件还是加密软件,都提供了丰富的基础密码功能,如:随机数生成、密钥生成、加解密、签名验证以及哈希摘要、数字证书、tls/ssl等功能。
  • 由于硬件产品的特殊性,一般会提供额外的设备访问、会话管理等功能。

加密硬件和加密软件对比如下:

对比项目 加密软件 加密硬件
特点 灵活,易更新,成本低,操作方便 性能优,安全强,专用性高,可靠
性能 依赖 CPU,加密慢,多任务弱 专用芯片,加密快,多任务强
安全性 易受软件攻击,代码易被分析 抗攻击,密钥管理安全
密钥保护 存储易受威胁,管理复杂 硬件存储安全,管理简单
应用场景 个人、小型企业一般加密需求 金融、政府等高标准场景
部署难度 安装配置简单 需专业人员物理安装
可扩展性 软件升级扩展,有性能局限 增加模块扩展,成本高

加密硬件

加密硬件也被成为密码设备,包含众多的密码产品,如:密码芯片、密码卡、密码机、密码钥匙以及密码系统等。

加密硬件介绍

  • 密码芯片是一种专门用于密码运算的集成电路芯片。它集成了加密算法、密钥管理、随机数生成等功能模块,能够为各种设备提供安全的密码服务。其体积小、功耗低、集成度高,广泛应用于智能卡、物联网设备、移动终端等领域,为数据的保密性、完整性和真实性提供基础保障。
  • 密码卡
    密码卡是一种基于 PCIe 接口的密码设备。它将密码芯片集成在 PCIe 卡上,通过 PCIe 接口与计算机或服务器进行高速数据传输。这种卡可以提供强大的密码运算能力,支持多种加密算法和密钥管理功能,适用于对性能要求较高的服务器、数据中心等环境,可用于加密存储、网络通信加密等应用场景。
  • 密码机
    密码机是一种专门设计用于实现密码功能的设备,通常由硬件、软件和固件组成。它可以独立完成数据的加密、解密、签名、验证等操作,具备强大的密码运算能力和密钥管理系统。密码机一般应用于金融、政府、军队等对信息安全要求极高的领域,为关键业务系统提供安全可靠的密码服务。
  • 智能密码钥匙
    智能密码钥匙是一种小型的、便携式的密码设备,通常采用 USB 接口与计算机或其他设备连接。它内置密码芯片,具有存储密钥、执行密码运算等功能。用户可以通过智能密码钥匙进行身份认证、数据加密等操作,其安全性高、便于携带,常用于网上银行、电子政务等领域,保障用户的身份安全和数据安全。
  • 密钥管理系统(KMS):
    KMS(Key Management System)是一种用于管理密钥生命周期的系统,涵盖了密钥的生成、存储、分发、更新、撤销等环节。它通过一套安全的策略和机制,确保密钥在整个生命周期内的保密性、完整性和可用性。密钥管理系统是保障密码体系安全运行的核心,它与各种密码设备和应用系统紧密配合,为其提供密钥支持和管理服务。

加密硬件设备具有如下关系:

image

  • 密码芯片是基础:是其他密码设备的核心组成部分,为密码卡、密码钥匙等提供基本的密码运算能力。没有密码芯片,这些设备就无法实现加密、解密等安全功能。
  • 密码卡和密码钥匙是基于密码芯片的应用产品:它们以不同的形态呈现,满足不同用户和应用场景的需求。密码卡可以是插入式的智能卡,用于特定设备或系统的身份认证和数据加密;密码钥匙则以 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_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`,失败返回其他错误码

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_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_ConnectDev(LPSTR szName, DEVHANDLE *phDev);
// 功能:通过设备名称连接设备,返回设备的句柄。
// 参数:
//     szName:[IN]设备名称。
//     phDev:[OUT]返回设备操作句柄。
// 返回值: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_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 系统中的密钥对数据进行签名
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;
}

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加解密示例

Java 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)]
}

密钥体系

根据Kerckhoff原则,密码的安全性的确不依赖于算法的保密。该原则指出,一个密码系统的安全性应该仅仅取决于对密钥的保密,而不是对加密算法或其他细节的保密 。也就是说,即使攻击者知道了整个加密算法的具体细节,只要密钥是安全保密的,该密码系统仍然应该是安全的。

当前密码体系主要分为对称密钥体系非对称密钥体系两种。因此密钥体系也涉及到两种密钥的管理和使用。密钥体系是密码学中的重要概念,包含密钥的分类、密钥的管理、密钥的生命周期等内容。加密硬件或者密码系统一般包含完善的密钥管理功能,其中密钥按照使用场景和功能主要包含:

image

  • LMK:Local Master Key,本地主密钥,用于保护其他密钥的安全。通常为对称密钥,存储在加密硬件中,不允许导出。
  • KEK:Key Encryption Key,密钥加密密钥,用于加密其他密钥的传输和存储。通常为对称密钥,存储在加密硬件中,不允许导出。
  • DEK:Data Encryption Key,数据加密密钥,用于对数据进行加密和解密。通常为对称密钥,存储在加密硬件或加密软件中,可以加密导出。
  • 身份密钥:用于数字签名和身份认证,通常为非对称密钥,存储在加密硬件或加密软件中,可以加密导出。

需要注意的是:

  • 加密硬件中的LMK通常也被叫做管理密钥,由出厂设置
  • 加密硬件中的身份密钥包含用户身份密钥和设备身份密钥,用户身份密钥用于对用户数据进行签名、身份校验等;设备身份密钥用于对设备管理操作进行身份校验等
  • 加密硬件中的DEK一般也被成为会话密钥,由于DEK的生命周期较短,通常用于对数据进行加密和解密,一般与加密数据一起传输,不存储在硬件中。
  • 加密软件中的密钥管理一般由密码库提供,开发人员可以根据需求自行管理密钥,密钥的存储和保护需要开发人员自行实现。

结语

本文详细介绍了现代密码学(基础密码技术)的应用技术体系,并分别对常见的加密硬件和加密软件进行了展开介绍。通过对比分析,我们可以看到,加密硬件和加密软件在应用场景、技术特点、性能表现等方面存在一定的差异,开发人员可以根据项目需求和实际情况选择合适的加密技术方案。在实际开发中,研发人员需要时刻注意密钥的安全性,密钥的管理和使用是保障数据安全的关键,需要合理设计密钥体系和密钥管理方案,确保密钥的安全保密和合理使用,在企业级应用中采用加密硬件,可以提高密钥的安全性和保密性,保障数据的安全性。

注:本文中的代码示例仅供参考,实际开发中需要根据具体需求和环境进行调整和优化。如:示例中加密模式使用了ECB,该模式已经被认为不安全,不推荐使用。

参考文献

posted @   warm3snow  阅读(230)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示