1

ストアからの証明書に問題があります。私のアプリでは、ユーザーはファイルからの証明書またはストアからの証明書を使用できます。証明書を読み込んだ後、署名データに証明書を使用します。

ファイルから証明書を使用しても問題ありませんが、ストアから同等のものを使用することはできません。

記号のコード:

// Sign data
using (RSACryptoServiceProvider csp = new RSACryptoServiceProvider())
{
    byte[] dataToSign = Encoding.UTF8.GetBytes(plainText);
    csp.ImportParameters(((RSACryptoServiceProvider)_certPopl.PrivateKey).ExportParameters(true));
    byte[] signature = csp.SignData(dataToSign, "SHA256");
    // Verify signature
    if (!csp.VerifyData(dataToSign, "SHA256", signature))
        throw new Exception("Nepodařilo se vytvořit platný podpisový kód poplatníka.");
    PKP = Convert.ToBase64String(signature);
}

ファイルから証明書を読み取るためのコード:

X509Certificate2Collection certStore = new X509Certificate2Collection();
certStore.Import(fileName, password, X509KeyStorageFlags.Exportable);
foreach (X509Certificate2 cert in certStore)
{
    // Find the first certificate with a private key
    if (cert.HasPrivateKey)
    {
        _certPopl = cert;
        break;
    }
}

ストアから証明書を読み取るためのコード。ストアから証明書をロードした後、データに署名できません:

public void LoadCertificate(string certificateName, DateTime notAfter, string password)
{
    var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    store.Open(OpenFlags.MaxAllowed);
    foreach (var certificate in store.Certificates)
    {
        if (certificate.FriendlyName.Equals(certificateName) && certificate.NotAfter.Equals(notAfter))
        {
            //X509Certificate2Collection certStore = new X509Certificate2Collection();
            //certStore.Import(certificate.Export(X509ContentType.SerializedCert), password, X509KeyStorageFlags.Exportable);
            //_certPopl = certStore[0];

            X509Certificate2Collection certStore = new X509Certificate2Collection();
            certStore.Import(certificate.GetRawCertData());
            foreach (X509Certificate2 cert in certStore)
            {
                // Find the first certificate with a private key
                if (cert.HasPrivateKey)
                {
                    _certPopl = cert;
                    break;
                }
            }

            break;
        }
    }
}

証明書を扱った経験がありません。しかし、署名のためにストアから証明書を取得するのと同等のものが必要です。

System.Security.Cryptography.CryptographicException が ExportParameters(true) でスローされます。例外の追加情報: キーは指定された状態での使用には無効です。

ありがとう。

4

3 に答える 3

3

.NET 4.6 を使用できる場合、これははるかに簡単です。秘密鍵にアクセスする新しい方法は、SHA-2 署名に対してはるかに確実に機能します。

using (RSA rsa = cert.GetRSAPrivateKey())
{
    if (rsa == null)
    {
        throw new Exception("Wasn't an RSA key, or no private key was present");
    }

    bool isValid = rsa.VerifyData(
        Encoding.UTF8.GetBytes(plainText),
        signature,
        HashAlgorithmName.SHA256,
        RSASignaturePadding.Pkcs1);

    if (!isValid)
    {
        throw new Exception("VerifyData failed");
    }
}
于 2016-11-08T17:40:12.127 に答える
0

動作状態は次のとおりです。

ストアから証明書を読み込んでいます:

var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
    store.Open(OpenFlags.ReadOnly);
    foreach (var certificate in store.Certificates)
    {
        if (certificate.FriendlyName.Equals(certificateName) && certificate.NotAfter.Equals(notAfter))
        {
            _certPopl = certificate;
            break;
        }
    }
}
finally
{
    store.Close();
}

データに署名して検証します。

byte[] dataToSign = Encoding.UTF8.GetBytes(plainText);
var privKey = (RSACryptoServiceProvider)_certPopl.PrivateKey;
// Force use of the Enhanced RSA and AES Cryptographic Provider with openssl-generated SHA256 keys
var enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;
var cspparams = new CspParameters(enhCsp.ProviderType, enhCsp.ProviderName, privKey.CspKeyContainerInfo.KeyContainerName);
privKey = new RSACryptoServiceProvider(cspparams);
byte[] signature = privKey.SignData(dataToSign, "SHA256");
// Verify signature
if (!privKey.VerifyData(dataToSign, "SHA256", signature))
    throw new Exception("Nepodařilo se vytvořit platný podpisový kód poplatníka.");
于 2016-11-08T14:05:23.527 に答える
0

CSP パラメータをエクスポートしようとしている理由がよくわかりません。CSP パラメータのエクスポートはキー エクスポート オプションに依存し、キーがエクスポートできない場合は失敗します。代わりに、オブジェクトのプロパティでRSACryptoServiceProvider直接使用する必要があります。PrivateKeyX509Certificate2

// assuming, you have X509Certificate2 object with existing private key in _certPol variable
// retrieve private key
var key = _certPol.PrivateKey as RSACryptoServiceProvider;
// check if it is legacy RSA, otherwise return.
if (key == null) { return; }
byte[] dataToSign = Encoding.UTF8.GetBytes(plainText);
// sign data
byte[] signature = key.SignData(dataToSign, "SHA256");
// Verify signature
if (!key.VerifyData(dataToSign, "SHA256", signature))
    throw new Exception("Nepodařilo se vytvořit platný podpisový kód poplatníka.");
...
于 2016-11-07T18:12:50.927 に答える