Showing posts with label Encryption Algorithms. Show all posts
Showing posts with label Encryption Algorithms. Show all posts

Thursday, 15 April 2010

Encrypting with OpenSSL

These days I've been immersed into new projects creating certificates with the OpenSSL tool, and I found interesting the part of encrypting files. Then, with simple steps, we can encrypt/decrypt our documents and share information safely. I've tested both of the versions (for Linux and Windows) and then following example is for windows. You can find a little distro of the OpenSSL for windows here. Once there, you need to download the full version (with source). This one will copy all the necessary libraries you need to generate certificates and encrypting documents. You can find the OpenSSL app into the next path : C:\OpenSSL\bin. You can also download and install the available version in "Shining Light Productions" The version I've tested is the Win32 OpenSSL v0.9.8m. If we want to encrypt a file we need to execute the following sentence into the command dialog:
C:\OpenSSL\bin>openssl aes-256-cbc -a -salt -in "fileToencrypt.rar" -out "fileToEncrypt.rar.enc"
  • Openssl command to launch the OpenSSL.
  • aes-256-cbc The encryption system used is AES 256 bits.
  • -a The encrypted files is in base64.
  • -salt Add strong to the encryption.
  • -in Input file.
  • -out Output file.
For the desencryption, we only need to do:
C:\OpenSSL\bin>openssl aes-256-cbc -d -a -in "fileToEncrypt.rar.enc" -out "fileToencrypt.rar"
  • -d decrypting command.
  • -a The encrypted files is in base64.
  • -in Input file.
  • -out Output file.
We can play with all these parameters, and we'll find more information on the help page.

If in windows, you find this error message:

unable to load config info from /usr/local/ssl/openssl.cnf

you only need to add at the end of the OpenSSL command the option: -config openssl.cfg.
you can find a little description of the problem here.

Then, if we want to create a little certificate, we can do it with a simple command like this:
C:\OpenSSL\bin>openssl req -x509 -newkey rsa:2048 -keyout key.pem -days 3650 -out certificate.pem
After the execution, you'll need to fill up all the fields needed, and then your certificate will be generated.

C:\OpenSSL\bin>openssl req -x509 -newkey rsa:2048 -keyout key.pem -days 3650 -out certificate.pem
Loading 'screen' into random state - done
Generating a 2048 bit RSA private key
.................................+++
........+++
writing new private key to 'key.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:AU
State or Province Name (full name) [Some-State]:Australia
Locality Name (eg, city) []:Sidney
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Sky
Organizational Unit Name (eg, section) []:Sky
Common Name (eg, YOUR name) []:Test
Email Address []:test@test.com
If you open the certificate.pem you'll get something like this:


Tuesday, 18 August 2009

Codificar y descodificar un String en Base 64

En una de mis aplicaciones, utilicé el siguiente código adaptado por Jacob Dybala (el código original es de David Barton) donde se nos muestra un algoritmo simple de codificación y descodificación de un string en base64. Éste ejemplo funcionó muy bien para codificar una serie de passwords y luego almancenarlos en una BD. Podemos variar el algoritmo a nuestro gusto por si queremos añadir un charset diferente o mejorar alguna cosa de su implementación. Aunque en la entrada de Jacob Dybala, él mejora y optimiza bastante el tema del espacio utilizado. Para éste ejemplo desarrollé una pequeña aplicación llamada Thundax Encode/Decode String Base64, y la podréis descargar para comprobar si os gusta la salida del algoritmo. También podréis encontrar varios codificadores base64 online, aquí os dejo varios enlaces para que los probéis:
  1. base64 Online.
  2. base64 Online.
Código fuente:

unit String64;

interface

uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls;

const
    B64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

function Base64Decode(const S: string): string;
function Base64Encode(const S: string): string;

implementation

{$R *.dfm}

function Base64Encode(const S: string): string;
var
    InBuf: array[0..2] of Byte;
    OutBuf: array[0..3] of Char;
    iI, iJ: Integer;
