Excel expone dos cosas que se llaman "contraseña", y solo una de ellas es cifrado. La contraseña de apertura activa un cifrado real: sin ella, el archivo no se puede leer en absoluto. Las contraseñas de protección de hoja de trabajo y libro de trabajo no hacen nada parecido. Establecen una bandera (flag) que un editor colaborador acepta respetar, y un libro de trabajo que solo lleva esa bandera es un archivo zip legible común con los datos en texto plano. Elija la incorrecta y enviará una nómina que parece bloqueada en Excel pero se lee en cualquier editor de texto
La prueba toma diez segundos. Cambie el nombre de un archivo .xlsx protegido a .zip, ábralo en cualquier herramienta de archivo y mire en xl/worksheets/sheet1.xml. Si los valores de las celdas están allí en UTF-8 plano, el archivo no está cifrado, por muchas solicitudes de contraseña que Excel genere cuando alguien intenta editar una celda. Esa brecha sobrevive durante años dentro de equipos que asumen que la protección de la hoja es confidencialidad, y generalmente sale a la luz el día en que una revisión de seguridad ejecuta exactamente este cambio de nombre
HotXLS es una biblioteca de hojas de cálculo nativa para Delphi y C++Builder, y mantiene las dos características en lados opuestos de esa línea. La protección de hojas de trabajo y libros de trabajo son restricciones de edición respaldadas por un hash heredado deliberadamente débil. SaveAsEncrypted produce un paquete cifrado con AES que nada que no sea la contraseña podrá abrir. Las secciones a continuación cubren lo que escribe esa llamada, la asimetría en torno a la cual debe diseñar (HotXLS escribe archivos cifrados pero no puede volver a leerlos) y en qué se diferencia la ruta XLS más antigua
¿Por qué la protección de la hoja no es cifrado?
Los métodos Protect en las hojas y ProtectWorkbook en el libro de trabajo almacenan un hash de 4 dígitos hexadecimales de la contraseña. Ese es el algoritmo heredado que tanto OOXML como BIFF heredaron de Excel de los años 90, y la documentación del formato nunca afirma que haga más que evitar ediciones accidentales. El paquete sigue siendo un zip legible normal: datos de celdas, fórmulas y cadenas compartidas, todo en XML de texto plano. El valor predeterminado lo empeora, no lo mejora. Cada celda comienza con Locked=True, por lo que llamar a Protect sin desbloquear primero un rango de entrada congela toda la hoja contra la edición mientras deja cada valor a la vista
Nada de lo cual hace que la protección sea inútil. Guiar a los usuarios hacia rangos editables y estabilizar un diseño para impresión son tareas reales, cubiertas en nuestro artículo sobre protección de hojas de trabajo y configuración de página. Pero esas son tareas de usabilidad. En el instante en que el requisito es la confidencialidad, la única API que responde a él es SaveAsEncrypted
Lo que escribe realmente SaveAsEncrypted
La implementación sigue el cifrado estándar ECMA-376, especificado en la sección 2.3.4 de [MS-OFFCRYPTO]. La contraseña pasa por 50,000 iteraciones de SHA-1 para derivar una clave AES-128. Un bloque verificador, cifrado con AES-128 en modo ECB, permite a un consumidor confirmar la contraseña antes de descifrar nada, y luego todo el paquete del libro de trabajo se cifra con AES-128 en modo CBC. Lo que aterriza en el disco no es un archivo zip en absoluto. Es un archivo compuesto OLE que contiene los flujos EncryptionInfo, EncryptedPackage y DataSpaces, sin ningún directorio xl/ para que una herramienta de archivo lo enumere, razón por la cual la prueba de cambio de nombre ahora no muestra nada legible. Excel 2007 y versiones posteriores lo abren solo con la contraseña, y la versión actual de LibreOffice también lee el cifrado estándar
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
rc: Integer;
begin
Book := TXLSXWorkbook.Create;
try
Sheet := Book.Sheets.Add('Payroll');
Sheet.Cells[1, 1].Value := 'Employee';
Sheet.Cells[1, 2].Value := 'Net pay';
Sheet.Cells[2, 1].Value := 'A. Garcia';
Sheet.Cells[2, 2].Value := 4815.16;
rc := Book.SaveAsEncrypted('payroll-2026-06.xlsx', PasswordFromVault);
if rc <> 1 then
raise Exception.CreateFmt('Encrypted save failed (rc=%d)', [rc]);
finally
Book.Free;
end;
end;
Trate la variable de contraseña con el mismo cuidado que una cadena de conexión. Recupérela de una bóveda (vault) o de un servicio de secretos generados en el último momento, nunca la registre (log) y nunca la escriba en el propio libro de trabajo. La comprobación del código de retorno no es una ceremonia opcional. Un guardado cifrado que falla a mitad de camino tiene que abortar la entrega, porque el único recurso alternativo que puede ofrecer el código de llamada es una copia no cifrada, y esa copia es el incidente exacto que esta característica existe para prevenir
También hay una prueba de aceptación comprobable por máquina que casi no cuesta nada: llame a CanReadEncrypted en el archivo que acaba de escribir. Devuelve verdadero solo cuando la salida es realmente un contenedor de cifrado, por lo que validarlo después de cada guardado cifrado detecta la regresión que más importa (una ruta de código que recurrió silenciosamente a un SaveAs simple) en el momento en que sucede, en lugar de semanas después en la bandeja de entrada de un cliente. La última palabra sigue perteneciendo a una apertura manual en Excel con la contraseña real durante las pruebas de lanzamiento
De solo escritura por diseño: manejo de EXlsxEncryptionNotImplemented
Aquí está la asimetría que debería dar forma a la arquitectura de su canalización: HotXLS cifra al guardar pero no descifra al abrir. OpenEncrypted genera EXlsxEncryptionNotImplemented cuando se apunta a un paquete cifrado real; en un libro de trabajo simple, simplemente pasa a un Open normal. La sonda complementaria CanReadEncrypted detecta el contenedor de cifrado OLE de forma económica, por lo que el código de entrada puede enrutar dichos archivos sin activar la excepción:
var
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
try
if Book.CanReadEncrypted(FileName) then
begin
// Encrypted container: HotXLS cannot decrypt it.
Writeln(FileName + ': needs manual decryption in Excel first');
Exit;
end;
try
Book.OpenEncrypted(FileName, ''); // plain files fall through to Open
Writeln(FileName + ': opened, ' + IntToStr(Book.Sheets.Count) + ' sheet(s)');
except
on EXlsxEncryptionNotImplemented do
Writeln(FileName + ': encrypted - routed to manual queue');
end;
finally
Book.Free;
end;
end;
Esa asimetría tiene una lectura arquitectónica clara: cifrar en el extremo de entrega, al final. Mantenga el maestro en texto plano dentro de su límite de confianza, en una base de datos, un almacén de documentos o un recurso compartido con control de acceso, y produce la copia cifrada como el paso final antes de que el archivo salga del sistema. Una canalización que archiva solo la salida cifrada se ha quedado bloqueada fuera de sus propios datos, porque ninguna etapa posterior del mismo sistema puede volver a abrir esos archivos. Cuando un proceso HotXLS descendente necesite el libro de trabajo nuevamente, entréguele el maestro en texto plano, nunca el artefacto de entrega
Cifrado estándar AES-128 y la línea de cumplimiento AES-256
El cifrado de archivos de Office viene en dos generaciones. El cifrado estándar, el que escribe HotXLS, utiliza AES-128 con derivación de clave SHA-1. El cifrado Agile llegó más tarde y se traslada a AES-256 con SHA-512 y un contenedor de claves diferente descrito en XML. Ambos se abren de forma transparente en Excel, y AES-128 sigue siendo computacionalmente sólido para proteger un archivo en tránsito hacia un cliente
La diferencia deja de ser académica el día en que un cuestionario de seguridad solicita "cifrado AES-256 de archivos en reposo". El cifrado estándar no cumple con esa línea, por muy fuerte que sea la contraseña, y ningún parámetro de SaveAsEncrypted cambia el algoritmo que emite. Por lo tanto, indique el perfil con precisión en su documentación de seguridad: AES-128, cifrado estándar ECMA-376, derivación de claves SHA-1 con 50,000 iteraciones. Una declaración que sobreviva a la revisión vale más que una optimista que se derrumbe bajo una auditoría
La ruta XLS heredada: RC4 de salida, RC4 y XOR de entrada
La fachada de BIFF tiene la forma opuesta. Su cifrado es más antiguo y débil, pero el viaje de ida y vuelta es completo: lo que escribe, también lo puede volver a leer. Establecer EncryptionPassword antes de SaveAs produce un archivo .xls cifrado con RC4 a través del mecanismo FilePass de BIFF, y Open con un parámetro de contraseña lee los tres esquemas heredados: RC4, RC4 CryptoAPI y la antigua ofuscación XOR:
var
Writer, Reader: IXLSWorkbook; // interface refs: no manual Free
begin
Writer := TXLSWorkbook.Create;
Writer.Sheets.Add.Cells.Item[1, 1].Value := 'Confidential';
Writer.EncryptionPassword := 'S3cret!';
Writer.SaveAs('confidential.xls');
Reader := TXLSWorkbook.Create;
if Reader.Open('confidential.xls', 'S3cret!') > 0 then
Writeln(Reader.Sheets[1].Cells.Item[1, 1].Value); // Entries are 1-based
end;
RC4 es criptografía obsoleta y nunca debería proteger datos que importen hoy en día; su único valor restante es la interoperabilidad con sistemas que aún intercambian .xls. Sin embargo, el lado de la lectura se gana su lugar en el trabajo de migración. Un archivo heredado protegido por contraseña se abre con Open(FileName, Password), se puentea al modelo OOXML y se vuelve a proteger a través de la ruta AES, una actualización unidireccional que se ejecuta sin Excel en ningún lugar del proceso. Para entregas cifradas de gran volumen, las notas de rendimiento del lado del guardado en nuestro artículo sobre escrituras de transmisión para trabajos por lotes en servidores se aplican a la fase de construcción de contenido que ocurre antes del cifrado
Cifrado y protección no son rivales
Un punto más que vale la pena resolver, porque surge en el momento en que alguien lee la advertencia en la parte superior de esta página como "la protección no sirve para nada". No es así. El cifrado y la protección responden a preguntas diferentes y se complementan limpiamente. El cifrado decide quién puede abrir el archivo; la protección decide qué puede cambiar un lector que ya está dentro. Una entrega de nóminas puede razonablemente hacer ambas cosas: cifrar el paquete para que solo lo vea el poseedor de la contraseña, y luego bloquear las celdas de fórmula para que el destinatario pueda filtrar y ordenar pero no reescribir silenciosamente los cálculos. El error nunca es añadir protección. El error es permitir que su presencia sustituya al cifrado cuando el requisito era la confidencialidad
El lado de la custodia no tiene red de seguridad, y eso es por diseño. La derivación de claves de 50,000 iteraciones existe para hacer que adivinar sea costoso, y nada dentro del archivo deposita el secreto. Una contraseña perdida son datos perdidos. Genere, entregue y almacene estas contraseñas con la misma disciplina que aplica a las credenciales de la base de datos, y el cifrado cumplirá su parte
El cifrado de archivos real es una sola llamada en HotXLS. La disciplina reside en todo lo que rodea a la llamada: custodia de contraseñas, el límite de solo escritura que impide que HotXLS vuelva a abrir su propia salida y una declaración de algoritmo que pueda defender en una auditoría. SaveAsEncrypted y el viaje de ida y vuelta heredado se distribuyen con el HotXLS Component, ejecutándose de forma nativa en procesos Delphi y C++Builder sin automatización de Excel en ninguna parte del trayecto