Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » SQL Server »

Ayuda - SHA1 y MD5 codificación de caracteres incorrecto

Estas en el tema de Ayuda - SHA1 y MD5 codificación de caracteres incorrecto en el foro de SQL Server en Foros del Web. Hola a todos! Tengo un pequeño problema, no se por qué rayos mi SQL Server está guardando las claves HASH con caracteres UTF en los ...
  #1 (permalink)  
Antiguo 10/06/2009, 09:01
Avatar de xdrtas  
Fecha de Ingreso: junio-2008
Ubicación: Venezuela
Mensajes: 97
Antigüedad: 15 años, 10 meses
Puntos: 13
Ayuda - SHA1 y MD5 codificación de caracteres incorrecto

Hola a todos! Tengo un pequeño problema, no se por qué rayos mi SQL Server está guardando las claves HASH con caracteres UTF en los campos nvarchar, char y varchar lo pone con otro tipo de caracteres como estos: WÚn5,iyñP¢kdð‚4«2ß.

He intentado cambiar la codificación mediante COLLATE en una Base de datos nueva pero me sigue haciendo lo mismo. Incluido en las bases de datos de prueba como Northwind y AdventureWorks.

Al ejecutar una consulta con HASHBYTES obtengo el siguiente resultado:

Resultado
----------------------------------------------------------------
櫙걡�ꇱ姠핮킧㬍

en vez de obtener algo como esto:
57da6e352c6979f150a26b647ff08234ab32df07

Mi instalación de SQL Server 2008 tiene la siguiente configuración:

Server Collation: Modern_Spanish_CI_AS

Algunas bases de datos que he creado le he cambiado el COLLATE a por ejemplo:
Latin1_General_CS_AI

Pero nada de nada, estuve viendo también la función HASHBYTES pero no me dice nada sobre un cambio en la codificación de caracteres.

Mi S.O. es Windows Vista SP1 con SQL Server 2008 Enterprise Edition en Inglés.

De ante mano muchas gracias por cualquier ayuda que me puedan prestar.

Última edición por xdrtas; 10/06/2009 a las 09:55 Razón: Equivocación al escribir el problema.
  #2 (permalink)  
Antiguo 10/06/2009, 20:11
Avatar de xdrtas  
Fecha de Ingreso: junio-2008
Ubicación: Venezuela
Mensajes: 97
Antigüedad: 15 años, 10 meses
Puntos: 13
Respuesta: Ayuda - SHA1 y MD5 codificación de caracteres incorrecto

Hola de nuevo a todos, ya resolví el problema, les dejo la solución por si a alguno de ustedes les llega a pasar lo mismo que a mi.

Al utilizar la función HASHBYTES con nvarchar el resultado se transforma a caracteres orientales porque el valor devuelto por HASHBYTES comienza con "0x".(Sin las comillas).

Asi que guardé el valor resultante de la función HASHBYTES en un varbinary para probar y luego lo transformé con la función CONVERT a nvarchar y listo.

Les dejo el ejemplo, (aunque aqui ya no uso varbinary, lo guardo directamente en una variable nvarchar transformando primero la cadena):

DECLARE @hash nvarchar(64)
SET @hash = CONVERT(nvarchar(64),HASHBYTES('SHA1','cualquierte xto'),2)
SELECT @hash as Resultado

Resultado: 1216BC84EACC1296FC3C81791807227A773F0CD1

El "2" en la función CONVERT lo que hace es quitar los dos primeros caracteres y el resto lo guarda como caracteres "normales".
Espero que les ayude!
  #3 (permalink)  
Antiguo 26/08/2010, 11:59
 
Fecha de Ingreso: agosto-2010
Mensajes: 3
Antigüedad: 13 años, 8 meses
Puntos: 0
Respuesta: Ayuda - SHA1 y MD5 codificación de caracteres incorrecto

Cita:
Iniciado por xdrtas Ver Mensaje
Hola de nuevo a todos, ya resolví el problema, les dejo la solución por si a alguno de ustedes les llega a pasar lo mismo que a mi.

Al utilizar la función HASHBYTES con nvarchar el resultado se transforma a caracteres orientales porque el valor devuelto por HASHBYTES comienza con "0x".(Sin las comillas).

Asi que guardé el valor resultante de la función HASHBYTES en un varbinary para probar y luego lo transformé con la función CONVERT a nvarchar y listo.

