Cifrado AES-256

Advanced Encryption Standard (AES), también conocido como Rijndael, es un sistema de cifrado por bloques adoptado como un estándar por el gobierno de los Estados Unidos. Actualmente es uno de los algoritmos más populares usados en criptografía simétrica.

Para saber mas sobre AES:
http://es.wikipedia.org/wiki/AES
http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
http://csrc.nist.gov/CryptoToolkit/aes/rijndael/

Existen multitud de implementaciones de este algoritmo, para todo tipo de lenguajes y plataformas, así que te preguntaras por que hacer otra implementación mas. La razón es que me apetecía hacerlo, pero tampoco está de más disponer de un código simple, pequeño, que pueda integrar en mis proyectos de Delphi sin tener que agregar una de esas enormes librerías de criptográfica, con un montón de algoritmos.

El algoritmo es el AES-256, es decir una clave de 256 bits y un tamaño de bloque de 16 bytes. Hay mas variantes de AES con diferentes tamaños de clave, pero como ya dije, busco la sencillez por encima de la variedad.

Es una unidad (AES.pas):

unit AES;
 
interface
 
uses Sysutils, Classes;
 
type
  TAESState = Array[0..3,0..3] of Byte;
  TAESKey = Array[0..7] of Cardinal;
  TAESExpandedKey = Array[0..59] of Cardinal;
 
procedure AESExpandKey(var ExpandedKey: TAESExpandedKey; Key: TAESKey);
procedure AESEncrypt(var State: TAESState; ExpandedKey: TAESExpandedKey);
procedure AESDecrypt(var State: TAESState; ExpandedKey: TAESExpandedKey);
procedure AESEncryptStreamECB(Source, Dest: TStream;
  ExpandedKey: TAESExpandedKey);
procedure AESDecryptStreamECB(Source, Dest: TStream;
  ExpandedKey: TAESExpandedKey);
procedure AESEncryptStreamCBC(IV: TAESState; Source, Dest: TStream;
  ExpandedKey: TAESExpandedKey);
procedure AESDecryptStreamCBC(IV: TAESState; Source, Dest: TStream;
  ExpandedKey: TAESExpandedKey);
 
implementation
 
