Проверка подписи - что является причиной ошибки «Подпись недействительна»? - PullRequest
3 голосов
/ 13 декабря 2011

Мне нужно подписать и подтвердить строку, используя цифровой сертификат моей компании.VerifyHash (хеш, CryptoConfig.MapNameToOID ("SHA1"), подпись);часть возвращает false, поэтому я получаю ошибку «Подпись не действительна».Что я делаю неправильно?Какова наиболее вероятная причина этой ошибки?

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace ConsoleApplication1
{
    class Program
    {
        static byte[] Sign(string text, string certSubject)
        {
            X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            X509Certificate2 myCert = null;
            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
            store.Open(OpenFlags.ReadOnly);
            foreach (X509Certificate2 cert in store.Certificates.Find(X509FindType.FindBySubjectName, certSubject, false))
            {
                myCert = cert;
                break;
            }
            store.Close();
            if (myCert == null)
            {
                throw new Exception("Certificate not found: " + certSubject, null);
            }
            // Hash the data
            SHA1Managed sha1 = new SHA1Managed();
            UnicodeEncoding encoding = new UnicodeEncoding();
            byte[] data = encoding.GetBytes(text);
            byte[] hash = sha1.ComputeHash(data);

            // Sign the hash
            return provider.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
        }

        static bool Verify(string text, byte[] signature, string certPath)
        {
            // Load the certificate we'll use to verify the signature from a file 
            X509Certificate2 cert = new X509Certificate2(certPath);
            // Note: 
            // If we want to use the client cert in an ASP.NET app, we may use something like this instead:
            // X509Certificate2 cert = new X509Certificate2(Request.ClientCertificate.Certificate);

            // Get its associated CSP and public key
            RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PublicKey.Key;

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

            // Verify the signature with the hash
            return csp.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), signature);
        }

        static void Main(string[] args)
        {
            // Usage sample
            try
            {
                // Sign text
                byte[] signature = Sign("Test 123", "Ross cert");

                // Verify signature. 
                if (Verify("Test 123", signature, @"C:\...RossTest.cer"))
                {
                    Console.WriteLine("SUCCESS! Signature verified");
                }
                else
                {
                    Console.WriteLine("ERROR: Signature not valid!");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("EXCEPTION: " + ex.Message);
            }
            Console.ReadKey();
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 13 декабря 2011

Я полагаю, что проблема в том, что в вашем методе знака вы прикладываете много усилий, чтобы получить myCert, но затем никогда не используете его.Вы просто подписываете его вновь созданным неинициализированным RSACryptoServiceProvider.

. Я представляю, что после строки store.Close() вы хотите что-то вроде следующего:

RSACryptoServiceProvider provider = (RSACryptoServiceProvider)cert.PrivateKey;
1 голос
/ 13 декабря 2011
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();

Это единственное место, где provider назначается при подписании данных.Этот код означает, что вы только что создали совершенно новую пару ключей, то есть она не связана с сертификатом, который вы искали.

Когда вы проверяете подпись, вы используете открытый ключ сертификата (а не тот из ключапара, которую вы создали).Так как они не совпадают, вы никогда не получите действительное подтверждение подписи.

IOW вам необходимо подписывать с закрытым ключом, связанным с сертификатом, а не просто с какой-либо парой ключей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...