none
hacer hash clase compleja RRS feed

  • Pregunta

  • Buenos días,

    Me gustaría saber si es posible crear un hash con MD5 por ejemplo de una clase compleja.

    Por ejemplo obtener un hash de una clase Alumno que tenga las propiedades Nombre, Apellidos y DNI.

    Un saludo.

    viernes, 27 de octubre de 2017 9:07

Respuestas

  • Buenas,

    acabo de darme cuenta que la pregunta es en vb.Net, asi que te pongo el programa traducido:

    • Hash
    Imports System.Text
    Imports System.Security.Cryptography
    Imports System.IO
    Imports System.Runtime.Serialization.Formatters.Binary
    Imports System.Runtime.Serialization
    Imports System.Reflection
    
    ''' <summary>
    ''' This class takes an object, and generates a key to it. There are several possibilities:
    ''' This generator can generate keys of type integer,float,double. The generated key is not necessarly
    ''' unique!
    ''' </summary>
    Public Class MD5HashGenerator
        Private Shared ReadOnly locker As New [Object]()
    
        ''' <summary>
        ''' Generates a hashed - key for an instance of a class.
        ''' The hash is a classic MD5 hash (e.g. BF20EB8D2C4901112179BF5D242D996B). So you can distinguish different 
        ''' instances of a class. Because the object is hashed on the internal state, you can also hash it, then send it to
        ''' someone in a serialized way. Your client can then deserialize it and check if it is in
        ''' the same state.
        ''' The method just just estimates that the object implements the ISerializable interface. What's
        ''' needed to save the state or so, is up to the implementer of the interface.
        ''' <b>The method is thread-safe!</b>
        ''' </summary>
        ''' <param name="sourceObject">The object you'd like to have a key out of it.</param>
        ''' <returns>An string representing a MD5 Hashkey corresponding to the object or null if the object couldn't be serialized.</returns>
        ''' <exception cref="ApplicationException">Will be thrown if the key cannot be generated.</exception>
        Public Shared Function GenerateKey(sourceObject As [Object]) As [String]
            Dim hashString As [String] = ""
    
            'Catch unuseful parameter values
            If sourceObject Is Nothing Then
                Throw New ArgumentNullException("Null as parameter is not allowed")
            Else
                'We determine if the passed object is really serializable.
                Try
                    'Now we begin to do the real work.
                    hashString = ComputeHash(ObjectToByteArray(sourceObject))
                    Return hashString
                Catch ame As AmbiguousMatchException
                    Throw New ApplicationException("Could not definitly decide if object is serializable. Message:" + ame.Message)
                End Try
            End If
        End Function
    
        ''' <summary>
        ''' Converts an object to an array of bytes. This array is used to hash the object.
        ''' </summary>
        ''' <param name="objectToSerialize">Just an object</param>
        ''' <returns>A byte - array representation of the object.</returns>
        ''' <exception cref="SerializationException">Is thrown if something went wrong during serialization.</exception>
        Private Shared Function ObjectToByteArray(objectToSerialize As [Object]) As Byte()
            Dim fs As New MemoryStream()
            Dim formatter As New BinaryFormatter()
            Try
                'Here's the core functionality! One Line!
                'To be thread-safe we lock the object
                SyncLock locker
                    formatter.Serialize(fs, objectToSerialize)
                End SyncLock
                Return fs.ToArray()
            Catch se As SerializationException
                Console.WriteLine("Error occured during serialization. Message: " + se.Message)
                Return Nothing
            Finally
                fs.Close()
            End Try
        End Function
    
        ''' <summary>
        ''' Generates the hashcode of an given byte-array. The byte-array can be an object. Then the
        ''' method "hashes" this object. The hash can then be used e.g. to identify the object.
        ''' </summary>
        ''' <param name="objectAsBytes">bytearray representation of an object.</param>
        ''' <returns>The MD5 hash of the object as a string or null if it couldn't be generated.</returns>
        Private Shared Function ComputeHash(objectAsBytes As Byte()) As String
            Dim md5 As MD5 = New MD5CryptoServiceProvider()
            Try
                Dim result As Byte() = md5.ComputeHash(objectAsBytes)
    
                ' Build the final string by converting each byte
                ' into hex and appending it to a StringBuilder
                Dim sb As New StringBuilder()
                For i As Integer = 0 To result.Length - 1
                    sb.Append(result(i).ToString("X2"))
                Next
    
                ' And return it
                Return sb.ToString()
            Catch ane As ArgumentNullException
                'If something occured during serialization, this method is called with an null argument. 
                Console.WriteLine("Hash has not been generated.")
                Return Nothing
            End Try
        End Function
    End Class

    • Module1
    Imports System.Collections.Generic
    Imports System.Linq
    Imports System.Text
    Imports System.Threading.Tasks
    
    Module Module1
        Sub Main()
            Dim Alumno1 As New Alumno() With {.Nombre = "Jorge", .Apellido = "Turrado", .DNI = "1234"}
            Dim Alumno2 As New Alumno() With {.Nombre = "Jorge", .Apellido = "Turrado", .DNI = "1234"}
            Dim Alumno3 As New Alumno() With {.Nombre = "Jorge", .Apellido = "Turrado", .DNI = "4321"}
            Dim HashAlumno1 As String = MD5HashGenerator.GenerateKey(Alumno1)
            Dim HashAlumno2 As String = MD5HashGenerator.GenerateKey(Alumno2)
            Dim HashAlumno3 As String = MD5HashGenerator.GenerateKey(Alumno3)
            Dim Alumno1_Alumno2 As Boolean = HashAlumno1 = HashAlumno2
            Dim Alumno1_Alumno3 As Boolean = HashAlumno1 = HashAlumno3
            Console.WriteLine(Alumno1.ToString())
            Console.WriteLine(Alumno2.ToString())
            Console.WriteLine(Alumno3.ToString())
            Console.WriteLine("El Alumno1 y el Alumno2 son iguales? {0}", Alumno1_Alumno2)
            Console.WriteLine("El Alumno1 y el Alumno3 son iguales? {0}", Alumno1_Alumno3)
            Console.ReadLine()
        End Sub
    End Module
    
    
    <Serializable>
    Class Alumno
        Public Property Nombre As String
            Get
                Return m_Nombre
            End Get
            Set
                m_Nombre = Value
            End Set
        End Property
        Private m_Nombre As String
        Public Property Apellido() As String
            Get
                Return m_Apellido
            End Get
            Set
                m_Apellido = Value
            End Set
        End Property
        Private m_Apellido As String
        Public Property DNI() As String
            Get
                Return m_DNI
            End Get
            Set
                m_DNI = Value
            End Set
        End Property
        Private m_DNI As String
        Public Overrides Function ToString() As String
            Return "Nombre: {Nombre}" & vbTab & "Apellido: {Apellido}" & vbTab & "DNI:{DNI}"
        End Function
    End Class

    La explicación es la del post anterior, en este solo he traducido el código.

    Lo dicho, si tienes dudas, comentanos

    Atte


    No olvides votar mi comentario si te ha ayudado y marcarlo como respuesta si ha sido la solución, con eso ayudas a mejorar mi reputación en la comunidad y a identificar la respuesta a la gente que tenga el mismo problema.

    Para obtener una respuesta lo más rápida y concisa posible, te recomiendo:



    • Marcado como respuesta Vicdeju viernes, 27 de octubre de 2017 10:30
    • Editado Jorge TurradoMVP viernes, 27 de octubre de 2017 10:40
    viernes, 27 de octubre de 2017 10:14