Les dejo el ejemplo, (aunque aqui ya no uso varbinary, lo guardo directamente en una variable nvarchar transformando primero la cadena):

DECLARE @hash nvarchar(64)
SET @hash = CONVERT(nvarchar(64),HASHBYTES('SHA1','cualquierte xto'),2)
SELECT @hash as Resultado

Resultado: 1216BC84EACC1296FC3C81791807227A773F0CD1

El "2" en la función CONVERT lo que hace es quitar los dos primeros caracteres y el resto lo guarda como caracteres "normales".
Espero que les ayude!

Amigo, veo que tienes experiencia con el uso del hashbytes, quisiera ver si me puedes apoyar para hacer lo siguiente:
Necesito hacer un hashbatyes a todo el contenido de una tabla, la tabla puede tener "n" campos con diferentes tipos tipos de datos.
De antemano agradezco tu tiempo y tus aportes

Atentamente,
Adán Martínez
  #4 (permalink)  
Antiguo 26/08/2010, 15:33
Avatar de xdrtas  
Fecha de Ingreso: junio-2008
Ubicación: Venezuela
Mensajes: 97
Antigüedad: 15 años, 10 meses
Puntos: 13
Respuesta: Ayuda - SHA1 y MD5 codificación de caracteres incorrecto

Cita:
Iniciado por amtzva Ver Mensaje
Amigo, veo que tienes experiencia con el uso del hashbytes, quisiera ver si me puedes apoyar para hacer lo siguiente:
Necesito hacer un hashbatyes a todo el contenido de una tabla, la tabla puede tener "n" campos con diferentes tipos tipos de datos.
De antemano agradezco tu tiempo y tus aportes

Atentamente,
Adán Martínez
Hola, tienes que aclararme algo, estás seguro de que quieres encriptar todos los datos? Hasta donde sé, HASHBYTES usa sólo métodos de encriptación en un sentido, (MD5, SHA1, etc...), o sea, no puedes desencriptar luego la información.
Cuál es el objetivo de encriptar toda la información de los campos de la tabla? Qué no acceda nadie en absoluto a la información o tendrías una copia de la tabla con el significado de todos los campos encriptados, para así poder traducir la información, (un diccionario de datos)?

Un cordial saludo.
__________________
¿Cuál es el mejor lenguaje para programar?
Aquel lenguaje por el cual te paguen más.
[--::xdrtas.coolpage.biz::--]
[---:::xdrtas:::---]
  #5 (permalink)  
Antiguo 26/08/2010, 15:44
 
Fecha de Ingreso: agosto-2010
Mensajes: 3
Antigüedad: 13 años, 8 meses
Puntos: 0
Respuesta: Ayuda - SHA1 y MD5 codificación de caracteres incorrecto

Gracias por contestar... te cuento:
Tengo 2 bases de datos con tablas identicas en estructura, la primera bd es producción y la segunda es una réplica utilizada para reportes, estoy trabajando en la plataforma de SQL2000

Estoy utilizando una query sql en un store procedure para detectar los registros que se crean borran o modifican en la bd1 y replicar estos cambios en la bd2, para ello estoy utilizando ckecksum_agg(binary_checksum(*)) from tabla x aplicado tanto en la tabla fuente como en la tabla destino....

Todo iba muy bien... pero recientemente en datos modificados no me está detectando un cambio que se hizo en un valor, a pesar de que está demostrado que si existe el cambio, los valores son:

Produccion: E700 79899186 40 22OP 01 NO .50
Replica: E700 79899186 40 22OP 01 NO 5.00

El valor que originalmente se capturó fue 5.00, por un error de captura, luego se modifica el valor a 0.50 en producción, sin embargo al correr la instrucción de verificación del cambio no detecta este cambio y por tanto lo pasa por alto sin afectar en la bd2 de la réplica...

observaciones...

puede cambiar cualquier campo de la tabla, tengo tablas que tiene mas de 200 campos con 1 solo campo llave...

estas tablas pertenecen a un ERP por lo tanto no puedo migrar de version de sql .

Leyendo la documentación del Binary_checksum me dice que es mejor utilizar el hashbytes... pero no he encontrado como aplicarlo a mi necesidad...

De nuevo gracias por el aporte y estoy atento a tus comentarios
  #6 (permalink)  
Antiguo 26/08/2010, 21:01
Avatar de xdrtas  
Fecha de Ingreso: junio-2008
Ubicación: Venezuela
Mensajes: 97
Antigüedad: 15 años, 10 meses
Puntos: 13
Respuesta: Ayuda - SHA1 y MD5 codificación de caracteres incorrecto

