Descifrar ficheros .crypt5 de Whatsapp

Recientemente whatsapp a cambiado el algoritmo y las claves de cifrado que utilizaba para cifrar las copias de la base de datos que guarda en la tarjeta SD de nuestros teléfonos. No es que sea un cambio muy grande, a pasado de usar una clave única para todos a usar una personalizada para cada usuario, y ademas ha dejado de utilizar el método de cifrado ECB para usar CBC con un vector de inicialización (IV), aunque este ultimo si que es igual para todo el mundo. En resumen, esta es otra buena ocasión para probar mi colección de funciones criptográficas (SeCrypt) y hacer un pequeño programa que permita descifrar este fichero.

El programa es el siguiente:

program Crypt5;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils,
  Classes,  
  SeAES256 in 'SeCrypt\SeAES256.pas',
  SeBase64 in 'SeCrypt\SeBase64.pas',
  SeSHA256 in 'SeCrypt\SeSHA256.pas',
  SeStreams in 'SeCrypt\SeStreams.pas',
  SeMD5 in 'SeCrypt\SeMD5.pas';
 
var
  {
   Las claves las conseguí aquí:
   w w w . securitybydefault.com/2014/03/descifrando-msgstoredbcrypt5-la-nueva.html
  }
  Key: array[0..23] of Byte = (141, 75, 21, 92, 201, 255, 129, 229, 203, 246, 250,
    120, 25, 54, 106, 62, 198, 33, 166, 86, 65, 108, 215, 147);
  IV:  array[0..15] of Byte = ($1E,$39,$F3,$69,$E9,$D,$B3,$3A,$A7,$3B,$44,$2B,
    $BB,$B6,$B0,$B9);
 
  i: Integer;
  md5: AnsiString;
  AESKey: TAESKey;
  AESExpandedKey: TAESExpandedKey;
  AESIV: TAESState;
  Src, Dst: TFileStream;
begin
  try
    // Abrimos el archivo cifrado
    Src:= TFileStream.Create(ParamStr(1),fmOpenRead or fmShareDenyWrite);
    try
      // Calculamos el hash md5 de la cuenta de usuario
      md5:= MD5ToStr(CalcMD5(ParamStr(2)));
      for i:= 0 to 23 do
        // Mezclamos el hash con la clave usand XOR
        Key[i]:= Key[i] xor Byte(StrToInt('$'+Copy(md5,(2*(i and $0F))+1,2)));
      // Creamos el archivo de salida
      Dst:= TFileStream.Create(ParamStr(3),fmCreate);
      try
        FillChar(AESKey,Sizeof(AESKey),0);
        // Inicializamos la clave con el valor calculado
        AESCopyKey(AESKey,@Key,192);
        // Expandimos la clave, indicando que es de 192 bits
        AESExpandKey(AESExpandedKey,AESKey,192);
        // Cargamos el vector de inicializacion en un bloque
        move(IV,AESIV,Sizeof(IV));
        with TAESDec.Create(Dst,AESExpandedKey,AESIV) do
        try
          // Desciframos el fichero
          CopyFrom(Src,0);
        finally
          Free;
        end;
      finally
        Dst.Free;
      end;
    finally
      Src.Free
    end;
  except
    // Si ocurre algun error lo mostramos
    On E: Exception do
    begin
      Writeln(E.Message); 
    end;
  end;
end.

Ejemplo de uso (tu cuenta de gmail es necesaria para calcular la clave de cifrado):

Crypt5 msgstore.db.crypt5 tucuenta @ gmail.com msgstore.db

El código esta hecho en delphi (pascal), y puede compilarse tanto en delphi como en lazarus/freepascal. Las "unit" necesarias son las ya mencionadas SeCrypt que se pueden descargar de aquí:
https://drive.google.com/folderview?id=0Byro2cahD9xEZDlSdTEzT2VTOWM&usp=...

Esta vez no pongo el ejecutable ya compilado porque la ultima vez que hable de whatsapp por aquí recibí un aluvión de visitas de gente que lo que menos le interesaba era la programación, incluso de alguna mujer que intentaba espiar a su marido (me llegaron a ofrecer dinero si les ayudaba). Así que solamente dejo el código fuente, el que lo entienda no tendrá problemas en compilarlo el mismo y el que no lo entienda que deje de espiar a su pareja que eso esta muy feo.

Enlaces de interés:
http://www.securitybydefault.com/2014/03/descifrando-msgstoredbcrypt5-la...
http://code.google.com/p/secrypt/