begin
    SetLength(Result, ((Length(S) + 2) div 3) * 4);
    for iI := 1 to ((Length(S) + 2) div 3) do
    begin
        if Length(S) < (iI * 3) then
            Move(S[(iI - 1) * 3 + 1], InBuf, Length(S) - (iI - 1) * 3)
        else
            Move(S[(iI - 1) * 3 + 1], InBuf, 3);
        OutBuf[0] := B64Table[((InBuf[0] and $FC) shr 2) + 1];
        OutBuf[1] := B64Table[(((InBuf[0] and $3) shl 4) or ((InBuf[1] and $F0) shr 4)) + 1];
        OutBuf[2] := B64Table[(((InBuf[1] and $F) shl 2) or ((InBuf[2] and $C0) shr 6)) + 1];
        OutBuf[3] := B64Table[(InBuf[2] and $3F) + 1];
        Move(OutBuf, Result[(iI - 1) * 4 + 1], 4);
    end;
    if Length(S) mod 3 = 1 then
    begin
        Result[Length(Result) - 1] := '=';
        Result[Length(Result)] := '=';
    end
    else if Length(S) mod 3 = 2 then
        Result[Length(Result)] := '=';
end;

function Base64Decode(const S: string): string;
var
    OutBuf: array[0..2] of Byte;
    InBuf: array[0..3] of Byte;
    iI, iJ: Integer;
begin
    if Length(S) mod 4 <> 0 then
        raise Exception.Create('Base64: Incorrect string format');
    SetLength(Result, ((Length(S) div 4) - 1) * 3);
    for iI := 1 to (Length(S) div 4) - 1 do
    begin
        Move(S[(iI - 1) * 4 + 1], InBuf, 4);
        for iJ := 0 to 3 do
            case InBuf[iJ] of
                43: InBuf[iJ] := 62;
                48..57: Inc(InBuf[iJ], 4);
                65..90: Dec(InBuf[iJ], 65);
                97..122: Dec(InBuf[iJ], 71);
            else
                InBuf[iJ] := 63;
            end;
        OutBuf[0] := (InBuf[0] shl 2) or ((InBuf[1] shr 4) and $3);
        OutBuf[1] := (InBuf[1] shl 4) or ((InBuf[2] shr 2) and $F);
        OutBuf[2] := (InBuf[2] shl 6) or (InBuf[3] and $3F);
        Move(OutBuf, Result[(iI - 1) * 3 + 1], 3);
    end;
    if Length(S) <> 0 then
    begin
        Move(S[Length(S) - 3], InBuf, 4);
        if InBuf[2] = 61 then
        begin
            for iJ := 0 to 1 do
                case InBuf[iJ] of
                    43: InBuf[iJ] := 62;
                    48..57: Inc(InBuf[iJ], 4);
                    65..90: Dec(InBuf[iJ], 65);
                    97..122: Dec(InBuf[iJ], 71);
                else
                    InBuf[iJ] := 63;
                end;
            OutBuf[0] := (InBuf[0] shl 2) or ((InBuf[1] shr 4) and $3);
            Result := Result + Char(OutBuf[0]);
        end
        else if InBuf[3] = 61 then
        begin
            for iJ := 0 to 2 do
                case InBuf[iJ] of
                    43: InBuf[iJ] := 62;
                    48..57: Inc(InBuf[iJ], 4);
                    65..90: Dec(InBuf[iJ], 65);
                    97..122: Dec(InBuf[iJ], 71);
                else
                    InBuf[iJ] := 63;
                end;
            OutBuf[0] := (InBuf[0] shl 2) or ((InBuf[1] shr 4) and $3);
            OutBuf[1] := (InBuf[1] shl 4) or ((InBuf[2] shr 2) and $F);
            Result := Result + Char(OutBuf[0]) + Char(OutBuf[1]);
        end
        else
        begin
            for iJ := 0 to 3 do
                case InBuf[iJ] of
                    43: InBuf[iJ] := 62;
                    48..57: Inc(InBuf[iJ], 4);
                    65..90: Dec(InBuf[iJ], 65);
                    97..122: Dec(InBuf[iJ], 71);
                else
                    InBuf[iJ] := 63;
                end;
            OutBuf[0] := (InBuf[0] shl 2) or ((InBuf[1] shr 4) and $3);
            OutBuf[1] := (InBuf[1] shl 4) or ((InBuf[2] shr 2) and $F);
            OutBuf[2] := (InBuf[2] shl 6) or (InBuf[3] and $3F);
            Result := Result + Char(OutBuf[0]) + Char(OutBuf[1]) + Char(OutBuf[2]);
        end;
    end;
end;

procedure TForm3.Button1Click(Sender: TObject);
begin
    if Edit1.text = '' then
        exit;
    Edit2.text := Base64Encode(Edit1.text);
end;

procedure TForm3.Button2Click(Sender: TObject);
begin
    if Edit2.text = '' then
        exit;
    Edit1.text := Base64Decode(Edit2.text);
end;

end.


Aplicación:


Espero que os guste el algoritmo, ya que en mi opinión creo que hay que tenerlo siempre a mano.
  • Enlaces de interés:
How to Base 64 (MIME) Encode and Decode a String

Tuesday, 14 July 2009

Calculando el Hash MD5 y SHA1

Últimamente si os fijáis cuando realizáis una descarga por internet, podréis ver que además os adjuntan un fichero md5 o sha1 para que comprobéis que realmente os habéis descargado lo que se supone que debería haber en ese fichero. Pues bien aquí os dejo una mini aplicación hecha por mi que os permitirá coger un fichero y generar su MD5 y SHA1 para que podáis comprobar que realmente coincide con el valor del hash del fichero. El código utilizado lo he sacado de ClubDelphi, donde encontrareis muchos ejemplos. El ejemplo de la mano de Domingo Seoane nos permite calcular el hash de un fichero, de un stream o de un texto. Podéis visitar su web en mi blog roll (la web de Seoane).
Para éste ejemplo, utilizaré una descarga típica de la web de eclipse, por ejemplo jetty (el cuál os hablaré en los próximos posts). Pues bien, podemos descargar éste componente desde la web de eclipse. Una vez en ésta página, podremos encontrar el fichero jetty-distribution-7.0.0.M4.zip, jetty-distribution-7.0.0.M4.zip.md5 y jetty-distribution-7.0.0.M4.zip.sha1 los cuales contienen la aplicación y los hashes MD5 y SHA1. Para el fichero descargado si abrimos los MD5 y SHA1, encontraremos los siguientes hashes:

MD5:
976bf42aa03a58accc042d2682e533da

SHA1:
92feb7386e486d2560663686449275588ddb056e

Pues bien, al descargar el fichero deberíamos comprobar que realmente el fichero descargado genera el mismo hash. Para esto utilizaré mi aplicación Thundax Calc Hash, que podréis descargar aquí.

Mediante la aplicación, podremos cargar un fichero y utilizando el algoritmo de Seoane generar los MD5 y SHA1:

Aquí os dejo el código fuente y su utilización:

unit hashes:




unit Hashes;

interface

uses
Windows, SysUtils, Classes;

type
THashAlgorithm = (haMD5, haSHA1);

function CalcHash(Stream: TStream; Algorithm: THashAlgorithm): string; overload;
function CalcHash(Archivo: string; Algorithm: THashAlgorithm): string; overload;
function CalcHash2(Str: string; Algorithm: THashAlgorithm): string;

implementation

type
HCRYPTPROV = ULONG;
PHCRYPTPROV = ^HCRYPTPROV;
HCRYPTKEY = ULONG;
PHCRYPTKEY = ^HCRYPTKEY;
HCRYPTHASH = ULONG;
PHCRYPTHASH = ^HCRYPTHASH;
LPAWSTR = PAnsiChar;
ALG_ID = ULONG;

const
CRYPT_NEWKEYSET = $00000008;
PROV_RSA_FULL = 1;
CALG_MD5 = $00008003;
CALG_SHA1 = $00008004;
HP_HASHVAL = $0002;

function CryptAcquireContext(phProv: PHCRYPTPROV;
pszContainer: LPAWSTR;
pszProvider: LPAWSTR;
dwProvType: DWORD;
dwFlags: DWORD): BOOL; stdcall;
external ADVAPI32 name 'CryptAcquireContextA';

function CryptCreateHash(hProv: HCRYPTPROV;
Algid: ALG_ID;
hKey: HCRYPTKEY;
dwFlags: DWORD;
phHash: PHCRYPTHASH): BOOL; stdcall;
external ADVAPI32 name 'CryptCreateHash';

function CryptHashData(hHash: HCRYPTHASH;
const pbData: PBYTE;
dwDataLen: DWORD;
dwFlags: DWORD): BOOL; stdcall;
external ADVAPI32 name 'CryptHashData';

function CryptGetHashParam(hHash: HCRYPTHASH;
dwParam: DWORD;
pbData: PBYTE;
pdwDataLen: PDWORD;
dwFlags: DWORD): BOOL; stdcall;
external ADVAPI32 name 'CryptGetHashParam';

function CryptDestroyHash(hHash: HCRYPTHASH): BOOL; stdcall;
external ADVAPI32 name 'CryptDestroyHash';

function CryptReleaseContext(hProv: HCRYPTPROV; dwFlags: DWORD): BOOL; stdcall;
external ADVAPI32 name 'CryptReleaseContext';