Hola de nuevo...
Cita:
Iniciado por amtzva Ver Mensaje
Gracias por contestar... te cuento:
Tengo 2 bases de datos con tablas identicas en estructura, la primera bd es producción y la segunda es una réplica utilizada para reportes, estoy trabajando en la plataforma de SQL2000

Estoy utilizando una query sql en un store procedure para detectar los registros que se crean borran o modifican en la bd1 y replicar estos cambios en la bd2, para ello estoy utilizando ckecksum_agg(binary_checksum(*)) from tabla x aplicado tanto en la tabla fuente como en la tabla destino....

Todo iba muy bien... pero recientemente en datos modificados no me está detectando un cambio que se hizo en un valor, a pesar de que está demostrado que si existe el cambio, los valores son:

Produccion: E700 79899186 40 22OP 01 NO .50
Replica: E700 79899186 40 22OP 01 NO 5.00

El valor que originalmente se capturó fue 5.00, por un error de captura, luego se modifica el valor a 0.50 en producción, sin embargo al correr la instrucción de verificación del cambio no detecta este cambio y por tanto lo pasa por alto sin afectar en la bd2 de la réplica...

observaciones...

puede cambiar cualquier campo de la tabla, tengo tablas que tiene mas de 200 campos con 1 solo campo llave...

estas tablas pertenecen a un ERP por lo tanto no puedo migrar de version de sql .

Leyendo la documentación del Binary_checksum me dice que es mejor utilizar el hashbytes... pero no he encontrado como aplicarlo a mi necesidad...

De nuevo gracias por el aporte y estoy atento a tus comentarios
Ahora si lo tengo más claro, sin embargo, mi ayuda se va a ver limitada por lo siguiente:
  • Hace años que no uso SQL Server 2000. Actualmente uso mucho más PostgreSQL y en menor medida, SQL Server 2008.
  • No conozco tu estructura de datos ni como funciona tu procedimiento almacenado
  • Nota: No quiero tampoco que me pases información sensible de tu ERP, ni de la Base de datos, sólo te aclaro que con las limitaciones que tengo puede que la ayuda que te preste no sea la más óptima.

Aclarado los puntos anteriores vamos a ver el problema, lo diagramé, porque siempre es mejor verlo con imágenes que con palabras:
Uploaded with ImageShack.us

Supongo que sabes como funciona HASHBYTES, si no, te lo explico:
Esta función se encarga de tomar los datos de un campo y lo encripta en algún algoritmo como por ejemplo SHA1 o MD5 entre otros.
Esto quiere decir que un texto cualquiera como por ejemplo el siguiente: "E700 79899186 40 22OP 01 NO 5.00" al usar Hashbytes con SHA1 se transforma en lo siguiente: "57A50D8AD69FE716DEFE744BDC56CDE980AB24CE"
Los algoritmos de encriptación como SHA1 o MD5 son CASE SENSITIVE, o sea, marcan diferencia entre "A" y "a", dando resultados diferentes de encriptación entre uno y otro aunque sea la misma letra.

Para tu caso en concreto se procedería de forma análoga, te lo coloco como pseudocódigo para mayor claridad:
  1. Obtener el valor del campo modificado de la Base de datos primaria.
  2. Aplicar la función HASHBYTES y guardar el resultado en una variable temporal.
  3. Obtener el valor del mismo campo en la Base de datos secundaria y del registro equivalente.
  4. Aplicar la función HASHBYTES y guardar el resultado en una variable temporal.
  5. Comparar los dos resultados.
  6. Si son distintos entonces actualizar el campo de la base de datos secundaria con el valor del campo de la base de datos primaria.

Aquí te dejo el ejemplo que desarrollé en SQL Server 2008:
Cree una base de datos para hacer la prueba, el nombre de la base de datos es "Test", sin las comillas.

Tabla "Primaria":
Código SQL:
Ver original
  1. USE [Test]
  2. GO
  3.  
  4. /****** Object:  Table [dbo].[Primaria]    Script Date: 08/26/2010 21:53:59 ******/
  5. SET ANSI_NULLS ON
  6. GO
  7.  
  8. SET QUOTED_IDENTIFIER ON
  9. GO
  10.  
  11. CREATE TABLE [dbo].[Primaria](
  12.     [id] [BIGINT] NOT NULL,
  13.     [campo] [nvarchar](50) NULL,
  14.  CONSTRAINT [PK_Primaria] PRIMARY KEY CLUSTERED
  15. (
  16.     [id] ASC
  17. )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
  18. ) ON [PRIMARY]
  19.  
  20. GO