const
  Sbox: Array[0..255] of Byte = (
    $63,$7c,$77,$7b,$f2,$6b,$6f,$c5,$30,$01,$67,$2b,$fe,$d7,$ab,$76,
    $ca,$82,$c9,$7d,$fa,$59,$47,$f0,$ad,$d4,$a2,$af,$9c,$a4,$72,$c0,
    $b7,$fd,$93,$26,$36,$3f,$f7,$cc,$34,$a5,$e5,$f1,$71,$d8,$31,$15,
    $04,$c7,$23,$c3,$18,$96,$05,$9a,$07,$12,$80,$e2,$eb,$27,$b2,$75,
    $09,$83,$2c,$1a,$1b,$6e,$5a,$a0,$52,$3b,$d6,$b3,$29,$e3,$2f,$84,
    $53,$d1,$00,$ed,$20,$fc,$b1,$5b,$6a,$cb,$be,$39,$4a,$4c,$58,$cf,
    $d0,$ef,$aa,$fb,$43,$4d,$33,$85,$45,$f9,$02,$7f,$50,$3c,$9f,$a8,
    $51,$a3,$40,$8f,$92,$9d,$38,$f5,$bc,$b6,$da,$21,$10,$ff,$f3,$d2,
    $cd,$0c,$13,$ec,$5f,$97,$44,$17,$c4,$a7,$7e,$3d,$64,$5d,$19,$73,
    $60,$81,$4f,$dc,$22,$2a,$90,$88,$46,$ee,$b8,$14,$de,$5e,$0b,$db,
    $e0,$32,$3a,$0a,$49,$06,$24,$5c,$c2,$d3,$ac,$62,$91,$95,$e4,$79,
    $e7,$c8,$37,$6d,$8d,$d5,$4e,$a9,$6c,$56,$f4,$ea,$65,$7a,$ae,$08,
    $ba,$78,$25,$2e,$1c,$a6,$b4,$c6,$e8,$dd,$74,$1f,$4b,$bd,$8b,$8a,
    $70,$3e,$b5,$66,$48,$03,$f6,$0e,$61,$35,$57,$b9,$86,$c1,$1d,$9e,
    $e1,$f8,$98,$11,$69,$d9,$8e,$94,$9b,$1e,$87,$e9,$ce,$55,$28,$df,
    $8c,$a1,$89,$0d,$bf,$e6,$42,$68,$41,$99,$2d,$0f,$b0,$54,$bb,$16
  );
 
  InvSbox: Array[0..255] of Byte = (
    $52,$09,$6a,$d5,$30,$36,$a5,$38,$bf,$40,$a3,$9e,$81,$f3,$d7,$fb,
    $7c,$e3,$39,$82,$9b,$2f,$ff,$87,$34,$8e,$43,$44,$c4,$de,$e9,$cb,
    $54,$7b,$94,$32,$a6,$c2,$23,$3d,$ee,$4c,$95,$0b,$42,$fa,$c3,$4e,
    $08,$2e,$a1,$66,$28,$d9,$24,$b2,$76,$5b,$a2,$49,$6d,$8b,$d1,$25,
    $72,$f8,$f6,$64,$86,$68,$98,$16,$d4,$a4,$5c,$cc,$5d,$65,$b6,$92,
    $6c,$70,$48,$50,$fd,$ed,$b9,$da,$5e,$15,$46,$57,$a7,$8d,$9d,$84,
    $90,$d8,$ab,$00,$8c,$bc,$d3,$0a,$f7,$e4,$58,$05,$b8,$b3,$45,$06,
    $d0,$2c,$1e,$8f,$ca,$3f,$0f,$02,$c1,$af,$bd,$03,$01,$13,$8a,$6b,
    $3a,$91,$11,$41,$4f,$67,$dc,$ea,$97,$f2,$cf,$ce,$f0,$b4,$e6,$73,
    $96,$ac,$74,$22,$e7,$ad,$35,$85,$e2,$f9,$37,$e8,$1c,$75,$df,$6e,
    $47,$f1,$1a,$71,$1d,$29,$c5,$89,$6f,$b7,$62,$0e,$aa,$18,$be,$1b,
    $fc,$56,$3e,$4b,$c6,$d2,$79,$20,$9a,$db,$c0,$fe,$78,$cd,$5a,$f4,
    $1f,$dd,$a8,$33,$88,$07,$c7,$31,$b1,$12,$10,$59,$27,$80,$ec,$5f,
    $60,$51,$7f,$a9,$19,$b5,$4a,$0d,$2d,$e5,$7a,$9f,$93,$c9,$9c,$ef,
    $a0,$e0,$3b,$4d,$ae,$2a,$f5,$b0,$c8,$eb,$bb,$3c,$83,$53,$99,$61,
    $17,$2b,$04,$7e,$ba,$77,$d6,$26,$e1,$69,$14,$63,$55,$21,$0c,$7d
  );
 
  LogTable: Array[0..255] of Byte = (
    $00,$ff,$c8,$08,$91,$10,$d0,$36,$5a,$3e,$d8,$43,$99,$77,$fe,$18,
    $23,$20,$07,$70,$a1,$6c,$0c,$7f,$62,$8b,$40,$46,$c7,$4b,$e0,$0e,
    $eb,$16,$e8,$ad,$cf,$cd,$39,$53,$6a,$27,$35,$93,$d4,$4e,$48,$c3,
    $2b,$79,$54,$28,$09,$78,$0f,$21,$90,$87,$14,$2a,$a9,$9c,$d6,$74,
    $b4,$7c,$de,$ed,$b1,$86,$76,$a4,$98,$e2,$96,$8f,$02,$32,$1c,$c1,
    $33,$ee,$ef,$81,$fd,$30,$5c,$13,$9d,$29,$17,$c4,$11,$44,$8c,$80,
    $f3,$73,$42,$1e,$1d,$b5,$f0,$12,$d1,$5b,$41,$a2,$d7,$2c,$e9,$d5,
    $59,$cb,$50,$a8,$dc,$fc,$f2,$56,$72,$a6,$65,$2f,$9f,$9b,$3d,$ba,
    $7d,$c2,$45,$82,$a7,$57,$b6,$a3,$7a,$75,$4f,$ae,$3f,$37,$6d,$47,
    $61,$be,$ab,$d3,$5f,$b0,$58,$af,$ca,$5e,$fa,$85,$e4,$4d,$8a,$05,
    $fb,$60,$b7,$7b,$b8,$26,$4a,$67,$c6,$1a,$f8,$69,$25,$b3,$db,$bd,
    $66,$dd,$f1,$d2,$df,$03,$8d,$34,$d9,$92,$0d,$63,$55,$aa,$49,$ec,
    $bc,$95,$3c,$84,$0b,$f5,$e6,$e7,$e5,$ac,$7e,$6e,$b9,$f9,$da,$8e,
    $9a,$c9,$24,$e1,$0a,$15,$6b,$3a,$a0,$51,$f4,$ea,$b2,$97,$9e,$5d,
    $22,$88,$94,$ce,$19,$01,$71,$4c,$a5,$e3,$c5,$31,$bb,$cc,$1f,$2d,
    $3b,$52,$6f,$f6,$2e,$89,$f7,$c0,$68,$1b,$64,$04,$06,$bf,$83,$38
  );
 
  InvLogTable: Array[0..255] of Byte = (
    $01,$e5,$4c,$b5,$fb,$9f,$fc,$12,$03,$34,$d4,$c4,$16,$ba,$1f,$36,
    $05,$5c,$67,$57,$3a,$d5,$21,$5a,$0f,$e4,$a9,$f9,$4e,$64,$63,$ee,
    $11,$37,$e0,$10,$d2,$ac,$a5,$29,$33,$59,$3b,$30,$6d,$ef,$f4,$7b,
    $55,$eb,$4d,$50,$b7,$2a,$07,$8d,$ff,$26,$d7,$f0,$c2,$7e,$09,$8c,
    $1a,$6a,$62,$0b,$5d,$82,$1b,$8f,$2e,$be,$a6,$1d,$e7,$9d,$2d,$8a,
    $72,$d9,$f1,$27,$32,$bc,$77,$85,$96,$70,$08,$69,$56,$df,$99,$94,
    $a1,$90,$18,$bb,$fa,$7a,$b0,$a7,$f8,$ab,$28,$d6,$15,$8e,$cb,$f2,
    $13,$e6,$78,$61,$3f,$89,$46,$0d,$35,$31,$88,$a3,$41,$80,$ca,$17,
    $5f,$53,$83,$fe,$c3,$9b,$45,$39,$e1,$f5,$9e,$19,$5e,$b6,$cf,$4b,
    $38,$04,$b9,$2b,$e2,$c1,$4a,$dd,$48,$0c,$d0,$7d,$3d,$58,$de,$7c,
    $d8,$14,$6b,$87,$47,$e8,$79,$84,$73,$3c,$bd,$92,$c9,$23,$8b,$97,
    $95,$44,$dc,$ad,$40,$65,$86,$a2,$a4,$cc,$7f,$ec,$c0,$af,$91,$fd,
    $f7,$4f,$81,$2f,$5b,$ea,$a8,$1c,$02,$d1,$98,$71,$ed,$25,$e3,$24,
    $06,$68,$b3,$93,$2c,$6f,$3e,$6c,$0a,$b8,$ce,$ae,$74,$b1,$42,$b4,
    $1e,$d3,$49,$e9,$9c,$c8,$c6,$c7,$22,$6e,$db,$20,$bf,$43,$51,$52,
    $66,$b2,$76,$60,$da,$c5,$f3,$f6,$aa,$cd,$9a,$a0,$75,$54,$0e,$01
  );
 
 