function CalcHash(Stream: TStream; Algorithm: THashAlgorithm): string; overload;
var
hProv: HCRYPTPROV;
hHash: HCRYPTHASH;
Buffer: PByte;
BytesRead: DWORD;
Algid: ALG_ID;
Data: array[1..20] of Byte;
DataLen: DWORD;
Success: BOOL;
i: integer;
begin
Result := EmptyStr;
Success := CryptAcquireContext(@hProv, nil, nil, PROV_RSA_FULL, 0);
if (not Success) then
if GetLastError() = DWORD(NTE_BAD_KEYSET) then
Success := CryptAcquireContext(@hProv, nil, nil, PROV_RSA_FULL,
CRYPT_NEWKEYSET);
if Success then
begin
if Algorithm = haMD5 then
begin
Algid := CALG_MD5;
Datalen := 16
end
else
begin
Algid := CALG_SHA1;
Datalen := 20;
end;
if CryptCreateHash(hProv, Algid, 0, 0, @hHash) then
begin
GetMem(Buffer, 10 * 1024);
try
while TRUE do
begin
BytesRead := Stream.Read(Buffer^, 10 * 1024);
if (BytesRead = 0) then
begin
if (CryptGetHashParam(hHash, HP_HASHVAL, @Data, @DataLen, 0)) then
for i := 1 to DataLen do
Result := Result + LowerCase(IntToHex(Integer(Data[i]), 2));
break;
end;
if (not CryptHashData(hHash, Buffer, BytesRead, 0)) then
break;
end;
finally
FreeMem(Buffer);
end;
CryptDestroyHash(hHash);
end;
CryptReleaseContext(hProv, 0);
end;
end;

function CalcHash(Archivo: string; Algorithm: THashAlgorithm): string; overload;
var
Stream: TFileStream;
begin
Result := EmptyStr;
if FileExists(Archivo) then
try
Stream := TFileStream.Create(Archivo, fmOpenRead or fmShareDenyWrite);
try
Result := CalcHash(Stream, Algorithm);
finally
Stream.Free;
end;
except
end;
end;

function CalcHash2(Str: string; Algorithm: THashAlgorithm): string;
var
Stream: TStringStream;
begin
Result := EmptyStr;
Stream := TStringStream.Create(Str);
try
Result := CalcHash(Stream, Algorithm);
finally
Stream.Free;
end;
end;

end.




utilización:




procedure TForm1.Button1Click(Sender: TObject);
begin
if Edit1.text = '' then
Exit;
Memo1.Lines.clear;
Memo1.Lines.Add(CalcHash(Edit1.text, haMD5));
Memo2.Lines.clear;
Memo2.Lines.Add(CalcHash(Edit1.text, haSHA1));
end;

procedure TForm1.Button2Click(Sender: TObject);
var
i: integer;
sPath: string;
begin
OpenDialog1.Execute(self.Handle);
for i := 0 to OpenDialog1.Files.Count - 1 do
sPath := OpenDialog1.Files.Strings[i];
if sPath <> '' then
Edit1.text := sPath;
end;




  • Enlaces de interés:
MD5 Hash.

Saturday, 13 June 2009

Delphi CryptoAPI

CryptoAPI es una Cryptographic API interface unit de Borland Delphi. Partes de la misma fueron creadas por Microsoft, y la creación y traducción para Pascal fue de Massimo Maria Ghisalberti. Podemos encontrar la última versión del fichero en Project JEDI (Joint Endeavour of Delphi Innovators) en http://delphi-jedi.org, y está sujeta a una licencia : Mozilla Public License Version 1.1. El fichero es Wcrypt2.pas y lo podemos encontrar en diferentes ubicaciones por la red de libre descarga. Aquí os dejo un enlace para su descarga : Wcrypt2 o CryptoAPI2.zip. Mediante esta librería, podemos generar diferentes hashes (MD2, MD4, MD5, SHA, etc), utilizar diferentes encriptaciones (RC4, DES, RC5, HMAC, etc) sobre texto o ficheros. Aquí os dejo el código fuente para la implementación de una pequeña aplicación para calcular el MD5 de un texto, y encriptar y desencriptar un fichero de texto utilizando un Hash SHA y una encriptación con RC4.:

El código fuente para la generación de la aplicación es el siguiente:




unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Wcrypt2, StdCtrls, hashes;

type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
Edit5: TEdit;
CheckBox1: TCheckBox;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

procedure
CryptFile(const SourceFileName, DestinationFileName, Password: string; ToCrypt: Boolean);
var
hProv: HCRYPTPROV;
hash: HCRYPTHASH;
key: HCRYPTKEY;

