Recientemente he publicado acerca de los problemas con el cifrado de datos de gran tamaño con RSA, por fin estoy hecho con eso y ahora me estoy moviendo en la puesta en práctica de la firma con la clave privada del usuario y verificar con la clave pública correspondiente. Sin embargo, cuando comparamos los datos firmados y el mensaje original yo, básicamente, sólo false devuelve. Tengo la esperanza de que algunos de sus pudiera ver lo que estoy haciendo mal.

Aquí está el código:

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);
    }

De modo que es el primer paso, para firmar los datos, el siguiente paso para la verificación de los datos:

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;
    }

Y aquí es el cliente de prueba:

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);

    }

Que me estoy perdiendo un paso aquí? De acuerdo a la API de Criptografía y los ejemplos que hay, no me manualmente calcular cualquier hash, ya que la oferta del algoritmo dentro de la llamada al método en sí.

Cualquier ayuda será muy apreciada.

1 Comentario

  1. 25

    El problema está en el principio de la VerifyData método:

    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
            ...

    Por algún motivo se cambia a FromBase64String en lugar de UTF8Encoding.GetBytes.

    • También, para la firma de datos, debe utilizar la clave privada, a continuación, utilizar la clave pública para descifrar los datos que fue firmado con la clave privada. Esto es debido a que distribuir la clave pública, no con la clave privada.
    • Yo sé que hay un tamaño máximo de la cadena de RSA puede cifrar. Hay un máximo de tamaño de la cadena de RSA puede firmar así ? o puede firmar una cadena de cualquier longitud ?

Dejar respuesta

Please enter your comment!
Please enter your name here