从 PIV 智能卡中提取名称
Posted
技术标签:
【中文标题】从 PIV 智能卡中提取名称【英文标题】:Extract names from PIV smartcard 【发布时间】:2020-09-03 16:52:02 【问题描述】:我正在尝试从 PIV 智能卡中提取以下内容:
-
主题通用名
证书主题替代名称/Microsoft 主体名称
我使用 RedHat 6(最终是 7)和 CoolKey 作为我的 PKCS11 模块。
我需要一种方法来通过代码提取此信息,而不需要智能卡引脚,无论是来自 shell 命令还是智能卡库。目前我可以通过使用 shell 命令 'pkcs11-tools --module -T' 来获取通用名称,因此主题替代名称确实是我所追求的,但我想找到一种更好的方法来获取通用名称(如果可用) .
我知道此信息无需输入密码即可使用,因为我可以在 RHEL (esc) 上包含的智能卡管理器中查看所有信息。如果这很重要,我有根证书链、中间证书链和从属证书链。
我的想法是我必须从卡中提取证书,使用我的本地 CA 验证该证书,然后对其进行解密。我花了几天时间阅读有关 APDU、智能卡和 openssl 的文档,但一无所获。
编辑 RHEL 智能卡管理器视图:
这是您打开卡并查看详细信息时智能卡查看器显示的内容。 Microsoft Principal Name 是我希望从卡片中提取的内容,以及显示在 Hierarchy 部分和其他位置的“通用名称”,由红色文本显示。
我实际上已经切换到使用 pkcs15-tool,因为 pkcs11-tool 截断了更长的常用名称(您可以在屏幕截图的标题栏中看到这一点,同样的问题)。 输出:'pkcs15-tool --list-info'
Using reader with a card: <reader name>
PKCS#15 Card [LASTNAME.FIRSTNAME.MIDDLENAME.12345678]:
Version : 0
Serial number : <big string>
Manufacturer ID : piv_II
Flags :
我当前的方法是简单地将括号中的字符串解析为通用名称,并让用户使用 Redhat 智能卡工具手动输入 Alt Name。
【问题讨论】:
查看PIV specification 我找不到术语主题通用名。 我猜他是指存储在卡上的一个或所有证书的主题 CN。 Subject Common Name 是 Redhat 智能卡管理器所称的,它是插入卡时在 GUI 中显示的名称。运行 pkcs11-tool -T 时,它被列为“令牌标签”。也许这在 PIV 规范的第 41 页上被列为“名称”?至于替代名称,我看到的唯一提及是在第 26 页。 pkcs11-tool 显示的“令牌标签”可以通过C_GetTokenInfo
提取(参见here)。您能否编辑您的答案以包括 pkcs11-tool 的输出和 Redhat 智能卡管理器显示的屏幕截图。一旦我们确定了您正在寻找的内容,我可以为 PKCS#11 提供更具体的代码示例。
【参考方案1】:
通过使用 Java bouncycastle 和 iaik pkcs11 包装器,我能够获得通用名称和 UPN/证书替代名称。
//path to .so library file
Module pkcs11Module = Module.getInstance(this.getProperties().getProperty("PKCS11_LIBRARY"));
pkcs11Module.initialize(null);
Slot[] slotsWithToken = pkcs11Module.getSlotList(Module.SlotRequirement.TOKEN_PRESENT);
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
for(Slot s : slotsWithToken)
Session session = s.getToken().openSession(Token.SessionType.SERIAL_SESSION, Token.SessionReadWriteBehavior.RO_SESSION, null, null);
session.findObjectsInit(new X509PublicKeyCertificate());
Object[] objects = null;
while((objects = session.findObjects(1)).length > 0)
for(Object c : objects)
X509PublicKeyCertificate cert = (X509PublicKeyCertificate) c;
byte[] certValue = cert.getValue().getByteArrayValue();
Certificate cc = certFactory.generateCertificate(new ByteArrayInputStream(certValue));
if(cc instanceof X509Certificate)
X509Certificate x509 = (X509Certificate) cc;
//COMMON NAME:
String name = new X500Name(x509.getSubjectDN().getName()).getRDNs()[0].getFirst().getValue().toString();
Collection<List<?>> altNames = x509.getSubjectAlternativeNames();
for(List<?> list : altNames)
ASN1Sequence seq = ASN1Sequence.getInstance(new ASN1InputStream(new ByteArrayInputStream((byte[]) list.get(1))).readObject());
ASN1TaggedObject obj = (ASN1TaggedObject) seq.getObjectAt(1);
//ALT NAME:
String upn = obj.getObject().toString();
upn = upn.substring(upn.lastIndexOf("]") + 1);
upn 前面附加了“[0]”,我不确定这是为什么,所以我对其进行了操作以消除它。
【讨论】:
以上是关于从 PIV 智能卡中提取名称的主要内容,如果未能解决你的问题,请参考以下文章