Buffer: PByte;
len: dWord;
fsIn, fsOut: TFileStream;
IsEndOfFile: Boolean;
begin
{get context for crypt default provider}
CryptAcquireContext(@hProv, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
{create hash-object (SHA algorithm)}
CryptCreateHash(hProv, CALG_SHA, 0, 0, @hash);
{get hash from password}
CryptHashData(hash, @Password[1], Length(Password), 0);
{create key from hash by RC4 algorithm}
CryptDeriveKey(hProv, CALG_RC4, hash, 0, @key);
{destroy hash-object}
CryptDestroyHash(hash);

{open source+destination files}
fsIn := TFileStream.Create(SourceFileName, fmOpenRead or fmShareDenyWrite);
fsOut := TFileStream.Create(DestinationFileName, fmCreate);
try
{allocate buffer to read content from source file}
GetMem(Buffer, 512);

repeat
IsEndOfFile := (fsIn.Position >= fsIn.Size);
if IsEndOfFile then break;

{read content from source file}
len := fsIn.Read(Buffer^, 512);

if ToCrypt then
{crypt buffer}
CryptEncrypt(key, 0, IsEndOfFile, 0, Buffer, @len, len)
else
{decrypt buffer}
CryptDecrypt(key, 0, IsEndOfFile, 0, Buffer, @len);

{write changed buffer to destination file}
fsOut.Write(Buffer^, len)
until IsEndOfFile;

{release memory allocated for buffer}
FreeMem(Buffer, 512);
finally
fsIn.Free;
fsOut.Free;
end;

{release the context for crypt default provider}
CryptReleaseContext(hProv, 0);
end;

function MD5(const Value: string): string;
var
hCryptProvider: HCRYPTPROV;
hHash: HCRYPTHASH;
bHash: array[0..$7F] of Byte;
dwHashLen: dWord;
i: Integer;
begin
dwHashLen := 16;
if (Value = '') then
begin
Result := 'd41d8cd98f00b204e9800998ecf8427e';
exit;
end
else
Result := '';

{get context for crypt default provider}
if CryptAcquireContext(@hCryptProvider, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT or CRYPT_MACHINE_KEYSET) then
begin
{create hash-object MD5}
if CryptCreateHash(hCryptProvider, CALG_MD5, 0, 0, @hHash) then
begin
{get hash from password}
if CryptHashData(hHash, @Value[1], Length(Value), 0) then
begin
if CryptGetHashParam(hHash, HP_HASHVAL, @bHash[0], @dwHashLen, 0) then
begin
for i := 0 to dwHashLen-1 do
Result := Result + IntToHex(bHash[i], 2);
end;
end;
{destroy hash-object}
CryptDestroyHash(hHash);
end;
{release the context for crypt default provider}
CryptReleaseContext(hCryptProvider, 0);
end;

Result := AnsiLowerCase(Result);
end;


{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
Edit2.text := MD5(Edit1.Text);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
CryptFile(Edit3.text, Edit4.text, Edit5.text, CheckBox1.Checked);
end;

end.





Parte de éste está disponible en Scalabium Software, tips 172 y 173.

Las pruebas realizadas muestran que el cálculo del MD5 no es del todo válido. Si lo comprobamos con los diversas aplicaciones On-line del MD5, podemos obtener el hash para el texto 'esto es una prueba' = 254d4a6b00b78b94f846b85528298d43, y no 60bb1c95ab70cc37d452ee1414dd2656 que es lo que aparece en nuestra aplicación. Éste cálculo, lo podemos encontrar bien hecho en la web de Seoane, donde nos muestra un ejemplo con la unit Hashes.pas. Aquí os dejo un enlace para el MD5 On-line.

  • Enlaces de interés:
http://www.lincoln.edu/math/rmyrick/ComputerNetworks/InetReference/143.htm
Cryptography and Multiple-Precision Arithmetic

Friday, 12 June 2009

Ararat Synapse

Ararat Synapse, es una librería de comunicaciones TCP/IP open source para Dephi, C++Builder, Kylix y FreePascal. No es un componente, sino un set de librerías útiles para realizar todo tipo de comunicaciones ya que soporta TCP, UDP, ICMP, etc. Además soporta TCP a través de proxy HTTP, SSL, SMTP, FTP, etc. Una buena herramienta y alternativa a utilizar componentes Indy. Podemos acceder a la última versión de su aplicación mediante Subversion accediendo a la url: https://synalist.svn.sourceforge.net/svnroot/synalist/trunk/ o realizar la descarga directa de su última versión estable: synapse.zip.
Una vez descargada la librería, la podemos adjuntar a nuestro proyecto y compilarla para utilizar todas las herramientas disponibles. Aquí os dejo un ejemplo para realizar un get y un post a una URL mediante esta librería:



uses
SysUtils,Classes,httpsend,synacode;

var
sl : TStringList;
data : String;
begin
data := 'user=' + ParamStr(1);
data := data + '&' + 'pass=' + ParamStr(2);
data := EncodeURL(data);

sl := TStringList.Create;
with THTTPSend.Create do
begin
if HttpGetText('http://localhost/datos.php?' + data,sl) then
try
WriteLn(sl.text);
except
WriteLn('Cannot get');
end;
sl.Free;
Free;
end;
end.




En este enlace de ejemplos, podemos encontrar lo que otras personas han hecho y lo han publicado en la web de synapse, muy útil.
  • VisualSynapse:
Visual Synapse, es un componente para Delphi, que utiliza la librería Synapse. Estos componentes visuales extienden la librería TCP/IP de synapse y la envuelven. Podemos descargar la última versión de la aplicación desde aquí: SourceForge.net.

  • Crypting libraries para SSL/TLS/SSH en Synapse:
Mediante este set de librerías para Delphi, Kylix y FreePascal, podemos utilizar diferentes algoritmos de encriptación para nuestros datos (mejorar la seguridad). En este enlace, encontraréis las últimas versiones estables para su descarga directa del set de componentes para la librería criptográfica de Synapse: http://synapse.ararat.cz/files/crypt/

Esta librería utiliza CriptLib, un componente de la mano de Wolfgang Gothier, que gracias a su fantástico trabajo, podemos disponer de un Add-on para Delphi con un sinfín de utilidades criptográficas. Podemos descargar la última versión de la librería en el siguiente enlace: http://cryptlib.sogot.de/delpas.html, además encontraremos muchos ejemplos y una buena documentación.

Sunday, 7 June 2009

Penjili Project

Penjili es un proyecto desarrollado por la EADS (European Aeronautic Defence and Space Company) y es una herramienta de análisis de software embebido. Ésta prueba la ausencia de vulnerabilidades de seguridad, por ejemplo los límites de una matriz, punteros con referencia null, desbordamientos, etc. Penjili con Newspeak (es un lenguaje de programación simplificado, bien adaptado a los fines de análisis) permite la entrada de ficheros C o ADA y genera una lista de warnings, indicando el origen del problema y el tipo de error. Si no hay ninguna advertencia, el código está libre de vulnerabilidades. Hay varios estudios que identifican este problema, como este por Xavier Allamigeon, Wenceslas Godad y Charles Hymans, donde hacen un análisis de la manipulación de Strings en Programas críticos embebidos escritos en C. En éste artículo se hace referencia al problema del uso de cadenas, ya que siempre tenemos que comprobar que la cadena de destino sea lo suficientemente larga como para poder albergar nuestra cadena original. Cuando no es el caso, y la cadena de destino es más larga, esta se llena con bytes aleatorios que pueden llegar a crear inesperadas posiciones de memoria.
En la página oficial del Proyecto Penjili, podemos encontrar una buena presentación explicando los contenidos más importantes de ésta, explicando las mejoras que conseguiremos en nuestra aplicación aplicando los parámetros de Penjili. Las características más importantes del proyecto son las siguientes:

Lograr una gran escalabilidad:
- más de 1 millón de líneas de código

Mantiene una gran precisión:
- más de 99% para las matrices y más del 95% para los punteros

Ha sido capaz de encontrar anomalías en Software verdadero y maduro.

Un ejemplo de conversión, utilizando el NewSpeak, es el siguiente:

Podemos encontrar toda la tabla de referencia en la misma web, y además podemos descargar todo el proyecto entero ya que está bajo una licencia LGPL. Desde este mismo enlace, podemos descargar la última versión de la aplicación NewSpeak 1.6, para que la podáis disfrutar y probar con vuestros proyectos generados en C o ADA. El proyecto llamado CtoNewSpeak, también lo podemos encontrar en SourceForge.

Aquí os dejo una imagen, que también la encontrareis en la web y que explica un poco la jerarquía del proyecto.

Gracias a JM_@Inject por hablarme de esta tecnología:

Penjili(뺀질이): in Korean, said of a person who is cunning at avoiding unnecessary work.