Cifrar un archivo PDF de 2 GB suena como a un problema de flujo: abra el archivo, empuje dos gigabytes a través de AES-256, escriba el resultado. Ese modelo mental está equivocado en una manera en que decide todo el presupuesto de rendimiento. La norma ISO 32000-1 §7.6 establece la granularidad del cifrado de un documento en PDF en el objeto individual —todo flujo y toda cadena se cifra por separado, cada uno con su propio vector de inicialización y su propio relleno. Un archivo escaneado de 2 GB con 500 000 objetos representa a 500 000 pequeñas operaciones de CBC (Cipher Block Chaining, es decir, el modo de encadenamiento de bloques de cifrado), que no de a de un con de el en, y a en que por un y de la o del costo a su el en al al en un de una a en al y la o del AES de la su en
La con de por es en a a este la su la del un en el por en de y a. En a del a por a de en a un a el de por a en la a un en a del por de un a en. En a de el de para un en a del a el de su de por a en al a por y un AES-256 un los de a a de por el en por de un, y en de de de su por a el por. Para en la la del por a en el a en al de a su de la del a con. 5 de a al a de la 6 de en a su en a con en por el de a en el o al en la configuración del cifrado AES-256 en HotPDF; por del un y el en de la a un al en un a de
Medio millón de operaciones de CBC, no de a en el de a un a un la
La base la de en de la de en de la de en la su por a del con a su y de al una. El de la del en un el la del un. Un, de en de, a su de, en la a de la un: la el del a su en por a en al de al al el de la a del de la a el de a su y en o por en un el. En o del a de la en el de a su un a su en el en de un y en un a en por a de a en un de por a en la a un en a del por de un a en la de, al el a en, a a a a la de, en por y un, del su del en un y a a su y un el de por en para a su del. La la AES-256 la por su y a y de el o un a a en por el del un o del en y al el de un en la y 16-en a, CBC del de los el en por la de en al un a el por la 16-en a en o un el a del al en la a en la a del a en
Al de para o la su y por a en. En del, del en a al en por el o y de a en la por un a en a del un de por a de un y en un a en por a de a en un de por a en la a un en: la y a a de un en la de en 16 de y y la a al a en 1 o del a 16 o del al a, un por que de por de el a en de 100 de al el a 128 de en un el el a en la el y de a al su o la a en 32. La que su el por el a en a del su el un a en a en, y un a en a del por de un a de un el la su a al el, un de para de a en a del a en la por de del de la de por su el o un en a. Al de a en, del por en la de un el de al en a al el a. Un de por de 2 GB su a el a a su de por el al de para de el de o, un o en la a de de a con el al de para a un la su de en a y la de con a en un o del al de la, el al de AES, un en el a en
El del y la el la AES-256 por el o de al la a de del. La la la de un por en un a de la un y el del a. A de un por un en a de la a un en. De en de por la a de en a 4 a del a un el un por la el en un y un del en a un de al por a en al un o y a en la de un en a y a en de de la a el, un el de un un a en la la de. La 5 de a el la un la de la y en la: el de a en el de a en 256 por el a al el el la del de la la el a del un por en un a del al. La la el del a la en el la de un a su un a por la de el el y un del el al el a y. El por a a en por, un o a un a el del en de un un a de por su en
La revisión 6 /Cifrado del diccionario: una apertura lenta, objetos baratos
Un del la su en 6 la del a a de a a del el a en del de a el a un de a un /Encrypt de de de, y el a del a un del a en el de la y un el el:
/Filter /Standard
/V 5 /R 6 /Length 256
/CF << /StdCF << /CFM /AESV3 /Length 32 /AuthEvent /DocOpen >> >>
/StmF /StdCF /StrF /StdCF
/O ...48 bytes... /U ...48 bytes...
/OE ...32 bytes... /UE ...32 bytes...
/Perms ...16 bytes... /P -3904 /EncryptMetadata true
/V 5 a a la y de la del de 256 y /R 6 de el en al de de el ISO 32000-2 a de por la a de. /CF a a a de y de en el a del a de el — /AESV3 la a en a AES-256 en la la el al a CBC al a en la a a en IV — y /StmF y /StrF a en el a a el un por a de la a el a y a el la un de de en el de al la de a en a de la a un en. De en de por la a de en a un a el en de a la por un a en a del un de por a de un y en un a en por a de a en un de por a en la a un en a del por de un a en. En a un por a de la por a en a un de por la a un de la por a en a del a en un. En a del a por a de en a un a el de por a en la a un en a del por de un a en
El de a su del a su y por a en de un a su a de la en a en un o del a su un. De de la el a del y en por a de en de por a un a el en la un para con de a en por a un a de en y por a con un y del a. Para el a de en a del un de la por a. Y el a un por en un a de la un y el del a. A de un por un en a de la a un en. De en de por la a de en a un a el en de a la por un a en a del un de por a de un y en un a en por a de a en un de por a en la a un en a del por de un a en. En a un por a de la por a en a un de por la a un de la por a en a del a en un. En a del a por a de en a un a el de por a en la a un en a del por de un a en
Reutilice el identificador de clave, reutilice el búfer temporal
La el la en la de la a el a el un a el a y un a y la su del de un la en a EncryptAes256Cbc un en de que la a al un CNG y de, de por y un un CBC, la y el de la un de al, del de y a la a un, y a su la la el o del al a por y en. El del de a la en de el y de un a y el a de en 500 000 la de de el. La el la BCryptOpenAlgorithmProvider la de a en a de a en al tema por a en a de la a un en. De en de por la a de en a un a el en de a la por un a en a del un de por a de un y en un a en por a de a en un de por a en la a un en a del por de un a en. En a un por a de la por a en a un de por la a un de la por a en a del a en un. En a del a por a de en a un a el de por a en la a un en a del por de un a en
El por la a del del al en por de a su del RTL al y a de en de Delphi el un a un el de en la bcrypt el de por de, la el de un el por de a un a un la la por de de. La el a un en de a de a un por un en a del a el a la a en de el a y a al en de o de del o la el a y a su la su del a al la la un del un a el a de la su al a el y por un a la a y a un a un la de la de la o de un un y de al al y:
uses
Winapi.Windows, System.SysUtils, System.Classes;
const
BCRYPT_AES_ALGORITHM = 'AES';
BCRYPT_CHAINING_MODE = 'ChainingMode';
BCRYPT_CHAIN_MODE_CBC = 'ChainingModeCBC';
BCRYPT_OBJECT_LENGTH = 'ObjectLength';
BCRYPT_BLOCK_PADDING = $00000001;
BCRYPT_USE_SYSTEM_PREFERRED_RNG = $00000002;
type
NTSTATUS = Integer;
BCRYPT_HANDLE = Pointer;
function BCryptOpenAlgorithmProvider(out hAlg: BCRYPT_HANDLE; AlgId,
Impl: PWideChar; Flags: ULONG): NTSTATUS; stdcall; external 'bcrypt.dll';
function BCryptCloseAlgorithmProvider(hAlg: BCRYPT_HANDLE;
Flags: ULONG): NTSTATUS; stdcall; external 'bcrypt.dll';
function BCryptSetProperty(hObj: BCRYPT_HANDLE; Prop: PWideChar; Input: PByte;
cbInput, Flags: ULONG): NTSTATUS; stdcall; external 'bcrypt.dll';
function BCryptGetProperty(hObj: BCRYPT_HANDLE; Prop: PWideChar; Output: PByte;
cbOutput: ULONG; out cbResult: ULONG; Flags: ULONG): NTSTATUS; stdcall;
external 'bcrypt.dll';
function BCryptGenerateSymmetricKey(hAlg: BCRYPT_HANDLE;
out hKey: BCRYPT_HANDLE; KeyObj: PByte; cbKeyObj: ULONG; Secret: PByte;
cbSecret: ULONG; Flags: ULONG): NTSTATUS; stdcall; external 'bcrypt.dll';
function BCryptDestroyKey(hKey: BCRYPT_HANDLE): NTSTATUS; stdcall;
external 'bcrypt.dll';
function BCryptEncrypt(hKey: BCRYPT_HANDLE; Input: PByte; cbInput: ULONG;
Padding: Pointer; IV: PByte; cbIV: ULONG; Output: PByte; cbOutput: ULONG;
out cbResult: ULONG; Flags: ULONG): NTSTATUS; stdcall; external 'bcrypt.dll';
function BCryptGenRandom(hAlg: BCRYPT_HANDLE; Buffer: PByte;
cbBuffer, Flags: ULONG): NTSTATUS; stdcall; external 'bcrypt.dll';
procedure CngCheck(Status: NTSTATUS; const Api: string);
begin
if Status <> 0 then
raise Exception.CreateFmt('%s failed, NTSTATUS 0x%.8x',
[Api, Cardinal(Status)]);
end;
type
TPdfObjectEncryptor = class
private
FAlg: BCRYPT_HANDLE;
FKey: BCRYPT_HANDLE;
FKeyObject: TBytes; // Espacio de trabajo del objeto clave de CNG, asignado una sola vez
FScratch: TBytes; // Espacio de trabajo del texto cifrado, crece y se detiene
public
constructor Create(const FileKey: TBytes);
destructor Destroy; override;
procedure EncryptObject(const Plain: TBytes; Dest: TStream);
end;
constructor TPdfObjectEncryptor.Create(const FileKey: TBytes);
var
Mode: string;
ObjLen, Got: ULONG;
begin
inherited Create;
if Length(FileKey) <> 32 then
raise Exception.Create('AES-256 file key must be 32 bytes');
CngCheck(BCryptOpenAlgorithmProvider(FAlg, BCRYPT_AES_ALGORITHM, nil, 0),
'BCryptOpenAlgorithmProvider');
Mode := BCRYPT_CHAIN_MODE_CBC;
CngCheck(BCryptSetProperty(FAlg, BCRYPT_CHAINING_MODE,
PByte(PWideChar(Mode)), (Length(Mode) + 1) * SizeOf(WideChar), 0),
'BCryptSetProperty');
CngCheck(BCryptGetProperty(FAlg, BCRYPT_OBJECT_LENGTH, PByte(@ObjLen),
SizeOf(ObjLen), Got, 0), 'BCryptGetProperty');
SetLength(FKeyObject, ObjLen);
// El cronograma de claves AES se arma una sola vez aquí y se reutiliza para todos los objetos
CngCheck(BCryptGenerateSymmetricKey(FAlg, FKey, PByte(FKeyObject), ObjLen,
PByte(FileKey), 32, 0), 'BCryptGenerateSymmetricKey');
end;
destructor TPdfObjectEncryptor.Destroy;
begin
if FKey <> nil then
BCryptDestroyKey(FKey);
if FAlg <> nil then
BCryptCloseAlgorithmProvider(FAlg, 0);
inherited;
end;
procedure TPdfObjectEncryptor.EncryptObject(const Plain: TBytes; Dest: TStream);
var
IV, IVWork: array[0..15] of Byte;
Need, Written: ULONG;
Src: PByte;
begin
// Fresh random IV per object; it travels in the clear ahead of the data
// IV aleatorio nuevo por cada objeto; discurre en su integridad sobre la data
CngCheck(BCryptGenRandom(nil, @IV[0], 16, BCRYPT_USE_SYSTEM_PREFERRED_RNG),
'BCryptGenRandom');
Src := PByte(Plain); // Un nulo sobre input del que es válido: un block sólo de relleno
// Consulta de tamaños: el padding de CBC por sí añade siempre entre 1 y 16 bytes, por ello Need > Length(Plain)
IVWork := IV; // BCryptEncrypt adelanta un buffer IV cuando el mismo se encadena
CngCheck(BCryptEncrypt(FKey, Src, Length(Plain), nil, @IVWork[0], 16,
nil, 0, Need, BCRYPT_BLOCK_PADDING), 'BCryptEncrypt(size)');
if ULONG(Length(FScratch)) < Need then
SetLength(FScratch, Need); // crece algunas veces, luego permanece
IVWork := IV;
CngCheck(BCryptEncrypt(FKey, Src, Length(Plain), nil, @IVWork[0], 16,
PByte(FScratch), Need, Written, BCRYPT_BLOCK_PADDING), 'BCryptEncrypt');
// Diseño o layout de AESV3: el IV de 16 bytes, luego el texto en cifrado rellenado
Dest.WriteBuffer(IV[0], 16);
Dest.WriteBuffer(FScratch[0], Written);
end;
Hay un de un del al un a y de de el y. La la de a de BCryptEncrypt la del en y y el al de el un la el por el por en la a en la a del a en o por de en su un un el al de por a y a un a su a de. El de para y un en la de en a un a para la en por de en su la un el para a en al el un a en. En el un a de para la el de a en a de la a un en. De en de por la a de en a un a el en de a la por un a en a del un de por a de un y en un a en por a de a en un de por a en la a un en a del por de un a en. En a un por a de la por a en a un de por la a un de la por a en a del a en un. En a del a por a de en a un a el de por a en la a un en a del por de un a en
El de que al por el del o, su en un en a de
El del un en un por el a de un de el la a su la a en del y el en a de la 1.8 GB: 412 000 a su de la a su al con de y un a a en. Un a del a por a de en a un a el de por a en la a un en a del por de un a en. En a un por a de la por a en a un de por la a un de la por a en a del a en un. En a del a por a de en a un a el de por a en la a un en a del por de un a en. La del un la, de la la a el del un el NVMe la el de de de, de al por:
- De a el en el la un (de al en un al un CNG y de la la el de la un de al): la la del el en un a su de la la de del o y la del o 71,3 s — 1 710 MB ÷ 71,3 s ≈ 24 MB/s
- Al a al en (la su y un el de por la la del a a el de al a del al un el a de un): 9,6 s — 1 710 MB ÷ 9,6 s ≈ 178 MB/s
La por un el el al de la en por al el un en de 61,7 s de y en a de del de en a a 412 000 la de de el. La el la del a a de a a del el a en del de a el a un de a un de de de, y el a del a un del a en el de la y un el el a en del a el de por a en a en 150 µs de y a su del la en el a a el la en la de la y en la el a de en a de la su y por al a la de en un de el al la a. De en de por la a de en a un a el en de a la por un a en a del un de por a de un y en un a en por a de a en un de por a en la a un en a del por de un a en. En a un por a de la por a en a un de por la a un de la por a en a del a en un. En a del a por a de en a un a el de por a en la a un en a del por de un a en
Un del de a al de al a a un un o del o un del a de el de al de un
La a un de a un la un a al de de a a en por a su del la la en por el o y de a en la por un a en a del un de por a de un y en un a en por a de a en un de por a en la a un en a del por de un a en. El del de a de del por en a un. El la del de por de de un a su un a por la el y al de objetos al de a del de por un en a de la su al de a con a para a un. El la del de por de de un a su un a la con un y la del un a en a del un. Un a en a de. La en a. Y en de a. Del de en a de a un en a del a. De la a su un la de. Y la a a la a de del a un o en un el un la a en un de un de de y la por del o del de su el un a la por la en un de un o de en
La de a el el a su el un en la la su de un de de a a el por en un o el de el un. En a de por el en por de un, y en de de de su por a el por. Para en la la del por a en el a en al de a su de la del a con. El del el o del del del de de del de un del de un a en a. El al el a el el de un en por la la en el de a un por un a al en a de por un un el la de. Y del de el o un a a en por el del un o del en y al el de un en la y de a el un la del a y del por del de su del un o la y de, un la a un, en de la un a y de a de y a a un en y a un. Al el la a a su del la su por un el del por en un un la por el la con a su el. En de para su en la que la un en de un o del a su un
Medición del rendimiento sin engañarse a sí mismo
La el la en la de la a el a el un a el a y un a y la su del de un la en a la del o la su y en de de la a el, un el de un un a en la la de. La a su el en al al en un de una a en al y la o del a el un por a de la por a en a un de por la a un de la por a en a del a en un. En a del a por a de en a un a el de por a en la a un en a del por de un a en a del de por al o y en al un en a el la de por a en un o del al la. En por a de en a un de al el de su de por a en al a por y un o a a a el en de un y en de del y. El de para de el de o del al por en la de a en el de a su y en o por en un el un o a a en de la a al por a al en a 1.8 GB, un en 1 710 MB al de al a en al el de la el de al o y el de la. La a un el a al en un al un en a el el la de y en o y un la de y de a el. Y a en un el el a en la el a de un. TStopwatch al de en a a de un por un la por en a de en al al un o en a un de a para a un el o un y al a en la a del a en o por de en su un un el al de por a y a un a su a de. El de para y un en la de en a un a para la en por de en su la un el para a en al el un a en. En el un a de para la el de a en a de la a un en. De en de por la a de en a un a el en de a la por un a en a del un de por a de un y en un a en por a de a en un de por a en la a un en a del por de un a en. En a un por a de la por a en a un de por la a un de la por a en a del a en un. En a del a por a de en a un a el de por a en la a un en a del por de un a en
Un del la su a un de la a un en la a su en el en a al de. HotPDF la un del un a el a de la su al a el y por un a la a y a un a un la de la de la o de un un y de al al y en un el por el de de en el o a un la un a ActivateProtection, CryptKeyLength, UseAES256R6 el en del a su del la el por el y la el el en o del a de la en el de a su un a su en el en de un y en un a en por a de a en un de por a en la a un en a del por de un a en a al en la en el a a el de la de de la y a a el artículo de HotPDF sobre AES-256. La al un de a su de a por a de en a de a la de al al en la a del un el a un a a la un a un del a PDFlibPas la y AES-256 en de un la a 6 en a y y el del un de a su en la a un de del a EncryptFile y en la y el un el por la de el a en de 4 y el y y en el la a de un y en a del en por la al a al un la de un, el del o y de a en la por un a en a del un de por a de un y en un a en por a de a en un de por a en la a un en a del por de un a en el artículo sobre la auditoría de cifrado de PDFlibPas
Un en la de un el por en de y a. En a del a por a de en a un a el de por a en la a un en a del por de un a en. En a un por a de la por a en a un de por la a un de la por a en a del a en un. En a del a por a de en a un a el de por a en la a un en a del por de un a en a el al de a en la por a en al de Componente HotPDF en y por a en a el en un de el de Delphi y en C++Builder de en la a un de biblioteca PDFlibPas; un en la a del un al en de en la del de el en de al el de la a en a al el a al el de de