SynCrypto is a open source library for data encryption included in this pack.
In this unit (SynCrypto.pas) is the following comment at the begining of file:
AES128 cypher 84 MB/s uncypher 81 MB/s asm version
AES128 cypher 57 MB/s uncypher 57 MB/s pascal version
AES192 cypher 72 MB/s uncypher 70 MB/s asm version
AES192 cypher 48 MB/s uncypher 48 MB/s pascal version
AES256 cypher 62 MB/s uncypher 61 MB/s asm version
AES256 cypher 42 MB/s uncypher 42 MB/s pascal version
From this I understand that are two versions of code: pascal-slower and asm-faster. But the problem is, how can I select between these two ?
Edit: And a secondary question, if you allow me: how cand I select the bitwidth of the key: 128, 192 and 256 ?
I use this code to encrypt and decrypt:
outp := TAESCFB.SimpleEncrypt(inp,'privatekey',true,true);
inp := TAESCFB.SimpleEncrypt(outp,'privatekey',false,true);
... and Delphi 2009.
Short answer: the fastest code will always be used for you, depending on the compiler and computer.
Long answer:
There is only a single code version compiled at a time, either pascal or optimized asm. It depends on conditional defines when running in the unit, set automatically depending on your compiler version (from Delphi 5 up to latest Delphi or FPC revision), and CPU platform (if it has Intel or ARM). Then at runtime, on Intel, AES-NI hardware opcodes can be detected and used, or, on VIA, Padlock hardware opcodes. Even the pascal implementation may be rolled or unrolled.
{$define AES_ROLLED}
// if defined, use rolled version, which is faster (at least on my AMD CPU)
{$ifdef DELPHI5OROLDER}
{$define AES_PASCAL} // Delphi 5 internal asm is buggy :(
{$define SHA3_PASCAL}
{$else}
{$ifdef CPUINTEL} // AES-NI supported for x86 and x64
{$ifdef CPU64}
{$ifdef HASAESNI}
{$define USEAESNI}
{$define USEAESNI64}
{$else}
{$define AES_PASCAL} // Delphi XE2/XE3 do not have the AES-NI opcodes :(
{$endif}
{$define AESPASCAL_OR_CPU64}
{$else}
{$define USEAESNI}
{$define USEAESNI32}
{$endif}
{$else}
{$define AES_PASCAL} // AES128 unrolled pascal(Delphi7)=57MB/s rolled asm=84MB/s :)
{$define SHA3_PASCAL}
{$endif CPUINTEL}
{$endif}
To sumup, when working with AES, the unit has six diverse versions of the algorithm: pascal rolled, pascal unrolled, x86/x64 asm without AES-NI, x86/x64 asm with AES-NI, x86 with padlock, Windows API.
SimpleEncrypt:
There are two overloaded SimpleEncrypt
methods. One with fixed size of 256 bits (the one you used), another with a KeySize
parameter (either 128, 192 or 256):
class function TAESAbstract.SimpleEncrypt(const Input: RawByteString; const Key;
KeySize: integer; Encrypt, IVAtBeginning: boolean): RawByteString;
Of course, you should first hash the input password text into a THash128 or THash256 secret key, before calling the function. We recommend using PBKDF2_HMAC_SHA256
for this purpose (with a high round number).
Some numbers:
With a modern CPU, including AES-NI, you will have tremendous performance. This is the fastest native AES implementation in Delphi/FPC, for sure (no other uses AES-NI). Some numbers run my laptop, taken from TTestCryptographicRoutines.Benchmark
regression tests:
50000 AES128CFB in 229.60ms i.e. 217764/s or 463.4 MB/s
50000 AES128OFB in 183.66ms i.e. 272237/s or 579.3 MB/s
50000 AES128CFBCRC in 227.61ms i.e. 219674/s or 467.5 MB/s
50000 AES128OFBCRC in 181.18ms i.e. 275954/s or 587.2 MB/s
50000 AES256CFB in 288.57ms i.e. 173265/s or 368.7 MB/s
50000 AES256OFB in 243.96ms i.e. 204944/s or 436.1 MB/s
50000 AES256CFBCRC in 294.38ms i.e. 169844/s or 361.4 MB/s
50000 AES256OFBCRC in 244.49ms i.e. 204507/s or 435.2 MB/s
50000 SHAKE128 in 473.34ms i.e. 105631/s or 224.8 MB/s
50000 SHAKE256 in 596.74ms i.e. 83787/s or 178.3 MB/s
Forget about the Windows API, which are dead slow in comparison. The TAES...CRC
class adds a 128-bit crc32c to the input and output during compression with no speed penalty, to authentication and validate the content. I also included SHAKE128/SHAKE256 encryption (not AES compatible), which is comparable to HMAC-SHA-256 + AES-256 in a single step, and is very fast on all CPUs without AES-NI.