20231326《密码系统设计》第五周预习报告
- 20231326《密码系统设计》第五周预习报告
- 学习内容
- 《Windows C/C++加密解密实战》第 9 章
- AI对学习内容的总结
- 1. CSP(Cryptographic Service Provider)
- 2. CryptoAPI 简明概览
- 3. CSP 调用与密钥结构
- 4. C/C++ 编程实战简要
- 学习思维导图
- 基于 AI 的学习
- 对话
- 总结
- 你掌握得好的地方
- 有待改进的地方
- 总体评价
- 学习实践过程遇到的问题与解决方式
- 如果不使用 CRYPT_VERIFYCONTEXT 标志,而是使用默认设置(需要访问密钥容器),如果应用程序连续多次使用 CRYPT_NEWKEYSET 创建一个同名的密钥容器,会对系统和密钥安全造成什么后果?
- 不使用 CRYPT_VERIFYCONTEXT 的情况
- 使用 CRYPT_NEWKEYSET 创建同名密钥容器
- 为什么CryptoAPI 采用了三层架构,并强制应用程序通过操作系统层来调用底层的 CSP,而不是允许直接调用 CSP 的 DLL?
- 如果不使用 CRYPT_VERIFYCONTEXT 标志,而是使用默认设置(需要访问密钥容器),如果应用程序连续多次使用 CRYPT_NEWKEYSET 创建一个同名的密钥容器,会对系统和密钥安全造成什么后果?
- 本文链接
- 参考资料
- 学习内容
学习内容
《Windows C/C++加密解密实战》第 9 章
-
CSP 简介与组成
- 什么是 CSP (Cryptographic Service Provider)
- CSP 是 Windows 平台的加密服务提供者。
- 它是真正执行密码运算的独立模块。
- 它是 Windows 密码服务系统的底层实现。
- 物理组成与实现
- 基本组成:动态链接库(DLL)和签名文件。
- 签名文件:用于保证 CSP 经过认证,防止被攻击者冒充或篡改。
- 实现分类:
- 纯软件实现。
- 带硬件的实现(通常称为 USB Key),按芯片分为加密型和存储型。
- 逻辑组成
- SPI 接口:微软提供的基本密码系统函数实现(CSP 必须支持)。
- 算法实现:加密签名算法的实现。
- 密钥库及密钥容器 (Key Containers):
- 密钥库是 CSP 的内部数据库。
- 密钥容器存放属于特定用户的签名密钥对、交换密钥对以及 X.509 数字证书。
- 出于安全考虑,私钥一般存储在 CSP 内部,不可导出。
- 什么是 CSP (Cryptographic Service Provider)
-
CryptoAPI 简介与服务体系结构
- CryptoAPI 简介
- CryptoAPI 是 Win32 平台下为应用程序开发者提供数据加解密和证书服务的编程接口。
- 作用:提供编码、解码、加密、解密、哈希、数字证书管理等与信息安全相关的函数。
- CSP 服务体系 (三层结构)
- 应用层:用户应用程序,通过 CryptoAPI 调用加密服务。
- 操作系统层 (OS):
- 为应用层提供统一的 CryptoAPI 接口。
- 为服务提供层提供 CryptoSPI (Cryptographic Service Provider Interface) 接口。
- 负责隔离底层 CSP 的实现细节,并进行管理。
- 服务提供层:具体的 CSP 模块,执行实际的加密工作。
- 通信路径:应用程序 -> CryptoAPI -> OS -> CryptoSPI -> CSP。
- CryptoAPI 简介
-
CryptoAPI 体系架构与基本功能
- CryptoAPI 体系架构(五大部分)
- 基本加密函数:用于选择/连接 CSP、产生/交换/传输密钥等操作。
- 简单的消息函数:用于消息编解码、加解密、数字签名及验签(包装了底层函数)。
- 底层消息函数:对 PKCS#7 数据进行编码/解码和验证,提供更大的灵活性。
- 证书编解码函数:用于数据加解密、哈希、签名校验,以及证书请求和扩展的编码/解码。
- 证书库管理函数:管理数字证书、证书撤销列表和证书信任列表的使用、存储、获取。
- CryptoAPI 的基本功能
- 密钥管理:支持会话密钥和公私钥对(分为交换密钥对和签名密钥对)。
- 数据编解码:采用 ASN.1 编码方式,编码规则为 DER。
- 数据加解密:约定加密较大的数据块时采用对称密钥算法。
- 哈希和数字签名:微软 CSP 产生的数字签名遵循 RSA 标准 (PKCS#6)。
- 数字证书管理:用于安全通信中的身份鉴别。
- CryptoAPI 体系架构(五大部分)
-
CryptoAPI 调用底层 CSP 服务方式
- CSP 连接与密钥容器
- 应用程序使用
CryptAcquireContext函数连接 CSP,并获得指向被选择的 CSP 的句柄。 - CSP 的密钥库包含一个或多个密钥容器,每个容器包含一个特定用户的所有密钥对。
- 应用程序使用
- 密钥存储结构
- KeyBlob:微软 CryptoAPI 采用 KeyBlob 数据结构存储离开了 CSP 内部的密钥。
- KeyBlob 是在不同 CSP 之间安全传送密钥的载体。
- 私钥 KeyBlob (PrivateKeyBlob) 的私钥部分需要用对称加密算法加密,以保证绝对保密。
- CSP 连接与密钥容器
-
C/C++ 编程实战:基本加密函数
- 服务提供者函数(连接与管理 CSP)
CryptAcquireContext:获得指定 CSP 的密钥容器的句柄(连接 CSP)。CryptReleaseContext:释放由CryptAcquireContext得到的句柄(断开连接)。CryptEnumProviders:枚举当前计算机中的所有 CSP。dwFlags关键参数值:CRYPT_VERIFYCONTEXT:不要求访问私钥,如程序只执行哈希和对称加密。CRYPT_NEWKEYSET:使用指定名称创建一个新的密钥容器。CRYPT_DELETEKEYSET:删除由pszContainer指定的密钥容器。
- C++ 开发环境搭建示例 (关键代码)
// 包含头文件 #include <windows.h> #include <wincrypt.h> // CryptoAPI 库函数声明int main() {HCRYPTPROV hCryptProv;// 尝试连接 CSP (PROV_RSA_FULL) 并获得句柄if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT | CRYPT_VERIFYCONTEXT)){// ... 处理错误return -1;}// ... 执行加密操作// 释放句柄CryptReleaseContext(hCryptProv, 0); return 0; }
- 服务提供者函数(连接与管理 CSP)
AI对学习内容的总结
1. CSP(Cryptographic Service Provider)
核心概念:
- CSP 是 Windows 平台真正执行加密运算的模块,所有加密、签名、哈希操作最终依赖 CSP。
- 对应用程序透明,通过 CryptoAPI 调用。
组成:
- 物理:DLL + 签名文件
- 确保 CSP 身份和完整性
- 实现类型:软件 CSP / 硬件 CSP(USB Key、HSM)
- 逻辑:
- SPI 接口:CSP 必须实现的标准接口
- 算法实现:RSA、AES、SHA 等
- 密钥库/密钥容器:存储用户密钥对和证书,私钥通常不可导出
实践补充:
- 硬件 CSP 私钥永不出硬件,更安全
- 软件 CSP 易部署,适合开发和测试环境
2. CryptoAPI 简明概览
定义:Win32 提供的加密接口,屏蔽 CSP 复杂性。
三层体系:
- 应用层:调用 CryptoAPI
- OS 层:提供统一接口,隔离 CSP 细节
- 服务提供层:CSP 执行实际加密
调用路径:应用 → CryptoAPI → OS → CryptoSPI → CSP
核心功能:
- 密钥管理:会话密钥、公私钥对(签名/交换)
- 数据编解码:ASN.1 + DER
- 加解密:对称加密处理大数据,非对称适合小数据或密钥交换
- 哈希与签名:RSA PKCS#6
- 证书管理:身份鉴别、证书撤销和信任管理
实践补充:
- CryptoAPI 可结合智能卡/USB Key/硬件 HSM
- 异常处理要覆盖 CSP 返回错误码
3. CSP 调用与密钥结构
关键函数:
CryptAcquireContext:获取 CSP 句柄CryptReleaseContext:释放句柄CryptEnumProviders:枚举系统 CSP
密钥存储:
- 密钥容器:每个用户独立存储密钥
- KeyBlob:安全传输密钥
- 私钥部分加密,防止泄露
- 可导出需显式设置
EXPORTABLE
实践补充:
CRYPT_VERIFYCONTEXT:不访问私钥,用于哈希或对称加密CRYPT_NEWKEYSET/CRYPT_DELETEKEYSET:创建/删除密钥容器- 密钥容器命名规范,便于管理
4. C/C++ 编程实战简要
流程:
- 包含头文件:
#include <windows.h>
#include <wincrypt.h>
- 获取 CSP 句柄:
HCRYPTPROV hProv;
CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
- 执行加密/解密/签名/哈希等操作
- 释放 CSP 句柄:
CryptReleaseContext(hProv, 0);
实践补充:
- CSP 句柄必须释放,防止资源泄漏
- 异常处理必不可少,尤其硬件 CSP 可能返回各种错误码
- 对称加密处理大数据更高效,非对称用于密钥交换或小数据
- 硬件 CSP 提供更高安全性,软件 CSP 部署更灵活
学习思维导图
基于 AI 的学习
原对话链接:
https://chatgpt.com/share/68fe18b6-d1e8-800b-b160-492d4083f192
对话
Gisli: 我学习了这些内容,请使用苏格拉底的方式回答我,一次一个问题
AI: 我们先从基础理解开始:
问题 1:
CSP(Cryptographic Service Provider)在 Windows 系统中扮演什么角色?它与 CryptoAPI 的关系是什么?
Gisli: CryptoAPI 是面向应用层的统一编程接口。应用程序通过调用 CryptoAPI,经由操作系统,最终调用底层的 CSP 来执行密钥管理、加解密等具体密码服务。
AI: 很好,你理解了整体流程。
问题 2:
CSP 的物理组成和逻辑组成有什么区别?为什么私钥一般不可导出?
Gisli: 物理组成指 CSP 的实体文件,包括动态链接库 (DLL) 和用于认证的签名文件(若有硬件实现,还包括硬件装置,如 USB Key)。
逻辑组成指 CSP 内部的功能结构,包括 SPI 接口(提供给 OS 的标准接口)、算法实现、以及密钥库/密钥容器。
私钥一般不可导出是为了安全保密。私钥是身份的最高凭证,不可导出能确保私钥始终驻留在安全的 CSP 内部(或硬件设备中),防止其被恶意软件窃取或在传输过程中泄露。
AI: 回答非常准确,你抓住了物理与逻辑层的核心差异,也理解了私钥不可导出的安全理由。
问题 3:
在 CryptoAPI 的三层服务体系结构中,操作系统层(OS)具体起到哪些作用?
Gisli: 提供统一 API、提供 SPI 接口、抽象与隔离、管理 CSP
AI: 完全正确,操作系统层既为应用层提供统一的 CryptoAPI 接口,也为服务提供层提供 CryptoSPI 接口,同时隔离底层 CSP 的实现细节并进行管理。
问题 4:
在 CryptoAPI 中,密钥容器(Key Container)和 KeyBlob 有什么区别,它们分别起什么作用?
Gisli: 密钥容器是 CSP 内部用于安全存储用户密钥对的逻辑存储单元。作为用户的“保险箱”,确保私钥始终安全地驻留在 CSP 内。
KeyBlob是一种数据结构,是密钥离开了 CSP 内部后的安全传输载体。用于安全地导入或导出密钥,或在不同的 CSP 之间传送密钥。
AI: 完全正确,你清楚地区分了“密钥容器”是 CSP 内部安全存储的单元,而 KeyBlob 是密钥在 CSP 之外传输时的安全载体。
问题 5:
CryptAcquireContext 函数在 C/C++ 编程中有哪些主要用途?CRYPT_VERIFYCONTEXT 和 CRYPT_NEWKEYSET 标志分别表示什么意思?
Gisli: 这个我记不清楚
AI: 没关系,我来帮你梳理一下。
-
CryptAcquireContext的主要用途是:连接到指定 CSP 并获得一个句柄,这个句柄之后可以用来进行加密、解密、哈希、签名等操作。它相当于“打开了 CSP 的门”,让应用程序可以使用底层加密服务。 -
标志说明:
CRYPT_VERIFYCONTEXT:不需要访问私钥,常用于只做哈希或对称加密的场景。CRYPT_NEWKEYSET:创建新的密钥容器,当你想生成一组新的密钥对并存储时使用。
问题 6:
在 C/C++ 编程中,为什么需要在使用完 CSP 后调用 CryptReleaseContext?它起什么作用?
Gisli: 清理资源?
AI: 对啦,基本理解正确。更准确地说:
CryptReleaseContext的作用是释放由CryptAcquireContext获得的 CSP 句柄,相当于断开应用程序与 CSP 的连接。- 它不仅释放内存资源,还确保底层 CSP 不再保持不必要的打开状态,从而提高安全性和系统稳定性。
问题 7:
CryptoAPI 的基本功能包括密钥管理、数据编解码、数据加解密、哈希与数字签名、数字证书管理。请你解释一下为什么对大数据块通常使用对称加密而不是非对称加密?
Gisli: 非对称加密太慢
AI: 完全正确,非对称加密(如 RSA)计算量大,效率低,不适合加密大数据块。
- 对称加密(如 AES)速度快,适合处理大数据块。
- 通常实际应用中会使用 非对称加密来加密对称密钥,然后用这个对称密钥加密大数据块,这就是常见的混合加密方式。
问题 8:
CryptoAPI 中,数字签名遵循 RSA 标准 (PKCS#6),为什么私钥需要严格保护,而公钥可以公开?
Gisli: 这个问题太简单了,结束提问。总结我的回答,指出需要改进的地方
AI: 好的,我们来总结一下你的学习情况,并分析优缺点与改进建议。
总结
你掌握得好的地方
-
CSP 与 CryptoAPI 的关系理解正确
- 你清楚应用程序通过 CryptoAPI 调用底层 CSP 服务完成加密、解密和密钥管理操作。
-
物理组成与逻辑组成区别明确
- 能准确区分 DLL/签名文件(物理)与 SPI 接口、算法实现、密钥库(逻辑)。
- 理解私钥不可导出的安全原因。
-
三层体系架构理解到位
- 明确操作系统层提供统一接口、CryptoSPI 接口,并隔离 CSP 实现。
-
密钥容器与 KeyBlob 区分清楚
- 容器用于内部安全存储,KeyBlob 用于密钥在 CSP 外部的安全传输。
-
非对称 vs 对称加密选择理解正确
- 明白大数据块使用对称加密效率高,非对称加密效率低。
有待改进的地方
-
CryptAcquireContext的标志记忆不够CRYPT_VERIFYCONTEXT与CRYPT_NEWKEYSET的作用在回答中忘记,需要加强记忆。- 建议通过小例子练习使用不同标志创建或连接密钥容器。
-
对
CryptReleaseContext的理解稍浅- 你只说了“清理资源”,可以补充它不仅释放资源,还断开 CSP 连接、保证安全和稳定。
-
部分安全机制理解可以更深入
- 比如为什么公钥可以公开、私钥必须严格保护,可以联系实际应用场景(数字签名、证书验证等)加深记忆。
总体评价
你对 CSP、CryptoAPI 的整体结构和核心功能掌握不错,回答准确度高,逻辑清晰。需要改进的是一些具体函数标志、调用细节和安全机制的深度理解。
Gisli: 不需要。
AI: 明白啦,那我们就先到这里,总结完毕。
学习实践过程遇到的问题与解决方式
如果不使用 CRYPT_VERIFYCONTEXT 标志,而是使用默认设置(需要访问密钥容器),如果应用程序连续多次使用 CRYPT_NEWKEYSET 创建一个同名的密钥容器,会对系统和密钥安全造成什么后果?
AI:
不使用 CRYPT_VERIFYCONTEXT 的情况
- 默认情况下,CryptAcquireContext 会尝试访问指定密钥容器中的私钥。
- 私钥保存在 CSP 内部,如果不使用 CRYPT_VERIFYCONTEXT,应用程序必须有权限访问容器中的密钥。
- 访问失败可能导致函数调用返回错误,例如 NTE_BAD_KEYSET 或 NTE_EXISTS。
使用 CRYPT_NEWKEYSET 创建同名密钥容器
- 第二次及之后尝试创建同名容器会失败,返回 NTE_EXISTS
- 覆盖或丢失原有密钥
- 可能出现多次实例但只保留最后一次的密钥
- CSP 日志可能记录大量错误
为什么CryptoAPI 采用了三层架构,并强制应用程序通过操作系统层来调用底层的 CSP,而不是允许直接调用 CSP 的 DLL?
- 安全隔离
- 统一接口和兼容性
- 密钥管理和持久化
- 审计日志管理
- 简化开发
本文链接
- cnblogs
- https://www.cnblogs.com/gisliw/p/19167402
参考资料
- AI工具(你使用的AI工具及其链接)
- ChatGPT
- 图书
- 《Windows C/C++加密解密实战》