Todas las respuestas

  • Buenas,

    Para lo que quieres, revisa este link:

    Generating MD5 Hash out of C# Objects

    Basicamente, lo que hace es generar una clase que se encarga de hacerlo:

    using System;
    using System.Text;
    using System.Security.Cryptography;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.Runtime.Serialization;
    using System.Reflection;
    
    /// <summary>
    /// This class takes an object, and generates a key to it. There are several possibilities:
    /// This generator can generate keys of type integer,float,double. The generated key is not necessarly
    /// unique!
    /// </summary>
    public class MD5HashGenerator
    {
        private static readonly Object locker = new Object();
    
        /// <summary>
        /// Generates a hashed - key for an instance of a class.
        /// The hash is a classic MD5 hash (e.g. BF20EB8D2C4901112179BF5D242D996B). So you can distinguish different 
        /// instances of a class. Because the object is hashed on the internal state, you can also hash it, then send it to
        /// someone in a serialized way. Your client can then deserialize it and check if it is in
        /// the same state.
        /// The method just just estimates that the object implements the ISerializable interface. What's
        /// needed to save the state or so, is up to the implementer of the interface.
        /// <b>The method is thread-safe!</b>
        /// </summary>
        /// <param name="sourceObject">The object you'd like to have a key out of it.</param>
        /// <returns>An string representing a MD5 Hashkey corresponding to the object or null if the object couldn't be serialized.</returns>
        /// <exception cref="ApplicationException">Will be thrown if the key cannot be generated.</exception>
        public static String GenerateKey(Object sourceObject)
        {
            String hashString = "";
    
            //Catch unuseful parameter values
            if (sourceObject == null)
            {
                throw new ArgumentNullException("Null as parameter is not allowed");
            }
            else
            {
                //We determine if the passed object is really serializable.
                try
                {
                    //Now we begin to do the real work.
                    hashString = ComputeHash(ObjectToByteArray(sourceObject));
                    return hashString;
                }
                catch (AmbiguousMatchException ame)
                {
                    throw new ApplicationException("Could not definitly decide if object is serializable. Message:" + ame.Message);
                }
            }
        }
    
        /// <summary>
        /// Converts an object to an array of bytes. This array is used to hash the object.
        /// </summary>
        /// <param name="objectToSerialize">Just an object</param>
        /// <returns>A byte - array representation of the object.</returns>
        /// <exception cref="SerializationException">Is thrown if something went wrong during serialization.</exception>
        private static byte[] ObjectToByteArray(Object objectToSerialize)
        {
            MemoryStream fs = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter();
            try
            {
                //Here's the core functionality! One Line!
                //To be thread-safe we lock the object
                lock (locker)
                {
                    formatter.Serialize(fs, objectToSerialize);
                }
                return fs.ToArray();
            }
            catch (SerializationException se)
            {
                Console.WriteLine("Error occured during serialization. Message: " + se.Message);
                return null;
            }
            finally
            {
                fs.Close();
            }
        }
    
        /// <summary>
        /// Generates the hashcode of an given byte-array. The byte-array can be an object. Then the
        /// method "hashes" this object. The hash can then be used e.g. to identify the object.
        /// </summary>
        /// <param name="objectAsBytes">bytearray representation of an object.</param>
        /// <returns>The MD5 hash of the object as a string or null if it couldn't be generated.</returns>
        private static string ComputeHash(byte[] objectAsBytes)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            try
            {
                byte[] result = md5.ComputeHash(objectAsBytes);
    
                // Build the final string by converting each byte
                // into hex and appending it to a StringBuilder
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < result.Length; i++)
                {
                    sb.Append(result[i].ToString("X2"));
                }
    
                // And return it
                return sb.ToString();
            }
            catch (ArgumentNullException ane)
            {
                //If something occured during serialization, this method is called with an null argument. 
                Console.WriteLine("Hash has not been generated.");
                return null;
            }
        }
    }

    Despues, para usarlo, tienes que añadir el atributo Serializable a tu clase:

    [Serializable]
    class Alumno
    {
        public string Nombre { get; set; }
        public string Apellido { get; set; }
        public string DNI { get; set; }
        public override string ToString()
        {
            return $"Nombre: {Nombre}\tApellido: {Apellido}\tDNI:{DNI}";
        }
    }


    Aqui te dejo un ejemplo de su uso:

    static void Main(string[] args)
    {
        Alumno Alumno1 = new Alumno() { Nombre = "Jorge", Apellido = "Turrado", DNI = "1234" };
        Alumno Alumno2 = new Alumno() { Nombre = "Jorge", Apellido = "Turrado", DNI = "1234" };
        Alumno Alumno3 = new Alumno() { Nombre = "Jorge", Apellido = "Turrado", DNI = "4321" };
        string HashAlumno1 = MD5HashGenerator.GenerateKey(Alumno1);
        string HashAlumno2 = MD5HashGenerator.GenerateKey(Alumno2);
        string HashAlumno3 = MD5HashGenerator.GenerateKey(Alumno3);
        bool Alumno1_Alumno2 = HashAlumno1 == HashAlumno2;
        bool Alumno1_Alumno3 = HashAlumno1 == HashAlumno3;
        Console.WriteLine(Alumno1.ToString());
        Console.WriteLine(Alumno2.ToString());
        Console.WriteLine(Alumno3.ToString());
        Console.WriteLine("El Alumno1 y el Alumno2 son iguales? {0}", Alumno1_Alumno2);
        Console.WriteLine("El Alumno1 y el Alumno3 son iguales? {0}", Alumno1_Alumno3);
        Console.ReadLine();
    }

    Ese codigo, da como resultado lo siguiente:

    Los dos primeros alumnos son identicos, en cambio en el tercero, el DNI cambia, por lo tanto el Hash no coincide

    Nos comentas si tienes dudas

    Atte



    No olvides votar mi comentario si te ha ayudado y marcarlo como respuesta si ha sido la solución, con eso ayudas a mejorar mi reputación en la comunidad y a identificar la respuesta a la gente que tenga el mismo problema.

    Para obtener una respuesta lo más rápida y concisa posible, te recomiendo:


    viernes, 27 de octubre de 2017 9:48
  • Buenas,

    acabo de darme cuenta que la pregunta es en vb.Net, asi que te pongo el programa traducido:

    • Hash
    Imports System.Text
    Imports System.Security.Cryptography
    Imports System.IO
    Imports System.Runtime.Serialization.Formatters.Binary
    Imports System.Runtime.Serialization
    Imports System.Reflection
    
    ''' <summary>
    ''' This class takes an object, and generates a key to it. There are several possibilities:
    ''' This generator can generate keys of type integer,float,double. The generated key is not necessarly
    ''' unique!
    ''' </summary>
    Public Class MD5HashGenerator
        Private Shared ReadOnly locker As New [Object]()
    
        ''' <summary>
        ''' Generates a hashed - key for an instance of a class.
        ''' The hash is a classic MD5 hash (e.g. BF20EB8D2C4901112179BF5D242D996B). So you can distinguish different 
        ''' instances of a class. Because the object is hashed on the internal state, you can also hash it, then send it to
        ''' someone in a serialized way. Your client can then deserialize it and check if it is in
        ''' the same state.
        ''' The method just just estimates that the object implements the ISerializable interface. What's
        ''' needed to save the state or so, is up to the implementer of the interface.
        ''' <b>The method is thread-safe!</b>
        ''' </summary>
        ''' <param name="sourceObject">The object you'd like to have a key out of it.</param>
        ''' <returns>An string representing a MD5 Hashkey corresponding to the object or null if the object couldn't be serialized.</returns>
        ''' <exception cref="ApplicationException">Will be thrown if the key cannot be generated.</exception>
        Public Shared Function GenerateKey(sourceObject As [Object]) As [String]
            Dim hashString As [String] = ""
    
            'Catch unuseful parameter values
            If sourceObject Is Nothing Then
                Throw New ArgumentNullException("Null as parameter is not allowed")
            Else
                'We determine if the passed object is really serializable.
                Try
                    'Now we begin to do the real work.
                    hashString = ComputeHash(ObjectToByteArray(sourceObject))
                    Return hashString
                Catch ame As AmbiguousMatchException
                    Throw New ApplicationException("Could not definitly decide if object is serializable. Message:" + ame.Message)
                End Try
            End If
        End Function
    
        ''' <summary>
        ''' Converts an object to an array of bytes. This array is used to hash the object.
        ''' </summary>
        ''' <param name="objectToSerialize">Just an object</param>
        ''' <returns>A byte - array representation of the object.</returns>
        ''' <exception cref="SerializationException">Is thrown if something went wrong during serialization.</exception>
        Private Shared Function ObjectToByteArray(objectToSerialize As [Object]) As Byte()
            Dim fs As New MemoryStream()
            Dim formatter As New BinaryFormatter()
            Try
                'Here's the core functionality! One Line!
                'To be thread-safe we lock the object
                SyncLock locker
                    formatter.Serialize(fs, objectToSerialize)
                End SyncLock
                Return fs.ToArray()
            Catch se As SerializationException
                Console.WriteLine("Error occured during serialization. Message: " + se.Message)
                Return Nothing
            Finally
                fs.Close()
            End Try
        End Function
    
        ''' <summary>
        ''' Generates the hashcode of an given byte-array. The byte-array can be an object. Then the
        ''' method "hashes" this object. The hash can then be used e.g. to identify the object.
        ''' </summary>
        ''' <param name="objectAsBytes">bytearray representation of an object.</param>
        ''' <returns>The MD5 hash of the object as a string or null if it couldn't be generated.</returns>
        Private Shared Function ComputeHash(objectAsBytes As Byte()) As String
            Dim md5 As MD5 = New MD5CryptoServiceProvider()
            Try
                Dim result As Byte() = md5.ComputeHash(objectAsBytes)
    
                ' Build the final string by converting each byte
                ' into hex and appending it to a StringBuilder
                Dim sb As New StringBuilder()
                For i As Integer = 0 To result.Length - 1
                    sb.Append(result(i).ToString("X2"))
                Next
    
                ' And return it
                Return sb.ToString()
            Catch ane As ArgumentNullException
                'If something occured during serialization, this method is called with an null argument. 
                Console.WriteLine("Hash has not been generated.")
                Return Nothing
            End Try
        End Function
    End Class

    • Module1
    Imports System.Collections.Generic
    Imports System.Linq
    Imports System.Text
    Imports System.Threading.Tasks
    
    Module Module1
        Sub Main()
            Dim Alumno1 As New Alumno() With {.Nombre = "Jorge", .Apellido = "Turrado", .DNI = "1234"}
            Dim Alumno2 As New Alumno() With {.Nombre = "Jorge", .Apellido = "Turrado", .DNI = "1234"}
            Dim Alumno3 As New Alumno() With {.Nombre = "Jorge", .Apellido = "Turrado", .DNI = "4321"}
            Dim HashAlumno1 As String = MD5HashGenerator.GenerateKey(Alumno1)
            Dim HashAlumno2 As String = MD5HashGenerator.GenerateKey(Alumno2)
            Dim HashAlumno3 As String = MD5HashGenerator.GenerateKey(Alumno3)
            Dim Alumno1_Alumno2 As Boolean = HashAlumno1 = HashAlumno2
            Dim Alumno1_Alumno3 As Boolean = HashAlumno1 = HashAlumno3
            Console.WriteLine(Alumno1.ToString())
            Console.WriteLine(Alumno2.ToString())
            Console.WriteLine(Alumno3.ToString())
            Console.WriteLine("El Alumno1 y el Alumno2 son iguales? {0}", Alumno1_Alumno2)
            Console.WriteLine("El Alumno1 y el Alumno3 son iguales? {0}", Alumno1_Alumno3)
            Console.ReadLine()
        End Sub
    End Module
    
    
    <Serializable>
    Class Alumno
        Public Property Nombre As String
            Get
                Return m_Nombre
            End Get
            Set
                m_Nombre = Value
            End Set
        End Property
        Private m_Nombre As String
        Public Property Apellido() As String
            Get
                Return m_Apellido
            End Get
            Set
                m_Apellido = Value
            End Set
        End Property
        Private m_Apellido As String
        Public Property DNI() As String
            Get
                Return m_DNI
            End Get
            Set
                m_DNI = Value
            End Set
        End Property
        Private m_DNI As String
        Public Overrides Function ToString() As String
            Return "Nombre: {Nombre}" & vbTab & "Apellido: {Apellido}" & vbTab & "DNI:{DNI}"
        End Function
    End Class

    La explicación es la del post anterior, en este solo he traducido el código.

    Lo dicho, si tienes dudas, comentanos

    Atte


    No olvides votar mi comentario si te ha ayudado y marcarlo como respuesta si ha sido la solución, con eso ayudas a mejorar mi reputación en la comunidad y a identificar la respuesta a la gente que tenga el mismo problema.

    Para obtener una respuesta lo más rápida y concisa posible, te recomiendo:



    • Marcado como respuesta Vicdeju viernes, 27 de octubre de 2017 10:30
    • Editado Jorge TurradoMVP viernes, 27 de octubre de 2017 10:40
    viernes, 27 de octubre de 2017 10:14
  • Muchas gracias Jorge.

    Un saludo.

    viernes, 27 de octubre de 2017 10:30