覆盖X509Certificate2 PIN行为

时间:2017-06-12 11:49:31

标签: c# digital-signature x509certificate x509certificate2

我正在尝试使用智能卡设备一次执行3种类型的数字签名(SHA256),XML,PDF和文本。所有签名都运行正常,但问题是,每次签名时都会要求PIN,但我只需要一次签名。任何人都可以提出更好的方法来实现结果吗?

我想要实现的是,

Ask pin -> Sign XML -> Sign PDF -> Sign TEXT

发生的事情是,

Ask pin -> Sign XML -> Ask pin -> Sign PDF -> Ask pin -> Sign TEXT

然后我为PDF和TEXT签名创建了一个公共cmssiger对象。

现在发生了什么,

Ask pin -> Sign XML -> Ask pin -> Sign PDF -> Sign TEXT

我希望每个人都明白我在说什么。

每个签名过程的代码如下, 的 XML

XAdESSignedXml signer = new XAdESSignedXml(toSign);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa = cert.PrivateKey as RSACryptoServiceProvider;
signer.SigningKey = rsa;
/*.......Elements attached......*/
signer.ComputeSignature();

PDF

private byte[] SignMsg(Byte[] msg, bool detached)
{
    ContentInfo contentInfo = new ContentInfo(msg);
    SignedCms signedCms = new SignedCms(contentInfo, detached);
    _cmsSigner.IncludeOption = X509IncludeOption.EndCertOnly;//common cmssigner object
    _cmsSigner.DigestAlgorithm.FriendlyName = "SHA256";
    signedCms.ComputeSignature(_cmsSigner, false);
    byte[] bb = signedCms.Encode();
    CmsSignedData sd = new CmsSignedData(bb);
    SignerInformationStore signers = sd.GetSignerInfos();
    byte[] signature = null;
    SignerInformation signer = null;
    foreach (SignerInformation signer_ in signers.GetSigners())
    {
        signer = signer_;
        break;
    }
    signature = signer.GetSignature();
    signer = SignerInformation.ReplaceUnsignedAttributes(signer, null);
    IList signerInfos = new ArrayList();
    signerInfos.Add(signer);
    sd = CmsSignedData.ReplaceSigners(sd, new SignerInformationStore(signerInfos));
    bb = sd.GetEncoded();
    return bb;
}

文字

public static string Sign(string msg, CmsSigner cmsSigner) //common cmssigner object
{
    SHA256Managed crypt = new SHA256Managed();
    string hash = String.Empty;
    byte[] crypto = crypt.ComputeHash(Encoding.UTF8.GetBytes(msg), 0, Encoding.UTF8.GetByteCount(msg));
    foreach (byte theByte in crypto)
    {
        hash += theByte.ToString("x2");
    }
    ContentInfo contentInfo = new ContentInfo(Encoding.UTF8.GetBytes(hash));
    SignedCms cms = new SignedCms(contentInfo);
    cmsSigner.IncludeOption = X509IncludeOption.EndCertOnly;
    cmsSigner.DigestAlgorithm.FriendlyName = "SHA256";
    cms.ComputeSignature(cmsSigner, false);
    return Convert.ToBase64String(cms.Encode());
}

提前致谢。

1 个答案:

答案 0 :(得分:0)

Pin prompt behavior is a provider specific implementation detail. In other words, one cryptographic service provider / key storage provider will behave one way while another will behave another.

To reduce chances of pin prompting you will want to use one session for all operations, it sounds like you are doing that though so were back to the provider-specific behavior.

In the case of RSACryptoServiceProvider a key can be generated and stored in such a way it enforces an on-use pin prompt policy. This is really the only pin prompt behavior it exposes, as such your stuck with the observed behavior with such keys.