简体   繁体   English

使用 GetRSAPrivateKey 和 .net 内核以编程方式设置智能卡 PIN

[英]Setting smartcard PIN programmatically using GetRSAPrivateKey and .net core

I have been using an extension method found at this link for years, to access the certificate on a smart card and supply the PIN programmatically without opening the request PIN mask to the user.多年来,我一直在使用此链接上的扩展方法来访问智能卡上的证书并以编程方式提供 PIN,而无需向用户打开请求 PIN 掩码。 Now with new versions of .net core it no longer works, so I'm trying to fix it.现在使用新版本的 .net 内核它不再工作,所以我正在尝试修复它。

I know that now with new versions of the framework it is better to use我知道现在有了新版本的框架,最好使用

RSA rsa = certificate.GetRSAPrivateKey();

however in this way I have no access to the CspKeyContainerInfo (KeyContainerName, ProviderName, ProviderType) required to call the native methods that provide PIN但是通过这种方式,我无法访问调用提供 PIN 的本机方法所需的 CspKeyContainerInfo (KeyContainerName, ProviderName, ProviderType)

Is there any way to access the same information using the RSA object?有没有办法使用 RSA object 访问相同的信息?

Or is there a better / newer method to provide the PIN of the smart card by program?还是有更好/更新的方法来通过程序提供智能卡的 PIN 码?

The code that you have works only when the private key is provided by Windows CAPI.只有当私钥由 Windows CAPI 提供时,您拥有的代码才有效。 If the private key is provided by Windows CNG you need to do the CNG form of it.如果私钥是由 Windows CNG 提供的,你需要做它的 CNG 形式。

private static RSA GetRSAPrivateKeyWithPin(this X509Certificate2 cert, string pin)
{
    RSA rsa = cert.GetRSAPrivateKey();

    if (rsa is RSACryptoServiceProvider rsaCsp)
    {
        // Current code
        SetPin(rsaCsp);
        return rsa;
    }

    if (rsa is RSACng rsaCng)
    {
        // Set the PIN, an explicit null terminator is required to this Unicode/UCS-2 string.

        byte[] propertyBytes;

        if (pin[pin.Length - 1] == '\0')
        {
            propertyBytes = Encoding.Unicode.GetBytes(pin);
        }
        else
        {
            propertyBytes = new byte[Encoding.Unicode.GetByteCount(pin) + 2];
            Encoding.Unicode.GetBytes(pin, 0, pin.Length, propertyBytes, 0);
        }

        const string NCRYPT_PIN_PROPERTY = "SmartCardPin";

        CngProperty pinProperty = new CngProperty(
            NCRYPT_PIN_PROPERTY,
            propertyBytes,
            CngPropertyOptions.None);

        rsaCng.Key.SetProperty(pinProperty);
        return rsa;
    }

    // If you're on macOS or Linux neither of the above will hit. There's
    // also no standard model for setting a PIN on either of those OS families.
    rsa.Dispose();
    throw new NotSupportedException($"Don't know how to set the PIN for {rsa.GetType().FullName}");
}

RSACng PIN-set code copied from https://stackoverflow.com/a/42630670/6535399 ;https://stackoverflow.com/a/42630670/6535399复制的 RSACng PIN 设置代码; because this question seems like it has better discovery, and the answer is more general here.因为这个问题似乎有更好的发现,这里的答案更笼统。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM