如何仅使用UWP API枚举读卡器中当前存在的智能卡的所有可用密钥
符合约束的UWP实现方案
核心思路
避免直接遍历全局证书存储触发无效私钥访问,改为先枚举当前物理存在的智能卡读卡器和已插入卡片,再读取实体卡关联的证书和密钥,从根源上排除不存在的智能卡对应的无效条目,不会触发插卡弹窗。
前置配置
在UWP项目的Package.appxmanifest中声明两项权限:
sharedUserCertificates:用于访问用户证书存储内的智能卡证书smartCard:用于枚举智能卡读卡器和访问卡片信息
实现代码
using Windows.Devices.SmartCards; using Windows.Security.Cryptography.Certificates; using System.Collections.Generic; using System.Threading.Tasks; public async Task<List<Certificate>> GetValidSmartCardCertificatesAsync() { List<Certificate> validCerts = new List<Certificate>(); // 枚举系统所有智能卡读卡器 var allReaderIds = await SmartCardReader.GetDevicesAsync(SmartCardReaderKind.Any); foreach (var readerId in allReaderIds) { SmartCardReader reader = await SmartCardReader.FromIdAsync(readerId); if (reader == null) continue; // 跳过无卡插入的读卡器 SmartCardReaderStatus status = await reader.GetStatusAsync(); if (status != SmartCardReaderStatus.CardPresent) continue; // 读取当前读卡器内的所有实体卡 IReadOnlyList<SmartCard> cards = await reader.FindAllCardsAsync(); foreach (var card in cards) { // 读取卡关联的证书 Certificate cardCert = await card.GetCertificateAsync(); if (cardCert != null && cardCert.HasPrivateKey) { validCerts.Add(cardCert); } // 若单卡存在多个密钥容器,遍历获取所有对应证书 IReadOnlyList<SmartCardKeyContainer> containers = await card.GetKeyContainersAsync(); foreach (var container in containers) { Certificate containerCert = await container.GetCertificateAsync(); if (containerCert != null && containerCert.HasPrivateKey && !validCerts.Contains(containerCert)) { validCerts.Add(containerCert); } } } } return validCerts; }
说明
- 方案全程使用UWP原生API实现,未调用任何Win32桌面API,符合仅使用UWP API的约束
- 仅枚举当前读卡器内物理存在的智能卡对应的证书和密钥,自动过滤系统残留的无效智能卡证书条目,不会触发Windows插入智能卡的弹窗,符合过滤非物理存在卡密钥的约束
- 若需要获取RSA私钥实例,可对返回的
Certificate对象调用GetRSAPrivateKey()方法,因为已提前确认对应实体卡存在,不会触发弹窗
内容的提问来源于stack exchange,提问作者Andrew Webb
相关产品推荐
相关产品推荐

