wake-up-neo.com

Signieren und Überprüfen von Signaturen mit RSA C #

Ich habe kürzlich über Probleme beim Verschlüsseln großer Datenmengen mit RSA geschrieben. Damit bin ich endlich fertig. Jetzt implementiere ich das Signieren mit dem privaten Schlüssel eines Benutzers und überprüfe mit dem entsprechenden öffentlichen Schlüssel. Wenn ich jedoch die signierten Daten mit der Originalnachricht vergleiche, erhalte ich im Grunde nur eine falsche Antwort. Ich hoffe, dass einige von Ihnen sehen können, was ich falsch mache.

Hier ist der Code:

public static string SignData(string message, RSAParameters privateKey)
    {
        //// The array to store the signed message in bytes
        byte[] signedBytes;
        using (var rsa = new RSACryptoServiceProvider())
        {
            //// Write the message to a byte array using UTF8 as the encoding.
            var encoder = new UTF8Encoding();
            byte[] originalData = encoder.GetBytes(message);

            try
            {
                //// Import the private key used for signing the message
                rsa.ImportParameters(privateKey);

                //// Sign the data, using SHA512 as the hashing algorithm 
                signedBytes = rsa.SignData(originalData, CryptoConfig.MapNameToOID("SHA512"));
            }
            catch (CryptographicException e)
            {
                Console.WriteLine(e.Message);
                return null;
            }
            finally
            {
                //// Set the keycontainer to be cleared when rsa is garbage collected.
                rsa.PersistKeyInCsp = false;
            }
        }
        //// Convert the a base64 string before returning
        return Convert.ToBase64String(signedBytes);
    }

Das ist also der erste Schritt, um die Daten zu signieren. Als nächstes gehe ich zur Überprüfung der Daten über:

public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey)
    {
        bool success = false;
        using (var rsa = new RSACryptoServiceProvider())
        {
            byte[] bytesToVerify = Convert.FromBase64String(originalMessage);
            byte[] signedBytes = Convert.FromBase64String(signedMessage);
            try
            {
                rsa.ImportParameters(publicKey);

                SHA512Managed Hash = new SHA512Managed();

                byte[] hashedData = Hash.ComputeHash(signedBytes);

                success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA512"), signedBytes);
            }
            catch (CryptographicException e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                rsa.PersistKeyInCsp = false;
            }
        }
        return success;
    }

Und hier ist der Testclient:

public static void Main(string[] args)
    {
        PublicKeyInfrastructure pki = new PublicKeyInfrastructure();
        Cryptograph crypto = new Cryptograph();
        RSAParameters privateKey = crypto.GenerateKeys("[email protected]");

        const string PlainText = "This is really sent by me, really!";

        RSAParameters publicKey = crypto.GetPublicKey("[email protected]");

        string encryptedText = Cryptograph.Encrypt(PlainText, publicKey);

        Console.WriteLine("This is the encrypted Text:" + "\n " + encryptedText);

        string decryptedText = Cryptograph.Decrypt(encryptedText, privateKey);

        Console.WriteLine("This is the decrypted text: " + decryptedText);

        string messageToSign = encryptedText;

        string signedMessage = Cryptograph.SignData(messageToSign, privateKey);

        //// Is this message really, really, REALLY sent by me?
        bool success = Cryptograph.VerifyData(messageToSign, signedMessage, publicKey);

        Console.WriteLine("Is this message really, really, REALLY sent by me? " + success);

    }

Vermisse ich hier einen Schritt? Gemäß der Cryptography-API und den dortigen Beispielen sollte ich keine Hashes manuell berechnen, da ich den Algorithmus innerhalb des Methodenaufrufs selbst bereitstelle.

Jede Hilfe wird sehr geschätzt.

47
Simon Langhoff

Ihr Problem steht am Anfang der VerifyData -Methode:

public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey)
{
    bool success = false;
    using (var rsa = new RSACryptoServiceProvider())
    {
        //Don't do this, do the same as you did in SignData:
        //byte[] bytesToVerify = Convert.FromBase64String(originalMessage);
        var encoder = new UTF8Encoding();
        byte[] bytesToVerify = encoder.GetBytes(originalMessage);

        byte[] signedBytes = Convert.FromBase64String(signedMessage);
        try
        ...

Aus irgendeinem Grund haben Sie zu FromBase64String Anstatt zu UTF8Encoding.GetBytes Gewechselt.

25
csharptest.net