Boletín Pascal #17 - 20-FEB-2001
INDICE
1. UNAS PALABRAS DEL EDITOR
2. INTRODUCCION A LA PROGRAMACION DE CRIPTOGRAFIA FUERTE USANDO BORLAND
DELPHI
- Algunas palabras
- Garantía
- Definiciones
- Advertencia
- El algoritmo
- El código
3. BARRA DE PROGRESO SIN MARCO
4. PUBLICACIONES ELECTRONICAS GRATUITAS
5. ENLACES
________________________________________________________________________
1. UNAS PALABRAS DEL EDITOR
El Sorteo de la Librería JfControls finalizó sin ganador, pero la gente
de JfActiveSoft está determinada a regalar una licencia de todos modos,
así que decidieron reducir el número de dígitos de la lotería a tres, y
si nadie tiene el número que corresponde a los últimos tres dígitos del
primer premio de la Lotería Nacional de España que tendrá lugar el
Sábado 17 de Marzo, entonces se continuará con el segundo premio,
tercero, cuarto, etc. hasta que haya un ganador. Esta vez tendrán más
tiempo para inscribirse puesto que la fecha tope es el Jueves 15 de
Marzo a las 20:00 GMT. Quienes se hayan inscripto para participar en el
primer sorteo quedan automáticamente inscriptos para este nuevo sorteo y
como cortesía recibirán un número adicional que les será notificado por
email.
Participar es gratis. Todo lo que tienen que hacer es descargar e
instalar la versión de evaluación de la librería (disponible tanto para
Delphi como para C++ Builder, ambos en versiones 3, 4 y 5) para así
obtener el Key Number (un número único que identifica cada instalación
de la librería) con el que podrán llenar el formulario de inscripción.
Si no quieren instalar la versión de evaluación de la librería, la
última versión de JfSetup le dará el Key Number si instala sólo la demo
(vale la pena verla y no se requiere que la librería esté instalada para
correr el ejecutable). Para más información sobre el sorteo:
http://www.latiumsoftware.com/jfcontrols/index.php?lang=es
En esta edición me complace presentar un artículo de Uri Fridman sobre
criptografía, y también otro artículo de Vladimir S. mostrándonos cómo
obtener una barra de progreso sin marco. Aprovecho para recordarles que
este boletín sólo puede continuar con sus contribuciones. Si no tiene
tiempo para escribir o si siente que no es bueno para eso, pero tiene
algún código útil o interesante que quiera compartir con otros desarro-
lladores, por favor contácteme y posiblemente yo pueda escribir algo por
usted. Debe ser el autor del material que me envíe y sólo se aceptan
contribuciones de código fuente... por favor no me envíen programas o
unidades compiladas!
Saludos,
Ernesto De Spirito
eds2008 @ latiumsoftware.com
________________________________________________________________________
JfControls Lib. Multilenguaje. Multiapariencia. Skins. Privilegios. Más
de 40 componentes integrados y personalizables. Múltiples problemas de
programación resueltos. Administración centralizada de recursos. Para
Delphi 3-2006 y C++ Builder 3-6. http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________
2. INTRODUCCION A LA PROGRAMACION DE CRIPTOGRAFIA FUERTE USANDO BORLAND
DELPHI
Copyright (c) 2001 Uri Fridman <urifrid@hushmail.com>
Algunas palabras
================
Históricamente, la criptografía fue usada por los gobiernos a través de
los tiempos para ocultar mensages secretos. La necesidad de mantener
"secretos de estado" fuera del alcance del público en general llevó a la
invención de varios métodos de encripción.
En el Siglo XX estos métodos fueron llevados un paso más allá a medida
que fueron automatizados por la introducción de máquinas como la Enigma
(descifrada por los aliados en la 2da Guerra Mundial).
Con la introducción de la computadora, este proceso automatizado se hizo
aún más fácil e incluso se inventaron nuevos métodos criptográficos.
Hoy las computadoras están en todos lados.
Los gobiernos tienen acceso a casi todo. Los Administradores de Sistemas
tienen acceso a todos los archivos de su disco duro. La competencia
tiene acceso a laptops robadas... Quiero decir, tratando de no sonar
"demasiado" paranoico, que en el mundo de hoy la privacidad se hace cada
vez más difícil de lograr.
Pero no se preocupen. Tenenos la Criptografía para ayudarnos.
Garantía
========
SIN GARANTÍA.
ESTE ARTICULO VIENE SIN NINGUNA GARANTIA, Y SE PROVEE SOBRE LA BASE "TAL
Y COMO ESTA". USTED ASUME TODO EL COSTO DE CUALQUIER DAÑO RESULTANTE DE
LA INFORMACION CONTENIDA EN O PRODUCIDA POR LOS CONTENIDOS DE ESTE
ARTICULO. USTED ASUME TODAS LAS RESPONSABILIDADES POR LA SELECCION DE
ESTE ARTICULO PARA LOGRAR SUS RESULTADOS ESPERADOS, Y POR LA INSTALACION
DE, USO DE Y RESULTADOS OBTENIDOS DE EL. HASTA EL MAXIMO ALCANCE
PERMITIDO POR LA LEY APLICABLE, URI, SUS PROVEEDORES Y OTROS QUE PUEDEN
DISTRIBUIR ESTE ARTICULO DESCONOCEN TODA GARANTIA, YA SEA EXPRESA O
IMPLICITA, INCLUYENDO PERO SIN LIMITARSE A LAS GARANTIAS IMPLICITAS DE
COMERCIALIZACION, ADECUACION A UN PROPOSITO PARTICULAR, CONFORMACION CON
LA DESCRIPCION, Y NO INFRINGIMIENTO, CON RESPECTO A ESTE PRODUCTO
SOFTWARE.
EN OTRAS PALABRAS: USELO BAJO SU PROPIO RIESGO
Definiciones
============
En la terminología cripto, un archivo legible sin más se llama
"Plaintext" (texto simple). El proceso de mezclar sus contenidos para
hacerlo ilegible se llama Encripción, entonces estamos Encriptando
un archivo. Este mensaje ilegible se llama ahora "Ciphertext"
(texto cifrado). La operación inversa, desenmarañar el texto cifrado, se
llama Desencripción, entonces Desencriptamos un archivo.
Estos dos procesos usan una Llave ("Key") pata encriptar o desencriptar
un archivo. Sólo conociendo la llave correcta deberíamos poder desen-
criptar un mensaje encriptado con esa llave.
Advertencia
===========
Estas definiciones son todas buenas y lindas, pero el mundo real es un
poco diferente. Puede parecer fácil y entretenido crear "ciphers"
(algortimos criptográficos) pero no lo es.
La buena encripción se ve igual que la mala. Ambas producen basura
ilegible. Pero no se deje engañar. Siempre use ciphers públicos y bien
conocidos, uno que haya sido estudiado por profesionales y haya sido
analizado por años. Siempre trate de obtener el código fuente de los
ciphers. Siga el siguiente enlace para aprender cómo diferenciar un
buen producto de uno malo:
http://www.interhack.net/people/cmcurtin/snake-oil-faq.html
He tratado de ser tan preciso como sea posible al escribir este
artículo. Sin embargo el español no es mi lengua natal y no soy un
criptógrafo profesional, así que algunos errores pueden aparecer en el
artículo. Por favor siéntase libre de comentarme acerca de ellos o de
otros temas enviando un email a <urifrid@hushmail.com>.
El algoritmo
============
Elegí Twofish como el algoritmo para esta introducción. Lo hice por
varias razones:
1) Fue escrito por Bruce Schneier (www.counterpane.com), un criptógrafo
y criptoanalista muy conocido
2) No ha sido roto
3) Es fácil de usar
4) ES PUBLICO. El código fuente puede obtenerse de varios lugares.
5) Puede uasrse en cualquier modo: ECB, CBC, CFB 8bit, OFB, OFB counter
8bit. Para conocer más acerca de los modos lea Applied Crytography
(Criptografía Aplicada) de Bruce Schneier o vaya a su sitio web:
http://www.counterpane.com
En breve, Twofish es:
- Un cipher de bloques de 128 bits. Encripta bloques de 128 bits de
tamaño.
- Llaves de 128, 192 o 256 bits. Puede usar varias longitudes para las
llaves. En general, si un cipher tiene una llave de 128 bits se
requerirían 2^128 intentos para tratar todas y cada una de las
llaves.
- Realiza 16 rondas de encripción. Itera el cipher 16 veces antes de
devolver el texto cifrado.
El código en Delphi para este algoritmo fue portado de la implementación
original en C por David Barton (<davebarton@bigfoot.com>). Puede
descargar muchos otros ciphers de su página web:
http://www.scramdisk.clara.net
Aquí proveo todos los archivos que se usan en este artículo. Los
encontrará en el archivo que acompaña este artículo.
El código
=========
Cree un nuevo proyecto. Agregue 3 cuadros de texto (Edit1, Edit2 y
Edit3), 4 buttons (encrypt, decrypt, hash and browse), también agregue
un radiogroup y llámelo RadioHex, inserte dos radiobuttons en él, uno
"Mostrar en Hexadecimal" y el otro "Mostrar en Base64".
Vamos a agregar lo siguiente a la cláusula uses:
uses SHA1, Twofish, Base64;
* SHA1 es el Hash. Las funciones de hash de una sola vía son como
huellas digitales de los datos "hasheados" que toman una entrada de
longitud variable y producen una salida de longitud fija (160 bits en
SHA1). Las funciones de hash aseguran que si la información se cambia
de alguna forma –aunque sea por un solo bit– se produce un valor de
salida completamente diferente. Esto es útil de muchas formas. Una de
ellas es por ejemplo para encriptar un archivo y luego hacer un hash
del archivo encriptado. Puede enviar tanto el archivo como su hash.
Cuando el otro lado recibe el archivo puede verificar si el mismo ha
sido alterando creando su hash y comparándolo con el hash que ha sido
enviado. Por supuesto que el hash debe ser enviado de un modo que sea
seguro que no sea tocado (probablemente usando algún algoritmo público
de encriptación de llaves como RSA). Vamos a usar hashes para crear
una huella digital tanto de la constraseña ingreada como del archivo
encriptado.
* TWOFISH es el algortimo de encripción.
* Base64 es una forma de codificar la salida para que sólo esté formada
por caracteres imprimibles.
Agregue los siguientes procedimientos a su programa:
// produce un hash de una cadena
procedure _HashString(s: string; var Digest: TSHA1Digest);
var
Context: TSHA1Context; // registro para guardar los
// datos intermedios
begin
SHA1Init(Context); // inicializa el reg. de datos
SHA1Update(Context,@S[1],Length(S)); // actualiza el registro de
// datos con la cadena
SHA1Final(Context,Digest); // produce el hash final
end;
// produce un hash de un archivo
procedure _HashFile(filename: string; var Digest: TSHA1Digest);
var
Context: TSHA1Context; // registro para guardar los
// datos intermedios
Source: file; // archivo origen
Buffer: array[1..8192] of byte; // búfer de lectura
Read: integer; // cantidad de bytes leídos
begin
AssignFile(Source,filename);
try
Reset(Source,1);
except
MessageDlg('No se pudo abrir el archivo de origen',
mtInformation,[mbOK],0);
Exit;
end;
SHA1Init(Context); // inicializa el reg. de datos
repeat
BlockRead(Source,Buffer,Sizeof(Buffer),Read);
SHA1Update(Context,@Buffer,Read); // actualiza el hash
until Read<> Sizeof(Buffer);
SHA1Final(Context,Digest); // produce el hash final
CloseFile(Source);
end;
Estos procedimientos producen un hash de una sola vía para archivos y
cadenas.
Note que el proceso de encripción y desencripción será como este:
1) obtener un hash de la contraseña
2) inicializar la llave en el algoritmo usando el hash
3) hacer un IV (el primer bloque a usar en los modos encadenados)
4) encriptar o desencriptar
5) quemar datos (llave en memoria, IV, etc.) y preparar el algoritmo
para la siguiete tarea.
6) (Opcional) obtener un hash del archivo encriptado
En (1) generamos el hash de la contraseña del usuario. Este hash será
usado en (2) para inicializar la llave. Esta llave NO es la contraseña
que el usuario escribió. En (3) generamos el primer bloque de datos
encriptados, este bloque contiene datos aleatorios. Esto se hace porque
estamos usando uno de los modos encadenados donde necesitamos que cada
bloque dependa del anterior para ser encriptado. Esto ayuda a ocultar
patrones en el texto como redundancias y otras cabeceras de archivo
(como "PK" en archivos zipeados). En (4) realizamos la verdadera
encripción/desencripción y en (5) nos deshacemos de los datos ubicados
en memoria (no queremos ningún cracker robando nuestra contraseña
¿verdad?).
Entonces, en el procedimiento OnClick del botón que llamamos Encrypt
puede escribir lo siguiente (Advertencia, esto SOBRESCRIBIRA el archivo
original. A menos que recuerde la constraseña, no podrá recuperar los
datos):
var
KeyData: TTwofishData; // los datos de la llave inicializada
Digest: TSHA1Digest;
IV: array[0..15] of byte; // el vetor de inicialización vector
// necesario para modos encadenados
Buffer: array[0..8191] of byte;
Source,source2: file;
i, j, n: integer;
Key: string;
NumRead, NumWritten: Integer;
begin
Key:= edit2.Text; // you wrote the password in edit2
_HashString(Key,Digest);
TwofishInit(KeyData,@Digest,Sizeof(Digest),nil); // inicializa los
// datos de la llave usando el hash de la llave
FillChar(IV,Sizeof(IV),0); // llenar al IV con ceros
TwofishEncryptCBC(KeyData,@IV,@IV); // encriptar el IV para obtener
// un IV 'aleatorio'
Move(IV,KeyData.InitBlock,Sizeof(KeyData.InitBlock)); // mover el
// IV en keydata para usar encadenamiento
TwofishReset(KeyData); // resetear keydata para usar el nuevo IV
AssignFile(Source, edit1.Text); // archivo a encriptar en edit1
try
Reset(Source,1);
except
TwofishBurn(KeyData); // deshacernos de los datos
MessageDlg('No se pudo abrir el archivo...', mtInformation,
[mbOK], 0);
Edit2.text:='00000000000000000000000000000000';
Edit2.text:='';
Exit;
end;
repeat
n:= FilePos(Source);
BlockRead(Source,Buffer,Sizeof(Buffer),i);
for j:= 1 to (i div 16) do // 16 es el tamaño de bloque de
// Twofish que procesa en bloques de bytes
TwofishEncryptCBC(KeyData,@Buffer[(j-1)*Sizeof(IV)], // encriptar
@Buffer[(j-1)*Sizeof(IV)]);
if (i mod 16)<> 0 then // encrypt the last bytes that don't
// fit in to a full block
begin
Move(KeyData.LastBlock,IV,Sizeof(IV));
TwofishEncryptCBC(KeyData,@IV,@IV); // encriptar el bloque
// completo nuevamente (p/que esté encriptado dos veces)
for j:= 1 to (i mod 16) do
// xor this encrypted block with the short block
Buffer[(i and not 15)+j]:= Buffer[(i and not 15)+j] xor IV[j];
end;
Seek(Source,n);
BlockWrite(Source,Buffer,i); // escribir el búfer en el archivo
until i<> Sizeof(Buffer);
CloseFile(Source);
TwofishBurn(KeyData); // deshacernos de los datos
Edit2.text:='00000000000000000000000000000000';
Edit2.text:='';
Edit1.text:='';
MessageDlg('Listo. El archivo ha sido encriptado con el mismo ' +
'nombre que el original.', mtInformation, [mbOK], 0);
end;
Presto! Acabamos de encriptar el archivo en Edit1 con la contraseña en
Edit2!
Para desencriptar hacemos exactamente lo mismo, pero en vez de usar
TwofishEncryptCBC usamos:
TwofishDecryptCBC(KeyData,@Buffer[(j-1)*Sizeof(IV)],
@Buffer[(j-1)*Sizeof(IV)]);
Simple, ¿no?
Muy bien, tiene su archivo encriptado. Un lindo toque sería generar el
hash de ese archivo encriptado y enviarlo junto con él.
Para lograr esto usaremos el procedimiento _HashFile que escribimos
antes. En el procedimiento OnClick para el botón que llamó Hash agregue
lo siguiente:
procedure TForm1.HashClick(Sender: TObject);
var
Digest: TSHA1Digest; // Forma binaria del hash
i: integer;
begin
if Edit1.Text='' then exit; // asegurarnos que tenemos un archivo
_HashFile(Edit1.Text,Digest); // calcular el hash y
// guardarlo en Digest
if radiohex.ItemIndex=0 then // queremos mostrar el
// hash en hexadecimal
begin
Edit3.Text:= '0x';
for i:= 0 to (Sizeof(Digest)-1) do
Edit3.Text:= Edit3.Text+IntToHex(Digest[i],2); // convertir Digest
// a una cadena hexadecimal
end
else // in base64
begin
Edit3.Text:= '';
for i:= 0 to (Sizeof(Digest)-1) do
Edit3.Text:= Edit3.Text+chr(Digest[i]); // convertir Digest a
// base64
Edit3.Text:=B64Encode(Edit3.Text);
end;
end;
Ahora podemos elegir guardar el hash en un archivo y comprimir tanto el
archivo encriptado como su hash en un solo arcihvo .zip. Podemos ahora
enviar el archivo zip a un amigo estando seguros que sólo el/ella podrá
desencriptarlo.
Esta es una simple aplicación. Mucho más puede agregársele para hacerla
más segura, pero este es sólo un ejemplo. Le queda a usted agregar su
propio código y recuerde:
"...que los fuentes lo acompañen."
El código fuente de SHA1, Twofish y Base64 junto con el programa que los
usa puede encontrarlo en el archivo que acompaña este artículo. Por
favor asegúrese de leer la garantía muy cuidadosamente.
Gracias.
Uri, Febrero 10, 2001. - urifrid@hushmail.com
---------------
NOTA: Por si tiene interés, Uri tiene una aplicación freeware que
presenta una interfaz tipo explorador que le permite encriptar y
desencriptar archivos. También hay disponible una versión de consola:
http://www.geocities.com/urifrid/soft.html
________________________________________________________________________
3. BARRA DE PROGRESO SIN MARCO
Por Vladimir S. <shvetadvipa@mtu-net.ru>
La barra de progreso (ProgressBar) de Delphi siempre tiene marco. Si
desea ponerla en una barra de estado (StatusBar) no se ve muy lindo que
digamos. Puede hacer un pequeño cambio en el componente y así obtener un
nuevo componente sin borde.
Vea la figura (progress.gif). Puede ver tres barras de progreso. Una es
el componente estándar de Delphi con marco y el resto de ellas son el
componente con una propiedad nueva. Ahora puede quitar el marco de la
barra de progreso.
unit NewProgress;
// By Vladimir S. <shvetadvipa@mtu-net.ru>
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls;
type
TNProgressBar = class(TProgressBar)
procedure WMNCPAINT(var Msg: TMessage); message WM_NCPAINT;
private
FShowFrame: boolean;
procedure SetShowFrame(Value: boolean);
public
constructor Create(AOwner: TComponent); override;
published
property ShowFrame: boolean read FShowFrame write SetShowFrame;
end;
procedure Register;
implementation
{ TNProgressBar }
constructor TNProgressBar.Create(AOwner: TComponent);
begin
inherited;
FShowFrame := True;
end;
procedure TNProgressBar.SetShowFrame(Value: boolean);
begin
if FShowFrame <> Value then begin
FShowFrame:= Value;
RecreateWnd;
end;
end;
procedure TNProgressBar.WMNCPAINT(var Msg: TMessage);
var
DC: HDC;
RC: TRect;
begin
if ShowFrame then begin
inherited;
Invalidate;
end else begin
DC := GetWindowDC(Handle);
try
Windows.GetClientRect(Handle, RC);
with RC do begin
Inc(Right, 2);
Inc(Bottom, 2);
end;
Windows.FillRect(DC, RC, Brush.Handle);
finally
ReleaseDC(Handle, DC);
end;
end;
end;
procedure Register;
begin
RegisterComponents('Controls', [TNProgressBar]);
end;
end.
________________________________________________________________________
4. PUBLICACIONES ELECTRONICAS GRATUITAS
Para los programadores en Delphi de habla hispana existen hoy tres
publicaciones electrónicas gratuitas:
* AbracaDelphi! - Trucos Delphi en tu email
Para estudiantes y principiantes en Delphi. Algoritmos, rutinas,
ejercicios, etc. El primer número saldrá a fines de Febrero. Semanal.
http://www.geocities.com/abracadelphi/
Suscribir: [Publicación cancelada]
Cancelar : abracadelphi-unsubscribe@ecircle.es
* Boletín Pascal - Una publicación gratuita para programadores Delphi (y
Kylix) de nivel intermedio con artículos, trucos, noticias, enlaces...
http://www.latiumsoftware.com/es/pascal/index.php
Suscribir: pascal-es-suscribir@latiumsoftware.com
Cancelar : pascal-es-cancelar@latiumsoftware.com
* Revista Síntesis
Una revista gratuita dedicada a todo lo referente al entorno Borland.
Se recibe por email una notificación para descargar un archivo ZIP de
la web (~1.3Mb) que contiene la revista en formato PDF y los ejemplos
de código fuente dentro de otro ZIP. Bimensual.
http://www.grupoalbor.com/sintesis/
Suscribir: revista_sintesis-subscribe@egroups.com
Cancelar : revista_sintesis-unsubscribe@egroups.com
________________________________________________________________________
5. ENLACES
* Lord Trancos' DirectX Laboratory (sitio en español)
Recursos y código fuente sobre programación de DirectX 8 bajo Delphi
http://www.geocities.com/dxlab/
________________________________________________________________________
¡TÚ PUEDES AYUDARNOS!
Necesitamos tu ayuda para que este boletín pueda continuar y crecer. Una
forma en que puedes ayudarnos es enviando este enlace a tus amigos:
http://www.latiumsoftware.com/es/pascal/index.php
Otra forma es votándonos en alguno de estos rankings para darle más
visibilidad a nuestro sitio web y aumentar así el número de suscrip-
ciones al boletín, que esperamos en el futuro se traduzca también en un
mayor número de colaboraciones de artículos, trucos, etc.:
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://www.lawebdelprogramador.com/buscar/votar.php?id=615
Por favor vota. Son sólo unos segundos para ti que REALMENTE pueden
hacer la diferencia. Necesitamos tu ayuda para poder continuar.
________________________________________________________________________
Si no has recibido el archivo con el código fuente completo de los
ejemplos que se presentan en este boletín, puedes descargarlo de la
siguiente dirección: http://www.latiumsoftware.com/es/file.php?id=p17
________________________________________________________________________
Página principal: http://www.latiumsoftware.com/es/pascal/index.php
Página del grupo: http://espanol.groups.yahoo.com/group/boletin-pascal/
Para suscribirse / apuntarse: boletin-pascal-subscribe@gruposyahoo.com
Para cancelar / removerse: boletin-pascal-unsubscribe@gruposyahoo.com
Para reportar problemas con la suscripción: eds2008 @ latiumsoftware.com
________________________________________________________________________
Este boletín se provee "TAL Y COMO ESTA", sin garantía de ninguna clase.
Su uso implica la aceptación de nuestros términos de licencia y de la
ausencia de garantía que puedes leer en nuestro sitio web. Allí también
encontrarás una nota sobre marcas registradas. Te animamos a que redis-
tribuyas este boletín, siempre y cuando lo hagas en forma completa
(incluyendo la información de copyright), sin modificaciones y de manera
gratuita. Los artículos son copyright de sus respectivos autores y se
reproducen aquí con el permiso de los mismos.
________________________________________________________________________
Latium Software http://www.latiumsoftware.com/es/index.php
Copyright (c) 2001 por Ernesto De Spirito. Todos los derechos reservados
________________________________________________________________________
|