procedure SubBytes(var State: TAESState);
var
  i,j: Integer;
begin
  for i:= 0 to 3 do
    for j:= 0 to 3 do
      State[i,j]:= Sbox[State[i,j]];
end;
 
procedure InvSubBytes(var State: TAESState);
var
  i,j: Integer;
begin
  for i:= 0 to 3 do
    for j:= 0 to 3 do
      State[i,j]:= InvSbox[State[i,j]];
end;
 
procedure ShiftRows(var State: TAESState);
var
  i,j,k: Integer;
begin
  for j:= 1 to 3 do
    for i:= j downto 1 do
    begin
      k:= State[0,j];
      State[0,j]:= State[1,j];
      State[1,j]:= State[2,j];
      State[2,j]:= State[3,j];
      State[3,j]:= k;
    end;
end;
 
procedure InvShiftRows(var State: TAESState);
var
  i,j,k: Integer;
begin
  for j:= 1 to 3 do
    for i:= j downto 1 do
    begin
      k:= State[3,j];
      State[3,j]:= State[2,j];
      State[2,j]:= State[1,j];
      State[1,j]:= State[0,j];
      State[0,j]:= k;
    end;
end;
 
function Mult(X, Y: Byte): Byte;
begin
  if (X = 0) or (Y = 0) then
    Result:= 0
  else
    Result:= InvLogTable[(LogTable[X] + LogTable[Y]) mod $FF];
