Borrado seguro de archivos
Artículo por Club Developers · 31 diciembre 2005
2613 vistas
puede ser interesante poder borrar de forma segura un archivo, es decir, de forma que sea casi imposible su recuperación con ningún programa "recuperador de archivos".
Esta función implementa el estándar DOD 5220.22-M del Depto. de defensa de EEUU para la limpieza y saneado de datos.
La rútina realiza lo siguiente:
1. Machaca el contenido del archivo 3 veces con un patrón distinto: todo a ceros, todo a unos y contenido aleatorio
2. Renombra el archivo 26 veces
3. Finalmente, borra el archivo
Aquà presentamos la unit entera:
Y ahora un ejemplo de llamada:
Esta función implementa el estándar DOD 5220.22-M del Depto. de defensa de EEUU para la limpieza y saneado de datos.
La rútina realiza lo siguiente:
1. Machaca el contenido del archivo 3 veces con un patrón distinto: todo a ceros, todo a unos y contenido aleatorio
2. Renombra el archivo 26 veces
3. Finalmente, borra el archivo
Aquà presentamos la unit entera:
delphi
unit SecureDel; interface function BorrarFichero(const NombreFichero: String): Boolean; implementation uses  Windows, SysUtils; const  TAMANIO_BUFFER = 65536;  NRO_BUFFERS = 3; var  FBuffers: array [0..NRO_BUFFERS-1] of ^byte; procedure CrearBuffers; var  i, j: Integer;  p: ^byte; begin  // obtenemos la memoria para los buffers (64Kb cada uno)  // y los rellenamos con info aleatoria  Randomize;  for i:=0 to Pred( NRO_BUFFERS ) do begin    GetMem( FBuffers[i], TAMANIO_BUFFER );    case i of       0: ; // relleno con ceros (lo hace el sistema)       1: FillChar( FBuffers[i]^, TAMANIO_BUFFER, $FF );       2: begin          p := @(FBuffers[i]^);          for j := TAMANIO_BUFFER downto 1 do begin            p^ := byte( Random( $FF ) );            Inc(p);          end;        end;    end;  end; end; procedure DestruirBuffers; var i: Integer; begin  for i:=0 to Pred( NRO_BUFFERS ) do FreeMem( FBuffers[i] ) end; function RenombrarFichero(const NombreFichero: String; var NuevoNombreFichero: String): Boolean; const  NRO_VECES_RENOMBRA = 26; var  i, j : Integer;  TmpNombreFichero, Ruta: String; begin  Ruta := ExtractFilePath( NombreFichero );  TmpNombreFichero := ExtractFileName( NombreFichero );  NuevoNombreFichero := TmpNombreFichero;  for i:= 0 to Pred( NRO_VECES_RENOMBRA ) do begin    for j := 1 to Length( NuevoNombreFichero ) do      if NuevoNombreFichero[j] <> '.'        then NuevoNombreFichero[j] := Char( Ord('A') + i );    if FileExists( Ruta + NuevoNombreFichero )      then Continue;    Result := RenameFile( Ruta + TmpNombreFichero, Ruta + NuevoNombreFichero );    if not Result      then Exit;    TmpNombreFichero := NuevoNombreFichero;  end;  NuevoNombreFichero := Ruta + NuevoNombreFichero; end; procedure MachacarFichero(const h: THandle; Longitud: Cardinal); var  i: Integer;  Posicion, TotalBytes, BytesEscritos, BytesAEscribir: Cardinal; begin  Posicion := Longitud;  for i:=0 to NRO_BUFFERS-1 do begin   if i <> 0     then SetFilePointer( h, -Posicion, nil, FILE_CURRENT );   TotalBytes := 0;   while TotalBytes < Longitud do begin     if Longitud - TotalBytes > TAMANIO_BUFFER         then BytesAEscribir := TAMANIO_BUFFER         else BytesAEscribir := Longitud - TotalBytes;     BytesEscritos := FileWrite( h, (FBuffers[i])^, BytesAEscribir );     if BytesEscritos = $FFFFFFFF       then RaiseLastWin32Error;     Inc( TotalBytes, BytesEscritos );   end;  end; end; function BorrarFichero(const NombreFichero: String): Boolean; var  h: THandle;  UltNomFich: String;  TamanioFileHi, TamanioFileLo, BytesAEscribir: Cardinal;  TamanioFile, BytesEscritos: Int64; begin  Result := False;  // cambiamos atributos del archivo por si tuviera atributos de solo lectura  Result := FileSetAttr( NombreFichero, faArchive ) = 0;  if not Result then begin   RaiseLastWin32Error;   Exit;  end;  // abrimos el archivo para escritura  h := FileOpen( NombreFichero, fmOpenWrite );  Result := h <> -1;  if not Result then begin   RaiseLastWin32Error;   Exit;  end;  // creamos los buffers de escritura de archivo  CrearBuffers;  try   // obtenemos tamaño del archivo   TamanioFileLo := GetFileSize( h, @TamanioFileHi );   // si el archivo no tiene tamaño 0, lo machacamos   if ( TamanioFileLo > 0 ) or ( TamanioFileHi > 0 ) then begin     // ponemos el puntero del archivo al final     Dec( TamanioFileLo );     if ( TamanioFileLo = $FFFFFFFF ) and ( TamanioFileHi > 0 )       then Dec( TamanioFileHi );     SetFilePointer( h, TamanioFileLo, @TamanioFileHi, FILE_BEGIN );     // escribimos un cero byte al final del archivo, lo q hace     // q el SO rellene con ceros todo el espacio ocupado por el archivo     MachacarFichero(h, 1);     // volvemos al principio del archivo y sobreescribimos     SetFilePointer( h, 0, nil, FILE_BEGIN );     BytesEscritos := 0;     TamanioFile := TamanioFileLo or (TamanioFileHi shl 32);     while BytesEscritos < TamanioFile do     begin       if TamanioFile - BytesEscritos < TAMANIO_BUFFER         then BytesAEscribir := TamanioFile - BytesEscritos         else BytesAEscribir := TAMANIO_BUFFER;       MachacarFichero( h, BytesAEscribir );       Inc( BytesEscritos, BytesAEscribir );     end;   end;  finally   // cerramos el archivo y liberamos memoria   FileClose( h );   DestruirBuffers;  end;  // cambiamos el archivo de nombre repetidas veces  Result := RenombrarFichero( NombreFichero, UltNomFich );  // finalmente, borramos el archivo  if Result then Result := DeleteFile( UltNomFich ); end; end.
Y ahora un ejemplo de llamada:
delphi
uses  SecureDel; .... procedure TForm1.Button1Click(Sender: TObject); begin  if edFile.Text <> '' then    if FileExists(edFile.Text) then     if BorrarFichero(edFile.Text) then     begin       ShowMessage('¡Hecho!');       edFile.Clear;     end    else     showmessage('El archivo no existe'); end;