Как проверить, подключен ли DSC (USB-токен) при подписании документа?

Я подписываю XML-документ цифровой подписью. Вот мой код:

private void mbSign_Click_1(object sender, EventArgs e)
{
    try
    {
            CadesSignature cs = new CadesSignature(FStrDSCSNo);
                            cs.DigitalSignatureCertificate = DigitalCertificate.LoadCertificate(false, string.Empty, "Select Certificate", "Select the certificate for digital signature");
                            RSACryptoServiceProvider rsaEncryptor = (RSACryptoServiceProvider)cs.DigitalSignatureCertificate.PrivateKey;

        L_ADSC_ValidTo = cs.DigitalSignatureCertificate.NotAfter.ToShortDateString();

        if (DateTime.Now <= DateTime.ParseExact(L_ADSC_ValidTo, "dd/MM/yyyy", null))
                        {
                            FObjLog.WriteToLog("Valid DSC");
                            L_ADSC_CertStatus = "A";
                            // Sign the XML document.
                            //DataTable dt_SignXMlAndSignaute = new DataTable();
                            SignXml(rsaEncryptor);
                        }
}

catch (CryptographicException)
            {
                MessageBox.Show("Invalid DSC Selection.Please Choose Correct DSC");
                FObjLog.WriteToLog("Invalid DSC Selection.Please Choose Correct DSC");
            }
            catch (NullReferenceException)
            {
                MessageBox.Show("Please Attach DSC");
                FObjLog.WriteToLog("Please Attach DSC");
            }

  }
public void SignXml(RSA Key)
        {
XmlDocument LXMLDoc = new XmlDocument();
            if (File.Exists(LXMLPath))
            {
                LXMLDoc.Load(LXMLPath);
            }
                if (LXMLDoc == null)
                    throw new ArgumentException("LXMLDoc");
                if (Key == null)
                    throw new ArgumentException("Key");

                // Create a SignedXml object.
                SignedXml signedXml = new SignedXml(LXMLDoc);

                // Add the key to the SignedXml document.
                signedXml.SigningKey = Key;

                // Create a reference to be signed.
                Reference reference = new Reference();
                //reference.Uri = txtfilepath.Text;
                reference.Uri = "";

                // Add an enveloped transformation to the reference.
                XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
                reference.AddTransform(env); // calculating Digest value

                // Add the reference to the SignedXml object.
                signedXml.AddReference(reference);

                // Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
                KeyInfo keyInfo = new KeyInfo();
                keyInfo.AddClause(new RSAKeyValue((RSA)Key));
                signedXml.KeyInfo = keyInfo;

                signedXml.ComputeSignature();

                string FullSignatureValue = "";
                string SignatureValue = "";
                XmlElement xmlDigitalSignature = signedXml.GetXml();
                FullSignatureValue = xmlDigitalSignature.InnerText;
                string[] Sign = FullSignatureValue.Split(new char[] { '=' }, 2);


                SignatureValue = Sign[1].ToString();

                signedXml = new SignedXml(LXMLDoc);
LXMLDoc.DocumentElement.AppendChild(LXMLDoc.ImportNode(xmlDigitalSignature, true));
}

Здесь я могу подписать документ, но не могу проверить, подключен ли USB-токен во время подписания. Здесь происходит то, что даже если USB-токен не подключен, сертификат появится для выбора, потому что сертификат доступен локально. Когда вы удаляете все сертификаты из Internet Explorer и пытаетесь подписать с неподключенным USB-токеном, он просит подключить карту DSC (USB-токен). Я хочу подписать документ только тогда, когда подключен DSC (USB-токен). Как убедиться, что USB подключен во время подписания?


person Rakesh    schedule 18.04.2017    source источник


Ответы (2)


Системные интерфейсы CryptoAPI и CNG (и классы .NET, использующие эти интерфейсы) предлагают высокоуровневые абстракции, которые не позволяют проверить оборудование. Если вы используете интерфейс PKCS # 11, вы можете достичь того, чего хотите. Однако у PKCS#11 есть и свои недостатки.

person Eugene Mayevski 'Callback    schedule 30.04.2017

CryptoAPI и CNG не раскрывают информацию о состоянии карты, для этого вам нужен WINSCARD. В частности, вы хотите вызвать SCARDGetStatusChange.

private void WaitChangeStatus(object sender, DoWorkEventArgs e)
    {
        while (!e.Cancel)
        {
            SmartCardErrorCode result;

            // Obtain a lock when we use the context pointer, which may be modified in the Dispose() method.
            lock (this)
            {
                if (!this.HasContext)
                {
                    return;
                }

                // This thread will be executed every 1000ms. 
                // The thread also blocks for 1000ms, meaning 
                // that the application may keep on running for 
                // one extra second after the user has closed the Main Form.
                result = (SmartCardErrorCode)UnsafeNativeMethods.GetStatusChange(this.context, 1000, this.states, (uint)this.states.Length);
            }

            if ((result == SmartCardErrorCode.Timeout))
            {
                // Time out has passed, but there is no new info. Just go on with the loop
                continue;
            }
            else if (result != SmartCardErrorCode.Succeeed)
            {
                // TODO OnExceptionRaised
                continue;
            }

            for (int i = 0; i <= this.states.Length - 1; i++)
            {
                // Check if the state changed from the last time.
                if ((this.states[i].EventState & CardState.Changed) == CardState.Changed)
                {
                    // Check what changed.
                    SmartCardState state = SmartCardState.None;
                    if ((this.states[i].EventState & CardState.Present) == CardState.Present
                        && (this.states[i].CurrentState & CardState.Present) != CardState.Present)
                    {
                        // The card was inserted.                            
                        state = SmartCardState.Inserted;
                    }
                    else if ((this.states[i].EventState & CardState.Empty) == CardState.Empty
                        && (this.states[i].CurrentState & CardState.Empty) != CardState.Empty)
                    {
                        // The card was ejected.
                        state = SmartCardState.Ejected;
                    }
                    if (state != SmartCardState.None && this.states[i].CurrentState != CardState.Unaware)
                    {
                        SmartCardEventArgs args = new SmartCardEventArgs();
                        args.Manager = this;

                        switch(state)
                        {
                            case SmartCardState.Inserted:
                            {
                                // Checa o ATR para monitorar apenas DESFire EV1
                                if (OnCardInserted != null)
                                {
                                    // Obtém o ATR
                                    byte[] atr = this.GetAtr(this.states[i].ATRBytes, this.states[i].ATRLength);

                                    // Cria SmartCard object and associa ao EventArgs
                                    SmartCard card = new SmartCard(atr);
                                    args.Card = card;

                                    // Dispara Evento
                                    OnCardInserted(this, args);
                                }
                                break;
                            }
                            case SmartCardState.Ejected:
                            {
                                if (OnCardRemoved != null)
                                {
                                    OnCardRemoved(this, args);
                                }
                                break;
                            }
                            default:
                            {
                                // TODO Log

                                // Null to force Garbage Collection
                                args = null; 

                                break;
                            }
                        }
                    }

                    //Update the current state for the next time they are checked.
                    this.states[i].CurrentState = this.states[i].EventState;
                }
            }
        }
    }
person rmhrisk    schedule 24.05.2017