5

私はスマートカードを持っていて、これでファイルに署名する必要があります。スタックオーバーで見られるように、これは大きな問題です。

RSACryptoServiceProvider を使用できませんでした。bkz は RSA-SHA256 アルゴリズムをサポートしていません。

最初は、以下のコードのように CAPICOM.dll を使用しました。

SignedData sed = new SignedData();
sed.Content = "a"; // data to sign
Signer ser = new Signer();
ser.Certificate = cc;
string singnn = sed.Sign(ser, false, CAPICOM_ENCODING_TYPE.CAPICOM_ENCODE_BASE64);

しかし、署名値を検証するための公開鍵がありません。capicom.dll から検証鍵を取得できませんでした。

以降 、

以下のコードのように X509Certificate2 と RSACryptoServiceProvider を使用しました。

        X509Certificate2 certificate = new X509Certificate2();
        // Access Personal (MY) certificate store of current user
        X509Store my = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        my.Open(OpenFlags.ReadOnly);

        // Find the certificate we'll use to sign            
        RSACryptoServiceProvider csp = null;
        foreach (X509Certificate2 cert in my.Certificates)
        {
            if (cert.Subject.Contains(certSubject))
            {
                // We found it. 
                // Get its associated CSP and private key
                certificate = cert;
                csp = (RSACryptoServiceProvider)cert.PrivateKey;
            }
        }
        if (csp == null)
        {
            throw new Exception("No valid cert was found");
        }

        // Hash the data
        SHA1Managed sha1 = new SHA1Managed();
        UnicodeEncoding encoding = new UnicodeEncoding();
        byte[] data = encoding.GetBytes(text);
        byte[] hash = sha1.ComputeHash(data);

        //byte[] data = Encoding.UTF8.GetBytes(text);
        //HashAlgorithm sha = new SHA256Managed();
        //byte[] hash = sha.TransformFinalBlock(data, 0, data.Length);

        string key = csp.ToXmlString(false);
        // Sign the hash
        csp.PersistKeyInCsp = true;
        byte[] response = csp.SignData(data, CryptoConfig.MapNameToOID("SHA1"));
        string signbase64 = Convert.ToBase64String(response);

動作しますが、RSA-SHA256 アルゴリズムで署名する必要があります。このようにハッシュアルゴリズムを変更すると

byte[] response = csp.SignData(data, CryptoConfig.MapNameToOID("SHA256"));

私は取得しています

error : 「特定されていないエラー」。

それが私の問題です。解決策は何ですか、またはどのライブラリを使用する必要がありますか??

アドバイスをありがとう..

4

1 に答える 1

13

RSACryptoServiceProvider は SHA2 ベースの署名で動作しますが、ある程度の労力を費やす必要があります。

証明書を使用して RSACryptoServiceProvider を取得する場合、基になる CryptoAPI プロバイダーが何であるかが本当に重要になります。デフォルトでは、「makecert」で証明書を作成すると、署名に SHA1 ハッシュのみをサポートする「RSA-FULL」になります。SHA2 をサポートする新しい「RSA-AES」が必要です。

したがって、追加オプション -sp "Microsoft Enhanced RSA and AES Cryptographic Provider" (または同等の -sy 24) を使用して証明書を作成すると、コードは (.NET 4.0 の場合) 次のようになります。

var rsa = signerCertificate.PrivateKey as RSACryptoServiceProvider;
//
byte[] signature = rsa.SignData(data, CryptoConfig.CreateFromName("SHA256"));

証明書の発行方法を変更できない場合は、RSACryptoServiceProvider がデフォルトで SHA2 をサポートするように作成されているという事実に基づいた、ある程度正当な回避策があります。したがって、次のコードも機能しますが、少し醜いです: (このコードが行うことは、新しい RSACryptoServiceProvider を作成し、証明書から取得したものからキーをインポートすることです)

var rsa = signerCertificate.PrivateKey as RSACryptoServiceProvider;
// Create a new RSACryptoServiceProvider
RSACryptoServiceProvider rsaClear = new RSACryptoServiceProvider();
// Export RSA parameters from 'rsa' and import them into 'rsaClear'
rsaClear.ImportParameters(rsa.ExportParameters(true));
byte[] signature = rsaClear.SignData(data, CryptoConfig.CreateFromName("SHA256"));

これがお役に立てば幸いです。

于 2012-05-31T08:46:28.457 に答える