Класс EnvelopedCms в .NET Framework не позволяет легко программно применить PIN-код (или другой механизм разблокировки);особенно если сертификат существует в хранилищах CurrentUser \ My или LocalMachine \ My (потому что они ищутся до каких-либо сертификатов в коллекции extraStore).
В .NET Framework 4.7+ вы можете выполнить его очень быстро.обходной способ для ключей, доступных для CNG, при условии, что сертификат также отсутствует в хранилищах CurrentUser \ My или LocalMachine \ My:
CngKey key = ExerciseLeftToTheReader();
key.SetProperty(new CngProperty("SmartCardPin", pin, CngPropertyOptions.None));
X509Certificate2 cert = DifferentExerciseLeftToTheReader();
// You need to use tmpCert because this won't do good things if the certificate
// already knows about/how-to-find its associated private key
using (key)
using (X509Certificate2 tmpCert = new X509Certificate2(cert.RawData))
{
// Need to NOT read the HasPrivateKey property until after the property set. Debugger beware.
NativeMethods.CertSetCertificateContextProperty(
tmpCert.Handle,
CERT_NCRYPT_KEY_HANDLE_PROP_ID,
CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG,
key.Handle);
envelopedCms.Decrypt(new X509Certificate2Collection(tmpCert));
}
(и, конечно, вам необходимо определить P / Invoke для CertSetCertificateContextProperty)
В .NET Core 3.0 это становится проще (предварительный просмотр 2 в настоящее время доступен с этой функцией) ... хотя на вас и остается бремя определения, какой вы RecipientInfo, и какой ключ к нему подходит:
RecipientInfo recipientInfo = FigureOutWhichOneYouCanMatch();
CngKey key = ExerciseLeftToTheReader();
key.SetProperty(new CngProperty("SmartCardPin", pin, CngPropertyOptions.None));
using (key)
using (RSA rsa = new RSACng(key))
{
envelopedCms.Decrypt(recipientInfo, rsa);
}