Tabla "Secundaria":
Código SQL:
Ver original
  1. USE [Test]
  2. GO
  3.  
  4. /****** Object:  Table [dbo].[Secundaria]    Script Date: 08/26/2010 21:54:45 ******/
  5. SET ANSI_NULLS ON
  6. GO
  7.  
  8. SET QUOTED_IDENTIFIER ON
  9. GO
  10.  
  11. CREATE TABLE [dbo].[Secundaria](
  12.     [id] [BIGINT] NOT NULL,
  13.     [campo] [nvarchar](50) NULL,
  14.     [fid] [BIGINT] NOT NULL
  15. ) ON [PRIMARY]
  16.  
  17. GO
  18.  
  19. ALTER TABLE [dbo].[Secundaria]  WITH CHECK ADD  CONSTRAINT [FK_Secundaria_Primaria] FOREIGN KEY([fid])
  20. REFERENCES [dbo].[Primaria] ([id])
  21. GO
  22.  
  23. ALTER TABLE [dbo].[Secundaria] CHECK CONSTRAINT [FK_Secundaria_Primaria]
  24. GO

Datos de la tabla "Primaria":
Código SQL:
Ver original
  1. INSERT INTO [Test].[dbo].[Primaria] ([id],[campo]) VALUES (1,'E700 79899186 40 22OP 01 NO .50');
  2. INSERT INTO [Test].[dbo].[Primaria] ([id],[campo]) VALUES (2,'E700 79899186 40 22OP 01 NO .40');
  3. INSERT INTO [Test].[dbo].[Primaria] ([id],[campo]) VALUES (3,'E700 79899186 40 22OP 01 NO .30');
  4. INSERT INTO [Test].[dbo].[Primaria] ([id],[campo]) VALUES (4,'E700 79899186 40 22OP 01 NO .20');

Datos de la tabla "Secundaria":
Código SQL:
Ver original
  1. INSERT INTO [Test].[dbo].[Secundaria] ([id],[campo],[fid]) VALUES (1,'E700 79899186 40 22OP 01 NO 5.00',2);
  2. INSERT INTO [Test].[dbo].[Secundaria] ([id],[campo],[fid]) VALUES (1,'E700 79899186 40 22OP 01 NO 5.00',1);
  3. INSERT INTO [Test].[dbo].[Secundaria] ([id],[campo],[fid]) VALUES (1,'E700 79899186 40 22OP 01 NO 5.00',1);
  4. INSERT INTO [Test].[dbo].[Secundaria] ([id],[campo],[fid]) VALUES (1,'E700 79899186 40 22OP 01 NO 5.00',1);
  5. INSERT INTO [Test].[dbo].[Secundaria] ([id],[campo],[fid]) VALUES (1,'E700 79899186 40 22OP 01 NO 5.00',2);

Procedimiento almacenado "Modificar", se encarga de modificar el campo usando la función HASHBYTES:
Código SQL:
Ver original
  1. USE [Test]
  2. GO
  3. /****** Object:  StoredProcedure [dbo].[Modificar]    Script Date: 08/26/2010 22:00:56 ******/
  4. SET ANSI_NULLS ON
  5. GO
  6. SET QUOTED_IDENTIFIER ON
  7. GO
  8. -- =============================================
  9. -- Author:      <Xdrtas, http://xdrtas.coolpage.biz/>
  10. -- Create date: <26 de Agosto del 2010>
  11. -- Description: <Comparar campos mediante HASHBYTES>
  12. -- =============================================
  13. ALTER PROCEDURE [dbo].[Modificar]
  14. AS
  15. BEGIN
  16.     SET NOCOUNT ON;
  17.     --Se declaran las variables que se van a usar para comparar los resultados de los campos...
  18.     --@pri_pri: Contiene el valor encriptado en "SHA1" del campo "campo" de la tabla "Primaria"...
  19.     --@sec_pri: Contiene el valor encriptado en "SHA1" del campo "campo" de la tabla "Secundaria"...
  20.     --@texto_P: (Tabla Primaria). Contiene el valor del campo obtenido mediante un query, este valor NO está encriptado.
  21.     --@texto_S: (Tabla Secundaria). Contiene el valor del campo obtenido mediante un query, este valor NO está encriptado.
  22.     DECLARE @pri_pri AS nvarchar(64),
  23.             @sec_pri AS nvarchar(64),
  24.             @texto_P AS nvarchar(64),
  25.             @texto_S AS nvarchar(64)
  26.    
  27.     SELECT @texto_P = p.campo FROM Primaria p WHERE id = 1;
  28.     SET @pri_pri = CONVERT(nvarchar(64), HASHBYTES('SHA1',@texto_P),2);
  29.    
  30.     SELECT @texto_S = s.campo FROM Test.dbo.Secundaria s WHERE fid = 1;
  31.     SET @sec_pri = CONVERT(nvarchar(64), HASHBYTES('SHA1',@texto_S),2);
  32.    
  33.     --Se compara los resultados, si son distintos, entonces se tiene que modificar el campo de la tabla "Secundaria"
  34.     --Se usa la variable @texto_P que contiene el valor del campo modificado de la tabla "Primaria"...
  35.     IF @pri_pri <> @sec_pri
  36.         UPDATE Secundaria SET campo = @texto_P WHERE fid = 1;
  37.        
  38. END