end;
 
procedure MixColumns(var State: TAESState);
var
  i,j: Integer;
  m: Array[0..3] of Byte;
begin
  for i:= 0 to 3 do
  begin
    for j:= 0 to 3 do
      m[j]:= State[i,j];
    State[i,0]:= Mult(2,m[0]) XOR Mult(3,m[1]) XOR m[2] XOR m[3];
    State[i,1]:= m[0] XOR Mult(2,m[1]) XOR Mult(3,m[2]) XOR m[3];
    State[i,2]:= m[0] XOR m[1] XOR Mult(2,m[2]) XOR Mult(3,m[3]);
    State[i,3]:= Mult(3,m[0]) XOR m[1] XOR m[2] XOR Mult(2,m[3]);
  end;
end;
 
procedure InvMixColumns(var State: TAESState);
var
  i,j: Integer;
  m: Array[0..3] of Byte;
begin
  for i:= 0 to 3 do
  begin
    for j:= 0 to 3 do
      m[j]:= State[i,j];
    State[i,0]:=
      Mult($0e,m[0]) XOR Mult($0b,m[1]) XOR Mult($0d,m[2]) XOR Mult($09,m[3]);
    State[i,1]:=
      Mult($09,m[0]) XOR Mult($0e,m[1]) XOR Mult($0b,m[2]) XOR Mult($0d,m[3]);
    State[i,2]:=
      Mult($0d,m[0]) XOR Mult($09,m[1]) XOR Mult($0e,m[2]) XOR Mult($0b,m[3]);
    State[i,3]:=
      Mult($0b,m[0]) XOR Mult($0d,m[1]) XOR Mult($09,m[2]) XOR Mult($0e,m[3]);
  end;
end;
 
procedure AddRoundKey(var State: TAESState; ExpandedKey: TAESExpandedKey;
  Round: Integer);
var
  i: Integer;
  W: Cardinal;
begin
  for i:= 0 to 3 do
  begin
    W:= ExpandedKey[(Round * 4) + i];
    State[i,0]:= State[i,0] XOR ((W shr 24) and $FF);
    State[i,1]:= State[i,1] XOR ((W shr 16) and $FF);
    State[i,2]:= State[i,2] XOR ((W shr 8) and $FF);
    State[i,3]:= State[i,3] XOR (W and $FF);
  end;
end;
 
function SubWord(W: Cardinal): Cardinal;
begin
  Result:= (Sbox[W shr 24] shl 24) or (Sbox[(W shr 16) and $FF] shl 16) or
    (Sbox[(W shr 8) and $FF] shl 8) or Sbox[W and $FF];
end;
 
function RotWord(W: Cardinal): Cardinal;
begin
  Result:= (W shl 8) or (W shr 24);
end;
 
