Ir al contenido


Foto

Proteger contraseña (o numero de serie)


  • Por favor identifícate para responder
13 respuestas en este tema

#1 seoane

seoane

    Advanced Member

  • Administrador
  • 1.257 mensajes
  • LocationEspaña

Escrito 30 junio 2012 - 04:59

La API de windows cuenta con una funcion que permite cifrar informacion, sin necesidad de utilizar una contraseña, pero con la peculiaridad que los datos cifrados solo los puede descifrar el mismo usuario, y en la misma maquina que se cifraron.

Por lo que si queremos guardar una contraseña solo tenemos que utilizar esta función, y aunque alguien acceda al fichero donde la guardamos no podrá descifrarlo a menos que se loguee en el sistema con el mismo nombre de usuario que la creo.

Esto también podemos utilizarlo para generar un numero de serie único que identifique un ordenador cifrando un dato conocido. Luego solo tenemos que descifrarlo y comprobar que el resultado es igual al dato que habíamos cifrado para saber si se trata del mismo ordenador.

El código (por supuesto es una aplicación de consola  :)  )


delphi
  1. program Test;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses
  6.   Windows, SysUtils;
  7.  
  8.  
  9. type
  10.   TDATA_BLOB = record
  11.     cbData: DWORD;
  12.     pbData: PByte;
  13.   end;
  14.   PDATA_BLOB = ^TDATA_BLOB;
  15.  
  16.   TCRYPTPROTECT_PROMPTSTRUCT = record
  17.     cbSize: DWORD;
  18.     dwPromptFlags: DWORD;
  19.     hwndApp: HWND;
  20.     szPrompt: PWChar;
  21.   end;
  22.   PCRYPTPROTECT_PROMPTSTRUCT = ^TCRYPTPROTECT_PROMPTSTRUCT;
  23.  
  24. function CryptProtectData(pDataIn: PDATA_BLOB; szDataDescr: PWChar;
  25.   pOptionalEntropy: PDATA_BLOB; pvReserved: Pointer;
  26.   pPromptStruct: PCRYPTPROTECT_PROMPTSTRUCT; dwFlags: DWORD; pDataOut: PDATA_BLOB
  27. ): BOOL; stdcall; external 'Crypt32.dll';
  28.  
  29. function CryptUnprotectData(pDataIn: PDATA_BLOB; szDataDescr: PWChar;
  30.   pOptionalEntropy: PDATA_BLOB; pvReserved: Pointer;
  31.   pPromptStruct: PCRYPTPROTECT_PROMPTSTRUCT; dwFlags: DWORD; pDataOut: PDATA_BLOB
  32. ): BOOL; stdcall; external 'Crypt32.dll';
  33.  
  34. procedure PrintData(Data: TDATA_BLOB);
  35. var
  36.   i: Integer;
  37.   P: PByte;
  38. begin
  39.   P:= Data.pbData;
  40.   for i:= 1 to Data.cbData do
  41.   begin
  42.     Write(IntToHex(P^,2) + #32);
  43.     if i mod 16 = 0 then
  44.       Writeln;
  45.     inc(P);
  46.   end;
  47. end;
  48.  
  49. const
  50.   // Si usamos este flag el dato lo puede descifrar cualquier usuario del mismo ordenador
  51.   CRYPTPROTECT_LOCAL_MACHINE = 4;
  52.  
  53. var
  54.   Str: String;
  55.   Src, Dst: TDATA_BLOB;
  56. begin
  57.   Str:= 'Texto sin cifrar';
  58.   Writeln('Texto sin cifrar: ' + Str);
  59.   Src.cbData:= Length(Str) + 1;
  60.   Src.pbData:= PByte(PChar(Str));
  61.   FillChar(Dst,Sizeof(Dst),#0);
  62.   if CryptProtectData(@Src,nil,nil,nil,nil,CRYPTPROTECT_LOCAL_MACHINE,@Dst) then
  63.   try
  64.     Writeln('Texto cifrado: ');
  65.     PrintData(Dst);
  66.     Writeln;
  67.     FillChar(Src,Sizeof(Src),#0);
  68.     if CryptUnProtectData(@Dst,nil,nil,nil,nil,CRYPTPROTECT_LOCAL_MACHINE,@Src) then
  69.     try
  70.       Write('Texto descifrado: ');
  71.       Writeln(String(PChar(Src.pbData)));
  72.     finally
  73.       LocalFree(Cardinal(Src.pbData));
  74.     end else
  75.       Writeln(SysErrorMessage(GetLastError));
  76.   finally
  77.     LocalFree(Cardinal(Dst.pbData));
  78.   end else
  79.     Writeln(SysErrorMessage(GetLastError));
  80.   Writeln;
  81.   Readln;
  82. end.


  • 0

#2 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.962 mensajes
  • LocationMadrid - España

Escrito 30 junio 2012 - 07:47

Es una buena alternativa a los sistemas que tratan de conocer el número de serie del HD para el mismo fin. (y) (y)

Me pregunto hasta que punto Windows considera que el PC es el mismo tras algún cambio significativo del hardware. :) 
  • 0

#3 seoane

seoane

    Advanced Member

  • Administrador
  • 1.257 mensajes
  • LocationEspaña

Escrito 30 junio 2012 - 08:24

Me pregunto hasta que punto Windows considera que el PC es el mismo tras algún cambio significativo del hardware. :) 

Si no me equivoco, utiliza algun tipo de "identificador único" creado durante la instalación de windows para identificar al equipo y al usuario, no utiliza directamente el hardware, por lo que al reinstalar el sistema operativo posiblemente el identificador cambie, pero los cambios de hardware no le afectan.
  • 0

#4 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.962 mensajes
  • LocationMadrid - España

Escrito 30 junio 2012 - 09:46

Yo lo comentaba por el consabido tema de li invalidación de la licencia de Windows con los cambios de Hardware. A mi nunca me pasó pero en si día fue muy comentado.

Saludos.
  • 0

#5 seoane

seoane

    Advanced Member

  • Administrador
  • 1.257 mensajes
  • LocationEspaña

Escrito 30 junio 2012 - 03:38

Yo lo comentaba por el consabido tema de la invalidación de la licencia de Windows con los cambios de Hardware. A mi nunca me pasó pero en si día fue muy comentado.

Pues te confirmo que si que pasa, al ordenador de un cliente le tuvimos que cambiar la placa base y al restaurar el windows no nos dejaba activarlo, pero se lo explicamos a una señorita muy amable (con acento francés) del servicio de atención al cliente de microsoft y lo pudimos activar manualmente.
  • 0

#6 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.962 mensajes
  • LocationMadrid - España

Escrito 30 junio 2012 - 03:42

Lástima que no pudiste probar, con ese cliente y en esas circunstancias, el código que expones arriba.  :(  :D :D.

Saludos.
  • 0

#7 seoane

seoane

    Advanced Member

  • Administrador
  • 1.257 mensajes
  • LocationEspaña

Escrito 30 junio 2012 - 04:58

Lástima que no pudiste probar, con ese cliente y en esas circunstancias, el código que expones arriba.  :(  :D :D.

Como ya dije mas arriba, al formatear windows crea un nuevo identificador para el equipo, por lo que ya no se podría descifrar la información.  :(
  • 0

#8 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 30 junio 2012 - 05:29

Hola,
Yo estoy confundido, ¿entonces se podría emplear esta técnica con seguridad y sin problemas para algo medio serio? ¿O es que se ve afectado por algún cambio de hardware? ¿Cuando y/o para que podría ser viable y cuando y para que NO es viable?

Saludos,
  • 0

#9 seoane

seoane

    Advanced Member

  • Administrador
  • 1.257 mensajes
  • LocationEspaña

Escrito 30 junio 2012 - 05:56

Yo estoy confundido, ¿entonces se podría emplear esta técnica con seguridad y sin problemas para algo medio serio? ¿O es que se ve afectado por algún cambio de hardware? ¿Cuando y/o para que podría ser viable y cuando y para que NO es viable?


No, los cambios de hardware no le afectan, solo se pierde la información si se formatea y se reinstala windows.

Un ejemplo sería un programa que se conecta periódicamente a un ftp y necesita guardar el usuario y la contraseña del ftp en algún sitio (un fichero .ini, el registro, una base de datos, etc ...). Si guarda la contraseña tal cual en el disco, cualquiera podría acceder al disco duro (un livecd, desmontando el equipo, etc ...) y leerla, y si la información se guarda en remoto (una base de datos en red, ficheros compartidos o una web) aun sería mas fácil tener acceso a ella. Al cifrarla con este método nos aseguramos que solo el usuario que la creo y en el equipo que la creo puede tener acceso a la información, por lo que un robo del fichero con las contraseñas seria inútil si no pueden loguearse en la maquina en que se cifraron, con el mismo usuario que las cifro.

Y si, se puede utilizar en programas serios, de hecho es el método recomendado por microsoft para guardar contraseñas

Saludos

  • 0

#10 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 30 junio 2012 - 06:53

No, los cambios de hardware no le afectan, solo se pierde la información si se formatea y se reinstala windows.

La pregunta mía entonces sigue siendo válida... ¡estoy confundido! ¿Que es eso de que se pierde la información?
Naturalmente que se pierde todo cuando se formatea y reinstala.

Un ejemplo sería un programa que se conecta periódicamente a un ftp y necesita guardar el usuario y la contraseña del ftp en algún sitio (un fichero .ini, el registro, una base de datos, etc ...). Si guarda la contraseña tal cual en el disco, cualquiera podría acceder al disco duro (un livecd, desmontando el equipo, etc ...) y leerla, y si la información se guarda en remoto (una base de datos en red, ficheros compartidos o una web) aun sería mas fácil tener acceso a ella. Al cifrarla con este método nos aseguramos que solo el usuario que la creo y en el equipo que la creo puede tener acceso a la información, por lo que un robo del fichero con las contraseñas seria inútil si no pueden loguearse en la maquina en que se cifraron, con el mismo usuario que las cifro.

Y si, se puede utilizar en programas serios, de hecho es el método recomendado por microsoft para guardar contraseñas

Saludos

Pues no entiendo... digamos que utilizo esta API para cifrar algunos datos sensibles para algunas cosas que necesita mi aplicación. Hagamos de cuenta que como buen programa y política se realizan copias de seguridad.
Supongamos ahora que justamente dicho equipo decide tomarse un viaje al mundo de los equipos fritos... Adquiero otro con idéntico hardware, se reinstala todo (con la misma configuración del anterior, permisos, etc) y se tiene lugar la recuperación de la copia de seguridad. Si en verdad es como dices que depende de que se requiera de la misma máquina... ¿entonces? ¿Cómo puedo recuperar mi información?

¿QUE es lo que se pierde?

Saludos,
  • 0

#11 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 30 junio 2012 - 07:01

Por otro lado, hay que recalcar que una cosa es cifrado y otra es reducción. Yo tengo entendido que no es nada bueno que se cifren contraseñas, precisamente porque existe la posibilidad de descifrarla.

Para almacenar contraseñas se hace uso de algoritmos de reducción, que no pueden (teóricamente) descifrar... y justamente para eso es que está: no poder obtener la información original tras el dato obtenido.
Esta API es de cifrado y me parece algo descolgado que Microsoft sugiera justo emplear cifrado para guardar contraseñas.

Como dije... ¡no entiendo!  :(  :

Saludos,
  • 0

#12 seoane

seoane

    Advanced Member

  • Administrador
  • 1.257 mensajes
  • LocationEspaña

Escrito 01 julio 2012 - 04:43

Vamos a ver Delphius no es tan difícil de entender. Supongo que tu tienes un programa para leer el correo (outlook, thunderbird, etc ...), cuando configuras en alguno de ellos una cuenta de correo te piden la contraseña y la guardan, para de este modo poder acceder al correo y leerlo sin tener tener que pedirte la contraseña cada 5 minutos. Tienen que guardar la contraseña, no su hash, porque al servidor de correo van a tener que enviar la contraseña original.

Pero ninguno de esos programas guarda la contraseña en un fichero .ini, o en el registro. No encontraras un fichero .ini que sea "Contraseña=contraseña", porque si alguien pude acceder al fichero seria muy fácil para el abrirlo y encontrar la contraseña. Ahí es donde entra esta función, usándola podemos guardar algo como esto "Contraseña=cifrado", donde la contraseña esta cifrada y solo la puede descifrar el mismo usuario que la guardo, por lo que la única forma de acceder a la contraseña es que accedieran a nuestro ordenador con la sesión iniciada con nuestro usuario.

Por ultimo, es verdad que al formatear se pierde la posibilidad de descifrar la contraseña, pero no es nada grave solamente se volvería pedir la contraseña del correo al usuario y la volveríamos a guardar. De hecho lo habitual es tener que volver a configurar el correo cada vez que se formatea.

Esta función NO se usa para guardar información que debe perdurar en el tiempo, o que se deba intercambiar entre ordenadores. Principalmente se utiliza para guardar contraseña de forma segura y que los programas puedan utilizarlas, pero no como un almacenamiento permanente.
  • 0

#13 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 01 julio 2012 - 02:19

Vamos a ver Delphius no es tan difícil de entender. Supongo que tu tienes un programa para leer el correo (outlook, thunderbird, etc ...), cuando configuras en alguno de ellos una cuenta de correo te piden la contraseña y la guardan, para de este modo poder acceder al correo y leerlo sin tener tener que pedirte la contraseña cada 5 minutos. Tienen que guardar la contraseña, no su hash, porque al servidor de correo van a tener que enviar la contraseña original.

Pero ninguno de esos programas guarda la contraseña en un fichero .ini, o en el registro. No encontraras un fichero .ini que sea "Contraseña=contraseña", porque si alguien pude acceder al fichero seria muy fácil para el abrirlo y encontrar la contraseña. Ahí es donde entra esta función, usándola podemos guardar algo como esto "Contraseña=cifrado", donde la contraseña esta cifrada y solo la puede descifrar el mismo usuario que la guardo, por lo que la única forma de acceder a la contraseña es que accedieran a nuestro ordenador con la sesión iniciada con nuestro usuario.

Por ultimo, es verdad que al formatear se pierde la posibilidad de descifrar la contraseña, pero no es nada grave solamente se volvería pedir la contraseña del correo al usuario y la volveríamos a guardar. De hecho lo habitual es tener que volver a configurar el correo cada vez que se formatea.

Esta función NO se usa para guardar información que debe perdurar en el tiempo, o que se deba intercambiar entre ordenadores. Principalmente se utiliza para guardar contraseña de forma segura y que los programas puedan utilizarlas, pero no como un almacenamiento permanente.

Ahora entiendo. Vaya que estaba dormido anoche... y es que esto me rompía los esquemas de lo que yo entiendo por cifrado.
Asi como lo dices, pues si, se vale usarla  :D

Saludos,
  • 0

#14 luisgutierrezb

luisgutierrezb

    Advanced Member

  • Miembros
  • PipPipPip
  • 92 mensajes
  • LocationMéxico

Escrito 02 julio 2012 - 11:06

La API de windows cuenta con una funcion que permite cifrar informacion, sin necesidad de utilizar una contraseña, pero con la peculiaridad que los datos cifrados solo los puede descifrar el mismo usuario, y en la misma maquina que se cifraron.

Por lo que si queremos guardar una contraseña solo tenemos que utilizar esta función, y aunque alguien acceda al fichero donde la guardamos no podrá descifrarlo a menos que se loguee en el sistema con el mismo nombre de usuario que la creo.

Esto también podemos utilizarlo para generar un numero de serie único que identifique un ordenador cifrando un dato conocido. Luego solo tenemos que descifrarlo y comprobar que el resultado es igual al dato que habíamos cifrado para saber si se trata del mismo ordenador.

El código (por supuesto es una aplicación de consola  :)  )


Hice el ejemplo en Delphi XE2, update 4, y no me regresa la cadena original al desencriptarla, alguna idea? pense que pudiera ser el tipo de string, cambia a ansistring, pero nada...


Update!! hice pruebas modificando la cadena a shortstring, en especifico, estas talineas:



delphi
  1. Str: ShortString;
  2.  
  3. Str := Str + #0; //por aquello del nulo para cadena tipo C
  4.  
  5. Src.pbData:= PByte(Pchar(@Str[1]));  //mandamos el puntero de la primer letra..



y con esto funciono bien, ahora a ver de que manera hace la conversion automatica...

Otro update! jeje

El problema es porque con unicode el espacio en memoria es de 2 bytes, y length nos devuelve la cantidad de caracteres, ahora si, ya corregido, queda asi...



delphi
  1. Str := Str + #0; //por aquello del nulo para cadena tipo C
  2.  
  3. Src.cbData:= Length(Str) * SizeOf(Str[1]); //Longitud o espacio en memoria



  • 0