Si @pri_pri es distinto de @sec_pri entonces se hace el UPDATE a la tabla "Secundaria" con el valor actual de la tabla "Primaria" que se guardó en la variable @texto_P, fíjate que este valor NO está encriptado, es el valor original del campo modificado.
Si son iguales las variables @pri_pri y @sec_pri entonces no hace falta la actualización.

NOTA: fid, es la clave foránea en la tabla "Secundaria" con relación al id de la tabla "Primaria", es para relacionar las tablas de 1 a N.
Soy conciente de que tu tienes que hacer la actualización de una base de datos a otra, no de una tabla a otra, sin embargo, por lo que he leído, eso ya lo tienes cubierto, así que la idea de este ejercicio es ilustrarte como hacer la comparación en Transact-SQL y como funciona.
Lo que queda es adaptarlo a tus necesidades, cosa que no he podido hacer porque no tengo todos lo datos ni siquiera la misma versión de bases de datos, pero eso ya te queda a tí hacerlo.
Recuerda hacer primero las pruebas en un base de datos independiente y cuando estés seguro del resultado lo lleves a la base de datos de producción.

Bueno, eso es todo, espero que se aclare tu duda y lo puedas adaptar sin muchos problemas a tú código.

Un cordial saludo.
__________________
¿Cuál es el mejor lenguaje para programar?
Aquel lenguaje por el cual te paguen más.
[--::xdrtas.coolpage.biz::--]
[---:::xdrtas:::---]

Última edición por xdrtas; 26/08/2010 a las 21:10
  #7 (permalink)  
Antiguo 26/08/2010, 21:44
 
Fecha de Ingreso: agosto-2010
Mensajes: 3
Antigüedad: 13 años, 8 meses
Puntos: 0
Respuesta: Ayuda - SHA1 y MD5 codificación de caracteres incorrecto

Amigo, muchas gracias... realmente me has dado una catedra...

Ahora solamente le he hechado un vistazo a la solucion que me planteas... mañana temprano estaré revisando puntualmente cada caso y trataré de aplicarlo a mi sistema...

Nuevamente muuuchas gracias... y te cuento como me fue con las pruebas...

Sinceramente
Adán Martinez
  #8 (permalink)  
Antiguo 27/08/2010, 10:21
Avatar de xdrtas  
Fecha de Ingreso: junio-2008
Ubicación: Venezuela
Mensajes: 97
Antigüedad: 15 años, 10 meses
Puntos: 13
Respuesta: Ayuda - SHA1 y MD5 codificación de caracteres incorrecto

Cita:
Iniciado por amtzva Ver Mensaje
Amigo, muchas gracias... realmente me has dado una catedra...

Ahora solamente le he hechado un vistazo a la solucion que me planteas... mañana temprano estaré revisando puntualmente cada caso y trataré de aplicarlo a mi sistema...

Nuevamente muuuchas gracias... y te cuento como me fue con las pruebas...

Sinceramente
Adán Martinez
De nada, sólo espero que lo puedas adaptar sin mayores dolores de cabeza.

Suerte!

Un cordial saludo.
__________________
¿Cuál es el mejor lenguaje para programar?
Aquel lenguaje por el cual te paguen más.
[--::xdrtas.coolpage.biz::--]
[---:::xdrtas:::---]
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 05:59.