如何使用 C# 从安全令牌中获取信息

Posted

技术标签:

【中文标题】如何使用 C# 从安全令牌中获取信息【英文标题】:How to get Information from a security token with C# 【发布时间】:2013-02-14 18:41:09 【问题描述】:

我需要让我的应用程序的用户使用他们的个人 USB 安全令牌签署他们的批准。

我已经成功地签署了数据,但我无法获得有关谁的令牌被用于这样做的信息。

这是我目前的代码:

CspParameters csp = new CspParameters(1, "SafeNet RSA CSP");
csp.Flags = CspProviderFlags.UseDefaultKeyContainer;            
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp);
// Create some data to sign. 
byte[] data = new byte[]  0, 1, 2, 3, 4, 5, 6, 7 ;
Console.WriteLine("Data         : " + BitConverter.ToString(data));
// Sign the data using the Smart Card CryptoGraphic Provider.            
byte[] sig = rsa.SignData(data, "SHA1");            
Console.WriteLine("Signature    : " + BitConverter.ToString(sig));

令牌信息中有一个字段,称为“令牌名称”。如何访问该字段以验证已使用哪个令牌签署批准?

其他信息和更新:

“令牌名称”总是匹配所有者的名称(拥有 USB 的用户 令牌) 好像不行,可能有网络服务或者 我需要打电话才能直接获取信息 来自证书颁发机构。

【问题讨论】:

也许这更像是 security.stachexchange.com 的一个问题? 看起来您需要提取Modulus 作为证书指纹,然后与所有可用证书指纹的数据库进行比较。可能类似于byte[] modulus = rsa.ExportParameters(false).Modulus; @oleksii 我没有模数数据库。我需要获取“令牌名称”并将其与当前的 AD 用户名进行比较。感谢您的评论。 我不太确定什么是令牌,它是私有 RSA 证书吗?我认为您根本无法将此类信息嵌入证书中。你需要一个你可以信任的第三方,即你的数据库,第三方要么承认这个指纹是用于 Bob 的私人证书的,要么它会拒绝它。例如,如果您将用户名嵌入到私有证书中,那么任何人都可以创建一个新的私有证书并声称自己是 Bob。你怎么能相信呢? 令牌名称是硬件独有的还是标准的一部分?它的存储方式很可能是您无法通过标准库获取的。 【参考方案1】:

当我最初问这个问题时,我对数字证书的理解非常基础,所以这个问题没有被正确地问出来。现在我知道我需要从智能卡设备访问证书,查询其属性并测试用户是否可以为其输入正确的 PIN。

这是我以前这样做的代码:

//Prompt the user with the list of certificates on the local store.
//The user have to select the certificate he wants to use for signing.
//Note: All certificates form the USB device are automatically copied to the local store as soon the device is plugged in.
X509Store store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509CertificateCollection certificates = X509Certificate2UI.SelectFromCollection(store.Certificates,
                                                                                "Certificados conocidos",
                                                                                "Por favor seleccione el certificado con el cual desea firmar",
                                                                                X509SelectionFlag.SingleSelection
                                                                                );
store.Close();
X509Certificate2 certificate = null;
if (certificates.Count != 0)

    //The selected certificate
    certificate = (X509Certificate2)certificates[0];

else

    //The user didn't select a certificate
    return "El usuario canceló la selección de un certificado";

//Check certificate's atributes to identify the type of certificate (censored)
if (certificate.Issuer != "CN=............................., OU=................., O=..., C=US")

    //The selected certificate is not of the needed type
    return "El certificado seleccionado no corresponde a un token ...";

//Check if the certificate is issued to the current user
if (!certificate.Subject.ToUpper().Contains(("E=" + pUserADLogin + "@censoreddomain.com").ToUpper()))

    return "El certificado seleccionado no corresponde al usuario actual";

//Check if the token is currently plugged in
XmlDocument xmlDoc = new XmlDocument();
XmlElement element = xmlDoc.CreateElement("Content", SignedXml.XmlDsigNamespaceUrl.ToString());
element.InnerText = "comodin";
xmlDoc.AppendChild(element);
SignedXml signedXml = new SignedXml();
try

    signedXml.SigningKey = certificate.PrivateKey;

catch

    //USB Token is not plugged in
    return "El token no se encuentra conectado al equipo";

DataObject dataObject = new DataObject();
dataObject.Data = xmlDoc.ChildNodes;
dataObject.Id = "CONTENT";
signedXml.AddObject(dataObject);
Reference reference = new Reference();
reference.Uri = "#CONTENT";
signedXml.AddReference(reference);
//Attempt to sign the data. The user will be prompted to enter his PIN
try

    signedXml.ComputeSignature();

catch

    //User didn't enter the correct PIN
    return "Hubo un error confirmando la identidad del usuario";

//The user has signed with the correct token
return String.Format("El usuario 0 ha firmado exitosamente usando el token con serial 1", pUserADLogin, certificate.SerialNumber);

来源:

http://stormimon.developpez.com/dotnet/signature-electronique/(法语) https://www.simple-talk.com/content/print.aspx?article=1713(英文)

【讨论】:

还有另一种获取令牌名称的方法。您必须使用 PKCS#11 或 CryptoAPI 接口来检测插入了哪个 tokane。这与您根据证书主题名称检测令牌名称的方法不同。

以上是关于如何使用 C# 从安全令牌中获取信息的主要内容,如果未能解决你的问题,请参考以下文章

Spring OAuth/JWT 从访问令牌中获取额外信息

如何从谷歌 api 令牌中获取数据?

如何从 RESTful 服务发送安全令牌?

如何使用用户名和传递以及 SSIS 中的动态令牌从 API 获取数据

从不记名令牌中获取信息

如何在 Angular 4 中处理安全会话