function RCon(n: Integer): Cardinal;
begin
  Result:= 1;
  if n = 0 then
    Result:= 0
  else while n > 1 do
  begin
    Result:= Mult(Result,2);
    dec(n);
  end;
  Result:= Result shl 24;
end;
 
procedure AESExpandKey(var ExpandedKey: TAESExpandedKey; Key: TAESKey);
var
  i: Integer;
  Temp: Cardinal;
begin
  FillChar(ExpandedKey,Sizeof(ExpandedKey),#0);
  for i:= 0 to 7 do
    ExpandedKey[i]:= Key[i];
  for i:= 8 to 59 do
  begin
    Temp:= ExpandedKey[i-1];
    if (i mod 8 = 0) then
      Temp:= SubWord(RotWord(Temp)) XOR Rcon(i div 8)
    else if (i mod 8 = 4) then
      Temp:= SubWord(temp);
    ExpandedKey[i]:= ExpandedKey[i-8] XOR Temp;
  end;
end;
 
procedure AESEncrypt(var State: TAESState; ExpandedKey: TAESExpandedKey);
var
  Round: Integer;
begin
  AddRoundKey(State,ExpandedKey,0);
  for Round:= 1 to 13 do
  begin
    SubBytes(State);
    ShiftRows(State);
    MixColumns(State);
    AddRoundKey(State,ExpandedKey,Round);
  end;
  SubBytes(State);
  ShiftRows(State);
  AddRoundKey(State,ExpandedKey,14);
end;
 
procedure AESDecrypt(var State: TAESState; ExpandedKey: TAESExpandedKey);
var
  Round: Integer;
begin
  AddRoundKey(State,ExpandedKey,14);
  for Round:= 13 downto 1 do
  begin
    InvShiftRows(State);
    InvSubBytes(State);
    AddRoundKey(State,ExpandedKey,Round);
    InvMixColumns(State);
  end;
  InvShiftRows(State);
  InvSubBytes(State);
  AddRoundKey(state,ExpandedKey,0);
end;
 
procedure AESEncryptStreamECB(Source, Dest: TStream;
  ExpandedKey: TAESExpandedKey);
var
  State: TAESState;
begin
  FillChar(State,Sizeof(State),#0);
  while Source.Read(State,Sizeof(State)) > 0 do
  begin
    AESEncrypt(State,ExpandedKey);
    Dest.WriteBuffer(State,Sizeof(State));
    FillChar(State,Sizeof(State),#0);
  end;
end;
 
procedure AESDecryptStreamECB(Source, Dest: TStream;
  ExpandedKey: TAESExpandedKey);
var
  State: TAESState;
begin
  FillChar(State,Sizeof(State),#0);
  while Source.Read(State,Sizeof(State)) > 0 do
  begin
    AESDecrypt(State,ExpandedKey);
    Dest.WriteBuffer(State,Sizeof(State));
    FillChar(State,Sizeof(State),#0);
  end;
end;
 
procedure XORState(var S1: TAESState; S2: TAESState);
var
  i,j: Integer;
begin
  for i:= 0 to 3 do
    for j:= 0 to 3 do
      S1[i,j]:= S1[i,j] XOR S2[i,j];
end;
 
procedure AESEncryptStreamCBC(IV: TAESState; Source, Dest: TStream;
  ExpandedKey: TAESExpandedKey);
var
  State: TAESState;
begin
  FillChar(State,Sizeof(State),#0);
  while Source.Read(State,Sizeof(State)) > 0 do
  begin
    XORState(State,IV);
    AESEncrypt(State,ExpandedKey);
    Dest.WriteBuffer(State,Sizeof(State));
    IV:= State;
    FillChar(State,Sizeof(State),#0);
  end;
end;
 
procedure AESDecryptStreamCBC(IV: TAESState; Source, Dest: TStream;
  ExpandedKey: TAESExpandedKey);
var
  Temp: TAESState;
  State: TAESState;
begin
  FillChar(State,Sizeof(State),#0);
  while Source.Read(State,Sizeof(State)) > 0 do
  begin
    Temp:= State;
    AESDecrypt(State,ExpandedKey);
    XORState(State,IV);
    Dest.WriteBuffer(State,Sizeof(State));
    IV:= Temp;
    FillChar(State,Sizeof(State),#0);
  end;
end;
 
end.

Para cifrar cualquier dato con AES hay que tener en cuenta que siempre se tiene que realizar en bloques de 16 bytes. Si el numero de bytes a cifrar no es múltiplo de 16, yo sugiero rellenar con ceros el ultimo bloque hasta completarlo. Para explicar mejor el proceso, nada mejor que un pequeño ejemplo:
var
  SrcName, DstName: String;
  SrcStream, DstStream: TFileStream;
  Size: int64;
  Clave: String;
  Key: TAESKey;
  ExpandedKey: TAESExpandedKey;
begin
  // Seleccionamos un origen
  SrcName:= EmptyStr;
  with TOpenDialog.Create(nil) do
  try
    if Execute then
      SrcName:= Filename;
  finally
    Free;
  end;
  // Seleccionamos un destino
  DstName:= EmptyStr;
  with TSaveDialog.Create(nil) do
  try
    if Execute then
      DstName:= Filename;
  finally
    Free;
  end;
  if (SrcName <> EmptyStr) and (DstName <> EmptyStr) then
  begin
    SrcStream:= TFileStream.Create(SrcName,fmOpenRead or fmShareDenyWrite);
    try
      DstStream:= TFileStream.Create(DstName,fmCreate);
      try 
        Clave:= 'Password';
        FillChar(Key,Sizeof(Key),#0);
        if Length(Clave) > Sizeof(Key) then
          move(PChar(Clave)^,Key,Sizeof(key))
        else
          move(PChar(Clave)^,Key,Length(Clave));
        AEsExpandKey(ExpandedKey,Key);
        // Guardamos el tamaño del archivo
        Size:= SrcStream.Size;
        DstStream.WriteBuffer(Size,Sizeof(Size));
        AESEncryptStreamECB(SrcStream,DstStream,ExpandedKey);
      finally
        DstStream.Free;
      end;
    finally
      SrcStream.Free;
    end;
  end;
end;

Y para descifrar tenemos este otro ejemplo:

var
  SrcName, DstName: String;
  SrcStream, DstStream: TFileStream;
  Size: int64;
  Clave: String;
  Key: TAESKey;
  ExpandedKey: TAESExpandedKey;
begin
  // Seleccionamos un origen
  SrcName:= EmptyStr;
  with TOpenDialog.Create(nil) do
  try
    if Execute then
      SrcName:= Filename;
  finally
    Free;
  end;
  // Seleccionamos un destino
  DstName:= EmptyStr;
  with TSaveDialog.Create(nil) do
  try
    if Execute then
      DstName:= Filename;
  finally
    Free;
  end;
  if (SrcName <> EmptyStr) and (DstName <> EmptyStr) then
  begin
    SrcStream:= TFileStream.Create(SrcName,fmOpenRead or fmShareDenyWrite);
    try
      DstStream:= TFileStream.Create(DstName,fmCreate);
      try 
        Clave:= 'Password';
        FillChar(Key,Sizeof(Key),#0);
        if Length(Clave) > Sizeof(Key) then
          move(PChar(Clave)^,Key,Sizeof(key))
        else
          move(PChar(Clave)^,Key,Length(Clave));
        AESExpandKey(ExpandedKey,Key);
        // Leemos el tamaño del archivo
        SrcStream.ReadBuffer(Size,Sizeof(Size));
        AESDecryptStreamECB(SrcStream,DstStream,ExpandedKey);
        DstStream.Size:= Size;
      finally
        DstStream.Free;
      end;
    finally
      SrcStream.Free;
    end;
  end;
end;

Sugerencias y correcciones sobre el código, serán bien recibidas.

Holas! Gracias por compartir

Holas! Gracias por compartir este trabajo ^_^. Me gustaría hacer unas preguntas sobre el uso de este PAS.
- ¿Qué es lo que encripta este módulo? Por el ejemplo, me da la impresión que encripta archivos... ¿Es así? Porque yo quiero encriptar meras palabras... ¿Se puede?
- ¿Cómo uso el PAS? Esto y lo anterior deben sonar estúpido a óidos de maestros programadores... Lo siento, pero debo decir que a mis años aún no sé cómo se implementa el contenido de un PAS en otro, que no sea usando TForm o módulo de Data ^^U. El caso es que he creado módulos así, sólo el PAS, pero luego no sé cómo llamarlo desde un Tform aparte...
Esop. Muchas gracias desde ya!! Saludos :D

Hola Carolina, aquí tienes

Hola Carolina, aquí tienes tus respuestas:
- Para cifrar texto mira aquí. http://delphi.jmrds.com/?q=node/44
- Para usar una unit (archivo PAS) puedes usar el menú "Project -> Add To Project" (buscalo en delphi) o copiarla al mismo directorio donde tienes el código de tu aplicación. Luego solo tienes que colocar el nombre de la unit (sin el .pas) en las "uses" de donde la quieras usar.

¿Cuál es la diferencia entre

¿Cuál es la diferencia entre los procedimientos terminados en ECB y los terminados en CBC?

Pues aquí tienes la wikipedia

Pues aquí tienes la wikipedia que lo explica maravillosamente:

http://es.wikipedia.org/wiki/Modos_de_operación_de_una_unidad_de_cifrado_por_bloques

Básicamente son dos métodos diferentes de operar con cifrado por bloques.

Excelente, gracias.

Excelente, gracias.

Una cosa más respecto a los

Una cosa más respecto a los procedimientos CBC, piden como primer parámetro un tipo TAESState ¿de dónde sale eso?, es decir, ¿que tendría que pasarle en ese parámetro?.

Disculpa que insista pero estoy tratando de transformar esta unidad en una clase para luego hacer un componente...

Es el "vector inicial". Como

Es el "vector inicial". Como en el método CBC cada bloque se cifra junto al resultado del bloque anterior es necesario suministrar un bloque inicial para combinar con el primer bloque.

Este bloque puede ser lo que tu quieras, pero tiene que ser el mismo tanto para cifrar como para descifrar. Puedes usar un bloque con todos los valores a cero o usar uno personalizado, lo que tu prefieras.

Si vas a crear un componente yo lo dejaría como una propiedad más del componente.

Básicamente es como una

Básicamente es como una segunda clave de encriptación. Sí, debe ser una propiedad de la clase también, el tema es que hay que proporcionar un array de números y ahí se complica para hacer algo cómodo. Algo me voy a inventar, gracias y disculpa las molestias.

He encontrado un pequeño bug

He encontrado un pequeño bug (o glich). Si el tamaño del archivo original no es múltiplo de 16, cuando el archivo encriptado resultante se desencripta para volver al original, se obtiene un archivo con bytes al final que no están en el original haciendo siempre que el tamaño del archivo sea múltiplo de 16.

El problema aparentemente está en las líneas:

Dest.WriteBuffer(State,Sizeof(State));

de los procedimientos DecryptStream. No debería ser Sizeof(State) sino el size de la lectura actual del TStreamFile Source...

En un cifrado por bloques, el

En un cifrado por bloques, el archivo una vez cifrado SIEMPRE tiene un tamaño múltiplo del tamaño del bloque. Por esa razón se ha de guardar aparte el tamaño original del fichero para luego ajustar el tamaño al descifrarlo. Si te fijas en el código de ejemplo, cuando cifra un archivo guarda primero el tamaño original en la cabecera del archivo cifrado, y cuando lo descifra ajusta el tamaño del fichero una vez descifrado.

Por otro lado, la instrucción que mencionas esta bien como esta. Recuerda que este es un cifrado por BLOQUES, así que los bloques han de guardarse completos, si intentas descifrar un bloque incompleto el resultado sera completamente diferente al original.

Enviar un comentario nuevo

El contenido de este campo se mantiene privado y no se mostrará públicamente.