logo.png
mORMot2 API Reference

mormot.crypt.core.pas unit

Purpose: Framework Core Cryptographic Process (Hashing and Cypher)
- this unit is a part of the Open Source Synopse mORMot framework 2, licensed under a MPL/GPL/LGPL three license - see LICENSE.md

1.1. Units used in the mormot.crypt.core unit

Unit NameDescription
mormot.core.baseFramework Core Shared Types and RTL-like Functions
mormot.core.osFramework Core Low-Level Wrappers to the Operating-System API
mormot.core.rttiFramework Core Low-Level Cross-Compiler RTTI Definitions
mormot.core.textFramework Core Low-Level Text Processing
mormot.core.unicodeFramework Core Low-Level Unicode UTF-8 UTF-16 Ansi Conversion

1.2. mormot.crypt.core class hierarchy

TAesPkcs7AbstractTAesPkcs7WriterTAesPkcs7ReaderTStreamWithPositionAndSizeTStreamTAesWriteStreamTAesPrngAbstractTSystemPrngTAesPrngTAesLockedTObjectOSLightLockTObjectTSha512_256TSha512TSha384512TSha384TSha3TSha256TSha1TRC4TMd5THmacSha512THmacSha384THmacSha256THmacSha1THmacCrc32cTAesGcmEngineTAesFullHeaderTAesFullTAesAbstractTAesTAesGcmAbstractTAesGcmTAesAbstractSynTAesAbstractApiTAesEcbTAesCbcTAesAbstractEncryptOnlyTAesOfbTAesCfbTAesC64TAesAbstractAeadTAesCtrTAesSymCrcTAesOfcTAesCtcTAesCfcTAesOfbApiTAesEcbApiTAesCfbApiTAesCbcApiESynExceptionESynCrypto
mormot.crypt.core class hierarchy

1.3. Objects implemented in the mormot.crypt.core unit

ObjectsDescription
ESynCryptoClass of Exceptions raised by this unit
TAesHandle AES cypher/uncypher
TAesAbstractHandle AES cypher/uncypher with chaining
TAesAbstractAeadAEAD (authenticated-encryption with associated-data) abstract class
TAesAbstractApiHandle AES cypher/uncypher using Windows CryptoApi and the official Microsoft AES Cryptographic Provider (PROV_RSA_AES)
TAesAbstractEncryptOnlyAbstract parent class for chaining modes using only AES encryption
TAesAbstractSynHandle AES cypher/uncypher with chaining with our own optimized code
TAesC64Handle AES cypher/uncypher with non-standard 64-bit Counter mode (CTR)
TAesCbcHandle AES cypher/uncypher with Cipher-block chaining (CBC)
TAesCbcApiHandle AES cypher/uncypher Cipher-block chaining (CBC) using Windows CryptoApi
TAesCfbHandle AES cypher/uncypher with Cipher feedback (CFB)
TAesCfbApiHandle AES cypher/uncypher Cipher feedback (CFB) using Windows CryptoApi
TAesCfcAEAD combination of AES with Cipher feedback (CFB) and 256-bit crc32c MAC
TAesCtcAEAD combination of AES with Counter (CTR) and 256-bit crc32c MAC
TAesCtrHandle AES cypher/uncypher with 128-bit Counter mode (CTR)
TAesEcbHandle AES cypher/uncypher without chaining (ECB)
TAesEcbApiHandle AES cypher/uncypher without chaining (ECB) using Windows CryptoApi
TAesFullAES and XOR encryption object for easy direct memory or stream access
TAesFullHeaderInternal header for storing our AES data with salt and CRC
TAesGcmHandle AES-GCM cypher/uncypher using our TAesGcmEngine
TAesGcmAbstractAbstract parent to handle AES-GCM cypher/uncypher with built-in authentication
TAesGcmEngineLow-level AES-GCM processing
TAesLockedThread-safe class containing a TAes encryption/decryption engine
TAesMac256Internal 256-bit structure used for TAesAbstractAead MAC storage
TAesOfbHandle AES cypher/uncypher with Output feedback (OFB)
TAesOfbApiHandle AES cypher/uncypher Output feedback (OFB) using Windows CryptoApi
TAesOfcAEAD combination of AES with Output feedback (OFB) and 256-bit crc32c MAC
TAesPkcs7AbstractAbstract parent class to TAesPkcs7Writer and TAesPkcs7Reader
TAesPkcs7ReaderMulti-mode PKCS7 buffered AES decryption stream
TAesPkcs7WriterMulti-mode PKCS7 buffered AES encryption stream
TAesPrngCryptographic pseudorandom number generator (CSPRNG) based on AES-256
TAesPrngAbstractAbstract parent for TAesPrng* classes
TAesSymCrcAEAD combination of AES and 256-bit MAC with symmetrical Encrypt/Decrypt
TAesWriteStreamAES encryption stream (deprecated)
THmacCrc32cCompute the HMAC message authentication code using crc32c as hash function
THmacSha1Compute the HMAC message authentication code using SHA-1 as hash function
THmacSha256Compute the HMAC message authentication code using SHA-256 as hash function
THmacSha384Compute the HMAC message authentication code using SHA-384 as hash function
THmacSha512Compute the HMAC message authentication code using SHA-512 as hash function
TMacAndCryptDataHeader layout used for TAesAbstract.MacAndCrypt format
TMd5Implements MD5 hashing - and could also implement MD4 if really needed
TRC4Implements RC4 encryption/decryption
TSha1Implements SHA-1 hashing
TSha256Implements SHA-256 hashing
TSha3Implements SHA-3 (Keccak) hashing
TSha384Implements SHA-384 hashing
TSha384512Abstract parent for implementing SHA-384, SHA-512/256 and SHA-512 hashing
TSha512Implements SHA-512 hashing
TSha512_256Implements SHA-512/256 hashing
TSystemPrngTAesPrng-compatible class using Operating System pseudorandom source

1.3.1. ESynCrypto

ESynCrypto = class(ESynException)

Class of Exceptions raised by this unit


1.3.2. TAes

TAes = object(TObject)

Handle AES cypher/uncypher
- this is the default Electronic codebook (ECB) mode
- this class will use AES-NI hardware instructions, if available
- we defined a record instead of a class, to allow stack allocation and thread-safe reuse of one initialized instance


function DecryptInit(const Key; KeySize: cardinal): boolean;

Initialize AES contexts for uncypher
- first method to call before using this object for decryption
- KeySize is in bits, i.e. 128, 192 or 256


function DecryptInitFrom(const Encryption: TAes; const Key; KeySize: cardinal): boolean;

Initialize AES contexts for uncypher, from another TAes.EncryptInit


function DoInit(const Key; KeySize: cardinal; doEncrypt: boolean): boolean;

Generic initialization method for AES contexts
- call either EncryptInit() either DecryptInit() method


function EncryptInit(const Key; KeySize: cardinal): boolean;

Initialize AES contexts for cypher
- first method to call before using this object for encryption
- KeySize is in bits, i.e. 128, 192 or 256


function Initialized: boolean;

TRUE if the context was initialized via EncryptInit/DecryptInit


function KeyBits: integer;

Returns the key size in bits (128/192/256)


function UsesAesni: boolean;

Return TRUE if the AES-NI instruction sets are available on this CPU


procedure Decrypt(var B: TAesBlock); overload;

Decrypt an AES data block


procedure Decrypt(const BI: TAesBlock; var BO: TAesBlock); overload;

Decrypt an AES data block into another data block


procedure DoBlocks(pIn, pOut: PAesBlock; Count: integer; doEncrypt: boolean); overload;

Perform the AES cypher or uncypher to continuous memory blocks
- call either Encrypt() either Decrypt() method


procedure DoBlocks(pIn, pOut: PAesBlock; out oIn, oOut: PAesBLock; Count: integer; doEncrypt: boolean); overload;

Perform the AES cypher or uncypher to continuous memory blocks
- call either Encrypt() either Decrypt() method


procedure DoBlocksCtr(iv: PAesBlock; src, dst: pointer; blockcount: PtrUInt);

Performs AES-CTR NIST encryption and decryption on whole blocks
- may be called instead of TAesCtr when only a raw TAes is available
- as used e.g. by mormot.db.raw.sqlite3.static.pas for its DB encryption
- this method is thread-safe, and is optimized for AES-NI on x86_64


procedure DoBlocksOfb(iv: PAesBlock; src, dst: pointer; blockcount: PtrUInt);

Performs AES-OFB encryption and decryption on whole blocks
- may be called instead of TAesOfb when only a raw TAes is available
- as used e.g. by mormot.db.raw.sqlite3.static.pas for its DB encryption
- this method is thread-safe, and is optimized for AES-NI on x86_64


procedure Done;

Finalize AES contexts for both cypher and uncypher
- would fill the TAes instance with zeros, for (paranoid) safety


procedure Encrypt(const BI: TAesBlock; var BO: TAesBlock); overload;

Encrypt an AES data block into another data block


procedure Encrypt(var B: TAesBlock); overload;

Encrypt an AES data block


1.3.3. TAesGcmEngine

TAesGcmEngine = object(TObject)

Low-level AES-GCM processing
- implements standard AEAD (authenticated-encryption with associated-data) algorithm, as defined by NIST Special Publication 800-38D
- will use AES-NI and CLMUL Intel/AMD opcodes if available on x86_64/i386


function Add_AAD(pAAD: pointer; aLen: PtrInt): boolean;

Append some data to be authenticated, but not encrypted


function Decrypt(ctp, ptp: pointer; ILen: PtrInt; ptag: pointer = nil; tlen: PtrInt = 0): boolean;

Decrypt a buffer with AES-GCM, updating the associated authentication data
- also validate the GMAC with the supplied ptag/tlen if ptag<>nil, and skip the AES-CTR phase if the authentication doesn't match


function Encrypt(ptp, ctp: pointer; ILen: PtrInt): boolean;

Encrypt a buffer with AES-GCM, updating the associated authentication data


function Final(out tag: TAesBlock; andDone: boolean = true): boolean;

Finalize the AES-GCM encryption, returning the authentication tag
- will also flush the AES context to avoid forensic issues, unless andDone is forced to false


function FullDecryptAndVerify(const Key; KeyBits: PtrInt; pIV: pointer; IV_len: PtrInt; pAAD: pointer; aLen: PtrInt; ctp, ptp: pointer; pLen: PtrInt; ptag: pointer; tLen: PtrInt): boolean;

Single call AES-GCM decryption and verification process


function FullEncryptAndAuthenticate(const Key; KeyBits: PtrInt; pIV: pointer; IV_len: PtrInt; pAAD: pointer; aLen: PtrInt; ptp, ctp: pointer; pLen: PtrInt; out tag: TAesBlock): boolean;

Single call AES-GCM encryption and authentication process


function Init(const Key; KeyBits: PtrInt): boolean;

Initialize the AES-GCM structure for the supplied Key


function Reset(pIV: pointer; IV_len: PtrInt): boolean;

Start AES-GCM encryption with a given Initialization Vector
- IV_len is in bytes use 12 for exact IV setting, otherwise the supplied buffer will be hashed using gf_mul_h()


procedure Done;

Flush the AES context to avoid forensic issues
- do nothing if Final() has been already called


1.3.4. TAesAbstract

TAesAbstract = class(TObject)

Handle AES cypher/uncypher with chaining
- use any of the inherited implementation, corresponding to the chaining mode required - TAesEcb, TAesCbc, TAesCfb, TAesOfb and TAesCtr classes to handle in ECB, CBC, CFB, OFB and CTR mode (including PKCS7-like padding)


constructor Create(const aKey: THash256); reintroduce; overload;

Initialize AES context for AES-256 cypher
- first method to call before using this class
- just a wrapper around Create(aKey,256);


constructor Create(const aKey: TBytes); reintroduce; overload;

Initialize AES context for AES-256 cypher
- first method to call before using this class
- here, aKey is expected to be a 128-bit, 192-bit or 256-bit TBytes, i.e. with 16, 24 or 32 bytes


constructor Create(const aKey; aKeySizeBits: cardinal); reintroduce; overload; virtual;

Initialize AES context for cypher
- first method to call before using this class
- KeySize is in bits, i.e. either 128, 192 or 256
- warning: aKey is an untyped constant, i.e. expects a raw set of memory bytes: do NOT use assign it with a string or a TBytes instance: you would use the pointer to the data as key - either digest the string via CreateFromPbkdf2 or use Create(TBytes)


constructor Create(const aKey: THash128); reintroduce; overload;

Initialize AES context for AES-128 cypher
- first method to call before using this class
- just a wrapper around Create(aKey,128);


constructor CreateFromPbkdf2(const aKey: RawUtf8; const aSalt: RawByteString; aRounds: integer);

Initialize AES context for cypher, from Pbkdf2HmacSha256 derivation
- here the Key is supplied as a string, and will be hashed using Pbkdf2HmacSha256 with the specified salt and rounds


constructor CreateFromSha256(const aKey: RawUtf8); deprecated;

Initialize AES context for cypher, from SHA-256 hash
- here the Key is supplied as a string, and will be hashed using SHA-256 via the Sha256Weak proprietary algorithm - to be used only for backward compatibility of existing code
- since Sha256Weak() is deprecated, consider using the more secure (and more standard and proven) CreateFromPbkdf2() constructor


constructor CreateTemp(aKeySize: cardinal);

Initialize AES context for cypher, from some TAesPrng random bytes
- may be used to hide some sensitive information from memory, like CryptDataForCurrentUser but with a temporary key


destructor Destroy; override;

Release the used instance memory and resources
- also fill the secret fKey buffer with zeros, for safety


function AlgoName: TShort15; overload;

OpenSSL-like Cipher name encoding of this AES engine
- return e.g. 'aes-128-cfb' or 'aes-256-gcm'
- our TAesC64, TAesCfc, TAesOfc, TAesCtc custom algorithms use non-standard trailing 'c64', 'cfc', 'ofc' and 'ctc' mode names e.g. as 'aes-256-cfc'


function Clone: TAesAbstract; virtual;

Compute a class instance similar to this one
- could be used to have a thread-safe re-use of a given encryption key


function CloneEncryptDecrypt: TAesAbstract; virtual;

Compute a class instance similar to this one, for performing the reverse encryption/decryption process using the identical key
- this default implementation calls Clone, but CFB/OFB/CTR chaining modes using only AES encryption (i.e. inheriting from TAesAbstractEncryptOnly) will return self to avoid creating two instances


function DecryptPkcs7(const Input: RawByteString; IVAtBeginning: boolean = false; RaiseESynCryptoOnError: boolean = true; TrailerLen: PtrInt = 0): RawByteString; overload;

Decrypt a memory buffer using a PKCS7 padding pattern
- PKCS7 padding is described in RFC 5652 - it will trim up to 16 bytes from the input buffer; note this method uses the padding only, not the whole PKCS#7 Cryptographic Message Syntax
- if IVAtBeginning is TRUE, the Initialization Vector will be taken from the beginning of the input binary buffer
- if RaiseESynCryptoOnError=false, returns '' on any decryption error
- if TrailerLen is <> 0, some last bytes from Input will be ignored


function DecryptPkcs7(const Input: TBytes; IVAtBeginning: boolean = false; RaiseESynCryptoOnError: boolean = true; TrailerLen: PtrInt = 0): TBytes; overload;

Decrypt a memory buffer using a PKCS7 padding pattern
- PKCS7 padding is described in RFC 5652 - it will trim up to 16 bytes from the input buffer; note this method uses the padding only, not the whole PKCS#7 Cryptographic Message Syntax
- if IVAtBeginning is TRUE, the Initialization Vector will be taken from the beginning of the input binary buffer
- if RaiseESynCryptoOnError=false, returns [] on any decryption error


function DecryptPkcs7Buffer(Input: pointer; InputLen: PtrInt; IVAtBeginning: boolean; RaiseESynCryptoOnError: boolean = true): RawByteString;

Decrypt a memory buffer using a PKCS7 padding pattern
- PKCS7 padding is described in RFC 5652 - it will trim up to 16 bytes from the input buffer; note this method uses the padding only, not the whole PKCS#7 Cryptographic Message Syntax
- if IVAtBeginning is TRUE, the Initialization Vector will be taken from the beginning of the input binary buffer
- if RaiseESynCryptoOnError=false, returns '' on any decryption error


function EncryptPkcs7(const Input: TBytes; IVAtBeginning: boolean = false; TrailerLen: PtrInt = 0): TBytes; overload;

Encrypt a memory buffer using a PKCS7 padding pattern
- PKCS7 padding is described in RFC 5652 - it will add up to 16 bytes to the input buffer; note this method uses the padding only, not the whole PKCS#7 Cryptographic Message Syntax
- if IVAtBeginning is TRUE, a random Initialization Vector will be generated by TAesPrng and stored at the beginning of the output buffer


function EncryptPkcs7(const Input: RawByteString; IVAtBeginning: boolean = false; TrailerLen: PtrInt = 0): RawByteString; overload;

Encrypt a memory buffer using a PKCS7 padding pattern
- PKCS7 padding is described in RFC 5652 - it will add up to 16 bytes to the input buffer; note this method uses the padding only, not the whole PKCS#7 Cryptographic Message Syntax
- if IVAtBeginning is TRUE, a random Initialization Vector will be generated by TAesPrng and stored at the beginning of the output buffer
- if TrailerLen is <> 0, some last bytes will be reserved in output buffer


function EncryptPkcs7Buffer(Input, Output: pointer; InputLen, OutputLen: PtrUInt; IVAtBeginning: boolean): boolean;

Encrypt a memory buffer using a PKCS7 padding pattern
- PKCS7 padding is described in RFC 5652 - it will add up to 16 bytes to the input buffer; note this method uses the padding only, not the whole PKCS#7 Cryptographic Message Syntax
- use EncryptPkcs7Length() function to compute the actual needed length
- if IVAtBeginning is TRUE, a random Initialization Vector will be generated by TAesPrng and stored at the beginning of the output buffer
- returns TRUE on success, FALSE if OutputLen is not correct - you should use EncryptPkcs7Length() to compute the exact needed number of bytes


function EncryptPkcs7Length(InputLen: cardinal; IVAtBeginning: boolean): cardinal;

Compute how many bytes would be needed in the output buffer, when encrypte using a PKCS7 padding pattern
- could be used to pre-compute the OutputLength for EncryptPkcs7Buffer()
- PKCS7 padding is described in RFC 5652 - it will add up to 16 bytes to the input buffer; note this method uses the padding only, not the whole PKCS#7 Cryptographic Message Syntax


class function IsAvailable: boolean; virtual;

Quick check if this cipher is available on the system
- this default implementation returns true
- TAesAbstractOsl.IsAvailable returns false if OpenSSL is not installed


function MacAndCrypt(const Data: RawByteString; Encrypt, IVAtBeginning: boolean; const Associated: RawByteString = ''; EndingSize: cardinal = 0): RawByteString;

Perform one step PKCS7 encryption/decryption and authentication with the curent AES instance over a small memory block
- returns '' on any (MAC) issue during decryption (Encrypt=false) or if this class does not support AEAD MAC
- as used e.g. by CryptDataForCurrentUser()
- do not use this abstract class, but TAesGcm/TAesCfc/TAesOfc
- TAesCfc/TAesOfc will store a header with its own CRC, so detection of most invalid formats (e.g. from fuzzing input) will occur before any AES/MAC process - for TAesGcm, authentication requires decryption
- EndingSize can be used if some custom info is stored at the end of Data


function MacCheckError(Encrypted: pointer; Count: cardinal): boolean; virtual;

Validate if an encrypted buffer matches the stored AEAD MAC
- called before the decryption process to ensure the input is not corrupted
- default implementation, for a non AEAD protocol, returns false


function MacDecryptCheckTag(const DecryptMac: THash256): boolean; virtual;

Validates an AEAD (authenticated-encryption with associated-data) MAC
- check if the MAC computed during the last Decryption matches DecryptMac
- default implementation, for a non AEAD protocol, returns false


class function MacEncrypt(const Data: RawByteString; const Key: THash256; Encrypt: boolean; const Associated: RawByteString = ''; IV: PAesBlock = nil): RawByteString; overload;

Perform one step PKCS7 encryption/decryption and authentication from a given 256-bit key over a small memory block
- wrapper which creates a TAesAbsract instance and calls MacAndCrypt()


class function MacEncrypt(const Data: RawByteString; const Key: THash128; Encrypt: boolean; const Associated: RawByteString = ''; IV: PAesBlock = nil): RawByteString; overload;

Perform one step PKCS7 encryption/decryption and authentication from a given 128-bit key over a small memory block
- wrapper which creates a TAesAbstract instance and calls MacAndCrypt()


function MacEncryptGetTag(out EncryptMac: THash256): boolean; virtual;

Returns AEAD (authenticated-encryption with associated-data) MAC
- returns a MAC hash (up to 256-bit), computed during the last Encryption
- may be used e.g. for TAesGcm or our custom TAesOfc/TAesCfbCr modes
- default implementation, for a non AEAD protocol, returns false


function MacSetNonce(DoEncrypt: boolean; const RandomNonce: THash256; const Associated: RawByteString = ''): boolean; virtual;

Initialize AEAD (authenticated-encryption with associated-data) nonce
- i.e. setup 256-bit MAC computation before next Encrypt/Decrypt call
- may be used e.g. for AES-GCM or our custom AES-CTR modes
- default implementation, for a non AEAD protocol, returns false


class function SimpleEncrypt(const Input, Key: RawByteString; Encrypt: boolean; IVAtBeginning: boolean = false; RaiseESynCryptoOnError: boolean = true): RawByteString; overload;

Deprecated wrapper able to cypher/decypher any in-memory content
- deprecated due to wrong IV process - use AesPkcs7() instead
- will use Sha256Weak() and PKCS7 padding with the current class mode, so is to be considered as **really** deprecated


class function SimpleEncrypt(const Input: RawByteString; const Key; KeySize: integer; Encrypt: boolean; IVAtBeginning: boolean = false; RaiseESynCryptoOnError: boolean = true): RawByteString; overload;

Deprecated wrapper able to cypher/decypher any in-memory content
- deprecated due to wrong IV process - use AesPkcs7() instead


class function SimpleEncryptFile(const InputFile, OutputFile: TFileName; const Key: RawByteString; Encrypt: boolean; IVAtBeginning: boolean = false; RaiseESynCryptoOnError: boolean = true): boolean; overload; deprecated;

Deprecated wrapper able to cypher/decypher any file content
- deprecated due to wrong IV process - use AesPkcs7File() instead
- will use Sha256Weak() and PKCS7 padding with the current class mode, so is to be considered as **really** deprecated


class function SimpleEncryptFile(const InputFile, Outputfile: TFileName; const Key; KeySize: integer; Encrypt: boolean; IVAtBeginning: boolean = false; RaiseESynCryptoOnError: boolean = true): boolean; overload;

Deprecated wrapper able to cypher/decypher any file content
- deprecated due to wrong IV process - use AesPkcs7File() instead


procedure AlgoName(out Result: TShort15); overload;

OpenSSL-like Cipher name encoding of this AES engine


procedure Decrypt(BufIn, BufOut: pointer; Count: cardinal); virtual; abstract;

Perform the AES un-cypher in the corresponding mode to Count bytes
- when used in block chaining mode, you should have set the IV property


procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); virtual; abstract;

Perform the AES cypher in the corresponding mode to Count bytes
- when used in block chaining mode, you should have set the IV property


property AlgoMode: TAesMode read fAlgoMode;

The chaining mode of this AES engine


property IV: TAesBlock read fIV write fIV;

Associated Initialization Vector
- all modes (except ECB) do expect an IV to be supplied for chaining, before any encryption or decryption is performed
- you could also use PKCS7 encoding with IVAtBeginning=true option


property IVUpdated: boolean read fIVUpdated;

Low-level flag indicating you can call Encrypt/Decrypt several times
- i.e. the IV and AEAD MAC are updated after each Encrypt/Decrypt call
- is enabled for our internal classes, and also for OpenSSL, but may be disabled for some libraries or APIs (e.g. Windows CryptoApi classes)
- if you call EncryptPkcs7/DecryptPkcs7 you don't have to care about it


property KeySize: cardinal read fKeySize;

Associated Key Size, in bits (i.e. 128,192,256)


1.3.5. TAesAbstractSyn

TAesAbstractSyn = class(TAesAbstract)

Handle AES cypher/uncypher with chaining with our own optimized code
- use any of the inherited implementation, corresponding to the chaining mode required - TAesEcb, TAesCbc, TAesCfb, TAesOfb and TAesCtr classes to handle in ECB, CBC, CFB, OFB and CTR mode (including PKCS7-like padding)
- this class will use AES-NI hardware instructions, if available
- those classes are re-entrant, i.e. that you can call the Encrypt* or Decrypt* methods on the same instance several times


destructor Destroy; override;

Release the used instance memory and resources
- also fill the TAes instance with zeros, for safety


function Clone: TAesAbstract; override;

Creates a new instance with the very same values
- by design, our classes will use TAes stateless context, so this method will just copy the current fields to a new instance, by-passing the key creation step


procedure Decrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES un-cypher in the corresponding mode
- this abstract method will set fIn/fOut from BufIn/BufOut


procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES cypher in the corresponding mode
- this abstract method will set fIn/fOut from BufIn/BufOut


1.3.6. TAesEcb

TAesEcb = class(TAesAbstractSyn)

Handle AES cypher/uncypher without chaining (ECB)
- this mode is known to be less secure than the others
- IV property should be set to a fixed value to encode the trailing bytes of the buffer by a simple XOR - but you should better use the PKC7 pattern
- this class will use AES-NI hardware instructions, if available
- use TAesFast[mEcb] to retrieve the fastest implementation at runtime


procedure Decrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES un-cypher in the ECB mode


procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES cypher in the ECB mode


1.3.7. TAesCbc

TAesCbc = class(TAesAbstractSyn)

Handle AES cypher/uncypher with Cipher-block chaining (CBC)
- this class will use AES-NI hardware instructions, if available
- expect IV to be set before process, or IVAtBeginning=true
- use TAesFast[mCbc] to retrieve the fastest implementation at runtime


function DecryptCts(const Input: RawByteString; IVAtBeginning: boolean = false): RawByteString; overload;

Kerberos AES-CBC-CTS un-cypher in the corresponding mode to a buffer
- follow Kerberos CipherText Stealing (CTS) padding from RFC 3962 (not NIST)
- if IVAtBeginning is TRUE, the Initialization Vector will be taken from the beginning of the input binary buffer
- length(result) is expected to be >= 16 bytes (i.e. at least one block)


function EncryptCts(const Input: RawByteString; IVAtBeginning: boolean = false): RawByteString; overload;

Kerberos AES-CBC-CTS cypher in the corresponding mode to a buffer
- follow Kerberos CipherText Stealing (CTS) padding from RFC 3962 (not NIST)
- if IVAtBeginning is TRUE, a random Initialization Vector will be generated by TAesPrng and stored at the beginning of the output buffer
- length(Input) is expected to be >= 16 bytes (i.e. at least one block)


procedure Decrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES un-cypher in the CBC mode


procedure DecryptCts(BufIn, BufOut: pointer; Count: cardinal); overload;

Kerberos AES-CBC-CTS un-cypher in the corresponding mode to Count bytes
- follow Kerberos CipherText Stealing (CTS) padding from RFC 3962 (not NIST)
- this method is not re-entrant and should be called once with process tail
- Count is expected to be >= 16 bytes (i.e. at least one block)


procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES cypher in the CBC mode


procedure EncryptCts(BufIn, BufOut: pointer; Count: cardinal); overload;

Kerberos AES-CBC-CTS cypher in the corresponding mode to Count bytes
- follow Kerberos CipherText Stealing (CTS) padding from RFC 3962 (not NIST)
- this method is not re-entrant and should be called once with process tail
- Count is expected to be >= 16 bytes (i.e. at least one block)


1.3.8. TAesAbstractEncryptOnly

TAesAbstractEncryptOnly = class(TAesAbstractSyn)

Abstract parent class for chaining modes using only AES encryption


function CloneEncryptDecrypt: TAesAbstract; override;

Compute a class instance similar to this one, for performing the reverse encryption/decryption process
- will return self to avoid creating two instances


1.3.9. TAesCfb

TAesCfb = class(TAesAbstractEncryptOnly)

Handle AES cypher/uncypher with Cipher feedback (CFB)
- this class will use AES-NI hardware instructions, if available
- expect IV to be set before process, or IVAtBeginning=true
- on x86_64, our TAesCfb class is really faster than OpenSSL 1.1:

  mormot aes-128-cfb in 6.95ms i.e. 359247/s or 764.5 MB/s
  mormot aes-256-cfb in 9.40ms i.e. 265816/s or 565.7 MB/s
  openssl aes-128-cfb in 10.53ms i.e. 237326/s or 505 MB/s
  openssl aes-256-cfb in 13.18ms i.e. 189652/s or 403.6 MB/s

- on i386, numbers are similar:

 mormot aes-128-cfb in 7.15ms i.e. 349259/s or 743.3 MB/s
 mormot aes-256-cfb in 9.62ms i.e. 259848/s or 553 MB/s
 openssl aes-128-cfb in 12.01ms i.e. 208142/s or 442.9 MB/s
 openssl aes-256-cfb in 14.49ms i.e. 172449/s or 367 MB/s

- is used e.g. by CryptDataForCurrentUser or WebSockets ProtocolAesClass
- use TAesFast[mCfb] to retrieve the fastest implementation at runtime


procedure Decrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES un-cypher in the CFB mode


procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES cypher in the CFB mode


1.3.10. TAesOfb

TAesOfb = class(TAesAbstractEncryptOnly)

Handle AES cypher/uncypher with Output feedback (OFB)
- this class will use AES-NI hardware instructions, if available
- expect IV to be set before process, or IVAtBeginning=true
- on x86_64, our TAesOfb class is faster than OpenSSL 1.1:

  mormot aes-128-ofb in 6.88ms i.e. 363002/s or 772.5 MB/s
  mormot aes-256-ofb in 9.37ms i.e. 266808/s or 567.8 MB/s
  openssl aes-128-ofb in 7.82ms i.e. 319693/s or 680.3 MB/s
  openssl aes-256-ofb in 10.39ms i.e. 240523/s or 511.8 MB/s

- on i386, numbers are similar:

 mormot aes-128-ofb in 6.92ms i.e. 360906/s or 768 MB/s
 mormot aes-256-ofb in 9.59ms i.e. 260552/s or 554.5 MB/s
 openssl aes-128-ofb in 9.21ms i.e. 271267/s or 577.3 MB/s
 openssl aes-256-ofb in 11.53ms i.e. 216806/s or 461.4 MB/s

- use TAesFast[mOfb] to retrieve the fastest implementation at runtime


procedure Decrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES un-cypher in the OFB mode


procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES cypher in the OFB mode


1.3.11. TAesC64

TAesC64 = class(TAesAbstractEncryptOnly)

Handle AES cypher/uncypher with non-standard 64-bit Counter mode (CTR)
- WARNING: BREAKING CHANGE since mORMot 1.18 in which it was named TAESCTR: use TAesCtr NIST class instead - it is also much faster - or continue to use this TAesC64 class which behaves the same as the old TAESCTR
- the CTR will use a counter in bytes 7..0 - which is not standard, and can be changed via the ComposeIV() methods
- this class will use AES-NI hardware instructions, if available, but does not benefit from the optimized x86_64 of TAesCtr which is much faster
- expect IV to be set before process, or IVAtBeginning=true


function ComposeIV(const Nonce, Counter: TByteDynArray; LSBCounter: boolean): boolean; overload;

Defines how the IV is set and updated in CTR mode
- you can specify startup Nonce and Counter, and the Counter position
- Nonce + Counter lengths should add to 16 - otherwise returns false


function ComposeIV(Nonce, Counter: PAesBlock; NonceLen, CounterLen: integer; LSBCounter: boolean): boolean; overload;

Defines how the IV is set and updated in CTR mode
- default (if you don't call this method) uses a Counter in bytes 7..0
- you can specify startup Nonce and Counter, and the Counter position
- NonceLen + CounterLen should be 16 - otherwise it fails and returns false


procedure Decrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES un-cypher in the CTR mode


procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES cypher in the CTR mode


1.3.12. TAesCtr

TAesCtr = class(TAesC64)

Handle AES cypher/uncypher with 128-bit Counter mode (CTR)
- this class matches the NIST behavior for the CTR, so is compatible with reference implementations like OpenSSL - see also TAesCtrOsl
- WARNING: BREAKING CHANGE mORMot 1.18 SynCrypto's TAESCTR is TAesC64
- on x86_64 we use a 8*128-bit interleaved optimized asm which is faster than OpenSSL 1.1 in our benchmarks (and much faster than OpenSSL 3.0):

  mormot aes-128-ctr in 1.99ms i.e. 1254390/s or 2.6 GB/s
  mormot aes-256-ctr in 2.64ms i.e. 945179/s or 1.9 GB/s
  openssl aes-128-ctr in 2.23ms i.e. 1121076/s or 2.3 GB/s
  openssl aes-256-ctr in 2.80ms i.e. 891901/s or 1.8 GB/s

as reference, optimized but not interleaved OFB asm is 3 times slower:

  mormot aes-128-ofb in 6.88ms i.e. 363002/s or 772.5 MB/s
  mormot aes-256-ofb in 9.37ms i.e. 266808/s or 567.8 MB/s

- on i386, numbers are slower for our classes, which are not interleaved:

 mormot aes-128-ctr in 10ms i.e. 249900/s or 531.8 MB/s
 mormot aes-256-ctr in 12.47ms i.e. 200368/s or 426.4 MB/s
 openssl aes-128-ctr in 3.01ms i.e. 830288/s or 1.7 GB/s
 openssl aes-256-ctr in 3.52ms i.e. 709622/s or 1.4 GB/s

- use TAesFast[mCtr] to retrieve the fastest implementation at runtime


procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES cypher in the CTR mode


1.3.13. TAesMac256

TAesMac256 = record

Internal 256-bit structure used for TAesAbstractAead MAC storage


encrypted: THash128;

The plain MAC of the encrypted content
- digital signature of the encrypted text, to check e.g. for transmissions errors or storage corruption, with no compromission of the plain content
- used by TAesAbstractAead.MacCheckError()


plain: THash128;

The AES-encrypted MAC of the plain content
- digital signature of the plain text, to perform message authentication and integrity after it has been decrypted
- used by TAesAbstractAead.MacDecryptCheckTag()


1.3.14. TMacAndCryptData

TMacAndCryptData = packed record

Header layout used for TAesAbstract.MacAndCrypt format


data: byte;

Crc32c(nonce+mac) to avoid naive fuzzing


1.3.15. TAesAbstractAead

TAesAbstractAead = class(TAesAbstractEncryptOnly)

AEAD (authenticated-encryption with associated-data) abstract class
- don't use this abstract class, but actual usable inherited classes
- perform AES encryption and on-the-fly MAC computation, i.e. computes a proprietary 256-bit MAC during AES cyphering, as 128-bit CRC of the encrypted data and 128-bit CRC of the plain data, seeded from a Key, then encrypted using the current AES engine
- returned 256-bit MAC value has cryptographic level, and ensures data integrity, authenticity, and transmission issues - it therefore avoids the https://moxie.org/2011/12/13/the-cryptographic-doom-principle.html


destructor Destroy; override;

Release the used instance memory and resources
- also fill the internal internal MAC hashes with zeros, for safety


function MacCheckError(Encrypted: pointer; Count: cardinal): boolean; override;

Validate if an encrypted buffer matches the stored AEAD MAC
- called before the decryption process to ensure the input is not corrupted
- expects the 256-bit MAC, as returned after Encrypt() by MacEncryptGetTag, to be stored after the encrypted data
- returns true if the 128-bit CRC of the encrypted text matches the supplied buffer, ignoring the 128-bit CRC of the plain data
- since it is easy to forge such 128-bit CRC, it will only indicate that no transmission error occurred, but won't be an integrity or authentication proof (which will need full Decrypt + MacDecryptCheckTag)
- checked CRC includes any MacSetNonce() Associated value


function MacDecryptCheckTag(const DecryptMac: THash256): boolean; override;

Validates an AEAD (authenticated-encryption with associated-data) MAC
- check if the MAC computed during the last Decryption matches DecryptMac
- default implementation, for a non AEAD protocol, returns false


function MacEncryptGetTag(out EncryptMac: THash256): boolean; override;

Returns AEAD (authenticated-encryption with associated-data) MAC
- returns a 256-bit MAC hash, computed during the last Encryption
- encrypt the internal fMac property value using the current AES cypher on the plain content and returns true; only the plain content CRC-128 is AES encrypted, to avoid reverse attacks against the known encrypted data


function MacSetNonce(DoEncrypt: boolean; const RandomNonce: THash256; const Associated: RawByteString = ''): boolean; override;

Initialize 256-bit MAC computation for next Encrypt/Decrypt call
- initialize the internal fMacKey property, and returns true
- only the plain text crc is seeded from RandomNonce - encrypted message crc will use -1 as fixed seed, to avoid RandomNonce compromission
- should be set with a new MAC key value before each message, to avoid replay attacks (as called from TEcdheProtocol.SetKey)


property Mac: TAesMac256 read fMac write fMac;

Direct access to the low-level 256-bit CRC used for AEAD process
- could be set before Encrypt/Decrypt, as rough alternative to MacSetNonce()
- note that MacEncryptGetTag() uses this value, but finalizes its plain 128-bit hash by applying the current AES cypher on it


1.3.16. TAesCfc

TAesCfc = class(TAesAbstractAead)

AEAD combination of AES with Cipher feedback (CFB) and 256-bit crc32c MAC
- expect IV and MAC to be set before process, or IVAtBeginning=true
- this class will use AES-NI and CRC32C hardware instructions, if available

  mormot aes-128-cfc in 7.26ms i.e. 344210/s or 732.5 MB/s
  mormot aes-256-cfc in 9.72ms i.e. 257201/s or 547.3 MB/s

- so computing the 256-bit crc32c MAC has only a slight impact:

  mormot aes-128-cfb in 6.95ms i.e. 359247/s or 764.5 MB/s
  mormot aes-256-cfb in 9.40ms i.e. 265816/s or 565.7 MB/s

- on i386, numbers are similar:

 mormot aes-128-cfc in 7.49ms i.e. 333422/s or 709.5 MB/s
 mormot aes-256-cfc in 10ms i.e. 249775/s or 531.5 MB/s

procedure Decrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES un-cypher in the CFB mode, and compute 256-bit MAC


procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES cypher in the CFB mode, and compute a 256-bit MAC


1.3.17. TAesSymCrc

TAesSymCrc = class(TAesAbstractAead)

AEAD combination of AES and 256-bit MAC with symmetrical Encrypt/Decrypt
- don't use this abstract class, but actual usable TAesOfc or TAesCtc


procedure Decrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES uncypher calling Encrypt()
- will reverse fMac.plain/encrypted before and after Encrypt()


1.3.18. TAesOfc

TAesOfc = class(TAesSymCrc)

AEAD combination of AES with Output feedback (OFB) and 256-bit crc32c MAC
- expect IV and MAC to be set before process, or IVAtBeginning=true
- this class will use AES-NI and CRC32C hardware instructions, if available

  mormot aes-128-ofc in 8.04ms i.e. 310713/s or 661.2 MB/s
  mormot aes-256-ofc in 10.41ms i.e. 240084/s or 510.9 MB/s

- so computing the 256-bit crc32c MAC has only a slight impact:

  mormot aes-128-ofb in 6.88ms i.e. 363002/s or 772.5 MB/s
  mormot aes-256-ofb in 9.37ms i.e. 266808/s or 567.8 MB/s

- on i386, numbers are similar:

 mormot aes-128-ofc in 7.49ms i.e. 333511/s or 709.7 MB/s
 mormot aes-256-ofc in 9.93ms i.e. 251635/s or 535.5 MB/s

procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES cypher in the OFB mode, and compute a 256-bit MAC


1.3.19. TAesCtc

TAesCtc = class(TAesSymCrc)

AEAD combination of AES with Counter (CTR) and 256-bit crc32c MAC
- this class will use AES-NI and CRC32C hardware instructions, if available
- expect IV and MAC to be set before process, or IVAtBeginning=true
- on x86_64 we use a 8*128-bit interleaved optimized asm:

  mormot aes-128-ctc in 2.58ms i.e. 967492/s or 2 GB/s
  mormot aes-256-ctc in 3.13ms i.e. 797702/s or 1.6 GB/s

- to be compared with the CTR without 256-bit crc32c MAC computation:

  mormot aes-128-ctr in 1.99ms i.e. 1254390/s or 2.6 GB/s
  mormot aes-256-ctr in 2.64ms i.e. 945179/s or 1.9 GB/s

- could be used as an alternative to AES-GCM, even if OpenSSL is available:

  mormot aes-128-gcm in 3.45ms i.e. 722752/s or 1.5 GB/s
  mormot aes-256-gcm in 4.11ms i.e. 607385/s or 1.2 GB/s
  openssl aes-128-gcm in 2.86ms i.e. 874125/s or 1.8 GB/s
  openssl aes-256-gcm in 3.43ms i.e. 727590/s or 1.5 GB/s

- on i386, numbers are lower, because they are not interleaved:

 mormot aes-128-ctc in 9.76ms i.e. 256068/s or 544.9 MB/s
 mormot aes-256-ctc in 12.14ms i.e. 205930/s or 438.2 MB/s

procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES cypher in the CTR mode, and compute a 256-bit MAC


1.3.20. TAesGcmAbstract

TAesGcmAbstract = class(TAesAbstract)

Abstract parent to handle AES-GCM cypher/uncypher with built-in authentication
- implements AEAD (authenticated-encryption with associated-data) process via MacSetNonce/MacEncrypt or AesGcmAad/AesGcmFinal methods
- don't use this abstract class, but TAesFast[mGcm] - i.e. TAesGcm/TAesGcmOsl


destructor Destroy; override;

Release the used instance memory and resources
- also fill the internal TAes instance with zeros, for safety


function AesGcmFinal(var Tag: TAesBlock; TagLen: integer = 16): boolean; virtual; abstract;

AES-GCM pure alternative to MacEncryptGetTag/MacDecryptCheckTag
- if the MacEncrypt pattern is not convenient for your purpose
- after Encrypt, fill tag with the GCM value of the data and return true
- after Decrypt, return true only if the GCM value of the data match tag
- you can customize the tag length in bytes, if 16 if too big
- warning: by design, you should always call AesGcmFinal() after Encrypt/Decrypt before reusing this instance


function MacCheckError(Encrypted: pointer; Count: cardinal): boolean; override;

Validate if an encrypted buffer matches the stored AEAD MAC
- always return true, since AES-GCM is a one pass process, and perform the authentication during the decryption process


function MacDecryptCheckTag(const DecryptMac: THash256): boolean; override;

Validates the AES-GCM GMAC after Decryption
- the expected 128-bit GMAC should be available in DecryptMac.Lo
- see AesGcmFinal() method as a "pure AES-GCM" alternative


function MacEncryptGetTag(out EncryptMac: THash256): boolean; override;

Returns the AES-GCM GMAC after Encryption
- returns the 128-bit GMAC into EncryptMac.Lo
- see AesGcmFinal() method as a "pure AES-GCM" alternative
- warning: by design, you should always call MacEncryptGetTag() or MacDecryptCheckTag() after Encrypt/Decrypt before reusing this instance


function MacSetNonce(DoEncrypt: boolean; const RandomNonce: THash256; const Associated: RawByteString = ''): boolean; override;

Prepare the AES-GCM process before Encrypt/Decrypt is called
- RandomNonce is not used: AES-GCM has its own nonce setting algorithm for its GMAC, and IV is likely to be randomly set by EncryptPkcs7()
- will just include any supplied associated data to the GMAC tag
- see AesGcmAad() method as a "pure AES-GCM" alternative


procedure AesGcmAad(Buf: pointer; Len: integer); virtual; abstract;

AES-GCM pure alternative to MacSetNonce()
- if the MacEncrypt pattern is not convenient for your purpose
- set the IV as usual (only the first 12 bytes will be used for GCM), then optionally append any AEAD data with this method; warning: you need to call Encrypt() once before - perhaps as Encrypt(nil, nil, 0)


procedure Decrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES un-cypher and authentication


procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES-GCM cypher and authentication


1.3.21. TAesGcm

TAesGcm = class(TAesGcmAbstract)

Handle AES-GCM cypher/uncypher using our TAesGcmEngine
- implements AEAD (authenticated-encryption with associated-data) process via MacSetNonce/MacEncrypt or AesGcmAad/AesGcmFinal methods
- will use AES-NI and CLMUL hardware instructions, if available
- expect IV to be set before process, or IVAtBeginning=true
- by design, AES-GCM doesn't expect any Nonce to be supplied before process
- our TAesGcm class is 8x interleaved for both GMAC and AES-CTR

  mormot aes-128-gcm in 3.45ms i.e. 722752/s or 1.5 GB/s
  mormot aes-256-gcm in 4.11ms i.e. 607385/s or 1.2 GB/s

- OpenSSL 1.1 is slightly faster since performs GMAC + CTR as single pass but OpenSSL 3.0 is slower due to higher library overhead

  openssl aes-128-gcm in 2.86ms i.e. 874125/s or 1.8 GB/s
  openssl aes-256-gcm in 3.43ms i.e. 727590/s or 1.5 GB/s

- on i386, numbers are much lower, since lacks interleaved asm

  mormot aes-128-gcm in 15.86ms i.e. 157609/s or 335.4 MB/s
  mormot aes-256-gcm in 18.23ms i.e. 137083/s or 291.7 MB/s
  openssl aes-128-gcm in 5.49ms i.e. 455290/s or 0.9 GB/s
  openssl aes-256-gcm in 6.11ms i.e. 408630/s or 869.6 MB/s

- use TAesFast[mGcm] to retrieve the fastest implementation at runtime


function AesGcmFinal(var Tag: TAesBlock; TagLen: integer): boolean; override;

AES-GCM pure alternative to MacEncryptGetTag/MacDecryptCheckTag
- after Encrypt, fill tag with the GCM value of the data and return true
- after Decrypt, return true only if the GCM value of the data match tag


function Clone: TAesAbstract; override;

Creates a new instance with the very same values
- by design, our classes will use TAesGcmEngine stateless context, so this method will just copy the current fields to a new instance, by-passing the key creation step


procedure AesGcmAad(Buf: pointer; Len: integer); override;

AES-GCM pure alternative to MacSetNonce()
- set the IV as usual (only the first 12 bytes will be used for GCM), then optionally append any AEAD data with this method; warning: you need to call Encrypt() once before - perhaps as Encrypt(nil, nil, 0)


1.3.22. TAesAbstractApi

TAesAbstractApi = class(TAesAbstract)

Handle AES cypher/uncypher using Windows CryptoApi and the official Microsoft AES Cryptographic Provider (PROV_RSA_AES)
- see @http://msdn.microsoft.com/en-us/library/windows/desktop/aa386979
- timing of our optimized asm versions, for small (<=8KB) block processing (similar to standard web pages or most typical JSON/XML content), benchmarked on a Core i7 notebook and compiled as Win32 platform:

 AES128 - ECB:79.33ms CBC:83.37ms CFB:80.75ms OFB:78.98ms CTR:80.45ms
 AES192 - ECB:91.16ms CBC:96.06ms CFB:96.45ms OFB:92.12ms CTR:93.38ms
 AES256 - ECB:103.22ms CBC:119.14ms CFB:111.59ms OFB:107.00ms CTR:110.13ms

- timing of the same process, using CryptoApi official PROV_RSA_AES provider:

 AES128 - ECB_API:102.88ms CBC_API:124.91ms
 AES192 - ECB_API:115.75ms CBC_API:129.95ms
 AES256 - ECB_API:139.50ms CBC_API:154.02ms

- but the CryptoApi does not supports AES-NI, whereas our classes handle it, with a huge speed benefit
- under Win64, the official CryptoApi is slower our x86_64 asm version, and the Win32 version of CryptoApi itself, but slower than our AES-NI code

 AES128 - ECB:107.95ms CBC:112.65ms CFB:109.62ms OFB:107.23ms CTR:109.42ms
 AES192 - ECB:130.30ms CBC:133.04ms CFB:128.78ms OFB:127.25ms CTR:130.22ms
 AES256 - ECB:145.33ms CBC:147.01ms CFB:148.36ms OFB:145.96ms CTR:149.67ms
 AES128 - ECB_API:89.64ms CBC_API:100.84ms
 AES192 - ECB_API:99.05ms CBC_API:105.85ms
 AES256 - ECB_API:107.11ms CBC_API:118.04ms

- in practice, you could forget about using the CryptoApi, unless you are required to do so, for legal/corporate reasons


destructor Destroy; override;

Release the AES execution context


procedure Decrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES un-cypher in the ECB mode
- if Count is not a multiple of a 16 bytes block, the IV will be used to XOR the trailing bytes - so it won't be compatible with our TAesAbstractSyn classes: you should better use PKC7 padding instead


procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); override;

Perform the AES cypher in the ECB mode
- if Count is not a multiple of a 16 bytes block, the IV will be used to XOR the trailing bytes - so it won't be compatible with our TAesAbstractSyn classes: you should better use PKC7 padding instead


1.3.23. TAesEcbApi

TAesEcbApi = class(TAesAbstractApi)

Handle AES cypher/uncypher without chaining (ECB) using Windows CryptoApi


1.3.24. TAesCbcApi

TAesCbcApi = class(TAesAbstractApi)

Handle AES cypher/uncypher Cipher-block chaining (CBC) using Windows CryptoApi


1.3.25. TAesCfbApi

TAesCfbApi = class(TAesAbstractApi)

Handle AES cypher/uncypher Cipher feedback (CFB) using Windows CryptoApi
- NOT TO BE USED: the current PROV_RSA_AES provider does not return expected values for CFB


1.3.26. TAesOfbApi

TAesOfbApi = class(TAesAbstractApi)

Handle AES cypher/uncypher Output feedback (OFB) using Windows CryptoApi
- NOT TO BE USED: the current PROV_RSA_AES provider does not implement this mode, and returns a NTE_BAD_ALGID error


1.3.27. TAesPkcs7Abstract

TAesPkcs7Abstract = class(TStreamWithPositionAndSize)

Abstract parent class to TAesPkcs7Writer and TAesPkcs7Reader


constructor Create(aStream: TStream; const password: RawUtf8; const salt: RawByteString = ''; rounds: cardinal = 1000; aesMode: TAesMode = mCtr; bufferSize: integer = 128 shl 10); overload;

Initialize AES encryption/decryption stream for a given stream and password
- will derivate the password using PBKDF2 over HMAC-SHA256, using lower 128-bit as AES-CTR-128 key, and the upper 128-bit as IV
- you can customize the parameters if needed


constructor Create(aStream: TStream; const key; keySizeBits: cardinal; aesMode: TAesMode = mCtr; IV: PAesBlock = nil; bufferSize: integer = 128 shl 10); overload; virtual;

Initialize AES encryption/decryption stream for a given stream and key
- aStream is typically a TMemoryStream or a TFileStreamEx
- a trailing random IV is generated/retrieved, unless an IV is supplied
- AES is performed on an internal buffer of 128KB by default for efficiency


destructor Destroy; override;

Finalize the AES encryption stream


function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;

Position change is not allowed: this method will raise an exception


property Stream: TStream read fStream;

Access to the associated stream, e.g. a TFileStreamEx instance


1.3.28. TAesPkcs7Writer

TAesPkcs7Writer = class(TAesPkcs7Abstract)

Multi-mode PKCS7 buffered AES encryption stream
- output will follow standard PKCS7 padding, with a trailing IV if needed, i.e. TAesAbstract.DecryptPkcs7 and TAesPkcs7Reader encoding


constructor Create(outStream: TStream; const key; keySizeBits: cardinal; aesMode: TAesMode = mCtr; IV: PAesBlock = nil; bufferSize: integer = 128 shl 10); override;

Initialize the AES encryption stream into a given stream and a key
- outStream is typically a TMemoryStream or a TFileStreamEx
- aesMode should be one of the supported AES_PKCS7WRITER chaining mode
- by default, a trailing random IV is generated, unless IV is supplied
- see also Create() overload with PBKDF2 password derivation


destructor Destroy; override;

Finalize the AES encryption stream
- internally call the Finish method


function Read(var Buffer; Count: Longint): Longint; override;

Reading some data is not allowed -> will raise an exception on call


function Write(const Buffer; Count: Longint): Longint; override;

Append some data to the outStream, after encryption


procedure Finish;

Write pending data to the Dest stream
- should always be called before closing the outStream (some data may still be in the internal buffers)


1.3.29. TAesPkcs7Reader

TAesPkcs7Reader = class(TAesPkcs7Abstract)

Multi-mode PKCS7 buffered AES decryption stream
- input should follow standard PKCS7 padding, with a trailing IV if needed, i.e. TAesAbstract.EncryptPkcs7 and TAesPkcs7Writer encoding


constructor Create(inStream: TStream; const key; keySizeBits: cardinal; aesMode: TAesMode = mCtr; IV: PAesBlock = nil; bufferSize: integer = 128 shl 10); override;

Initialize the AES decryption stream from an intput stream and a key
- inStream is typically a TMemoryStream or a TFileStreamEx
- inStream size will be checked for proper PKCS7 padding
- aesMode should be one of the supported AES_PKCS7WRITER chaining mode
- by default, a trailing random IV is read, unless IV is supplied
- see also Create() overload with PBKDF2 password derivation


function Read(var Buffer; Count: Longint): Longint; override;

Read and decode some data from the inStream


function Write(const Buffer; Count: Longint): Longint; override;

Writing some data is not allowed -> will raise an exception on call


1.3.30. TAesLocked

TAesLocked = class(TObjectOSLightLock)

Thread-safe class containing a TAes encryption/decryption engine


destructor Destroy; override;

TAes is enough for cache line padding of this lock finalize all used memory and the TAes instance


1.3.31. TAesPrngAbstract

TAesPrngAbstract = class(TAesLocked)

Abstract parent for TAesPrng* classes
- you should never use this class, but TAesPrng, TSystemPrng or TAesPrngOsl


function AFSplit(const Buffer: RawByteString; StripesCount: integer): RawByteString; overload;

Create an anti-forensic representation of a key for safe storage
- a binary buffer will be split into StripesCount items, ready to be saved on disk; returned length is BufferBytes*(StripesCount+1) bytes
- just a wrapper around the other overloaded AFSplit() funtion


function AFSplit(const Buffer; BufferBytes, StripesCount: integer): RawByteString; overload;

Create an anti-forensic representation of a key for safe storage
- a binary buffer will be split into StripesCount items, ready to be saved on disk; returned length is BufferBytes*(StripesCount+1) bytes
- AFSplit supports secure data destruction crucial for secure on-disk key management. The key idea is to bloat information and therefore improve the chance of destroying a single bit of it. The information is bloated in such a way, that a single missing bit causes the original information become unrecoverable.
- this implementation uses SHA-256 as diffusion element, and the current TAesPrngAbstract instance to gather randomness
- for reference, see TKS1 as used for LUKS and defined in @https://gitlab.com/cryptsetup/cryptsetup/wikis/TKS1-draft.pdf


class function AFUnsplit(const Split: RawByteString; out Buffer; BufferBytes: integer): boolean; overload;

Retrieve a key from its anti-forensic representation
- is the reverse function of AFSplit() method
- returns TRUE if the input buffer matches BufferBytes value
- is defined as a class function since is stand-alone


class function AFUnsplit(const Split: RawByteString; StripesCount: integer): RawByteString; overload;

Retrieve a key from its anti-forensic representation
- is the reverse function of AFSplit() method
- returns the un-splitted binary content
- returns '' if StripesCount is incorrect
- is defined as a class function since is stand-alone


class function Bytes(Len: integer): TBytes;

Just a wrapper around TAesPrngAbstract.Main.FillRandomBytes() function
- this method is thread-safe, but you may use your own TAesPrng instance if you need some custom entropy level


class function Fill(Len: integer): RawByteString; overload;

Just a wrapper around TAesPrng.Main.FillRandom() function
- this method is thread-safe, but you may use your own TAesPrng instance if you need some custom entropy level


function FillRandom(Len: integer): RawByteString; overload;

Returns a binary buffer filled with some pseudorandom data
- this method is thread-safe, and its AES process is non blocking


function FillRandomBytes(Len: integer): TBytes;

Returns a binary buffer filled with some pseudorandom data
- this method is thread-safe, and its AES process is non blocking


function FillRandomHex(Len: integer): RawUtf8;

Returns an hexa-encoded binary buffer filled with some pseudorandom data
- this method is thread-safe, and its AES process is non blocking


class function IsAvailable: boolean; virtual;

Quick check if this class PRNG is available on the system
- this default implementation returns true
- TAesPrnOpenSsl.IsAvailable returns false if OpenSSL is not installed


class function Main: TAesPrngAbstract; virtual; abstract;

Returns a shared instance of a TAesPrng* instance
- if you need to generate some random content, just call the TAesPrng*.Main.FillRandom() overloaded methods, or directly TAesPrng*.Fill() class methods


function Random32: cardinal; overload;

Returns a 32-bit unsigned random number
- is twice slower than Lecuyer's Random32 of mormot.core.base unit, but is cryptographic secure


function Random32(max: cardinal): cardinal; overload;

Returns a 32-bit unsigned random number, with a maximum value
- is twice slower than Lecuyer's Random32 of mormot.core.base unit, but is cryptographic secure


function Random64: QWord;

Returns a 64-bit unsigned random number


function RandomDateTime: TDateTime;

Returns a contemporary date/time


function RandomDouble: double;

Returns a 64-bit floating-point random number in range [0..1]


function RandomExt: TSynExtended;

Returns a floating-point random number in range [0..1]


function RandomPassword(Len: integer): SpiUtf8;

Computes a random ASCII password
- will contain uppercase/lower letters, digits and $.:()?%!-+*/@# excluding ;,= to allow direct use in CSV content


class procedure Fill(out Block: THash256); overload;

Just a wrapper around TAesPrngAbstract.Main.FillRandom() function
- this method is thread-safe, but you may use your own TAesPrng instance if you need some custom entropy level


class procedure Fill(Buffer: pointer; Len: integer); overload;

Just a wrapper around TAesPrngAbstract.Main.FillRandom() function
- this method is thread-safe, but you may use your own TAesPrng instance if you need some custom entropy level


class procedure Fill(out Block: TAesBlock); overload;

Just a wrapper around TAesPrngAbstract.Main.FillRandom() function
- this method is thread-safe, but you may use your own TAesPrng instance if you need some custom entropy level


procedure FillRandom(out Block: TAesBlock); overload; virtual;

Fill a TAesBlock with some pseudorandom data
- could be used e.g. to compute an AES Initialization Vector (IV)
- this method is thread-safe


procedure FillRandom(out Buffer: THash256); overload; virtual;

Fill a 256-bit buffer with some pseudorandom data
- this method is thread-safe


procedure FillRandom(Buffer: pointer; Len: PtrInt); overload; virtual; abstract;

Fill a binary buffer with some pseudorandom data
- this method should be thread-safely implemented when overriden


procedure Seed; virtual;

Would force the internal generator to re-seed its private key
- avoid potential attacks on backward or forward security
- would be called by FillRandom() methods, according to SeedAfterBytes
- this method is thread-safe, and does nothing by default


procedure XorRandom(Buffer: pointer; Len: integer);

Xor a binary buffer with some pseudorandom data
- call FillRandom then xor the supplied buffer content


property TotalBytes: QWord read fTotalBytes;

How many bytes this generator did compute


1.3.32. TAesPrng

TAesPrng = class(TAesPrngAbstract)

Cryptographic pseudorandom number generator (CSPRNG) based on AES-256
- use as a shared instance via TAesPrng.Fill() overloaded class methods
- this class is able to generate some random output by encrypting successive values of a counter with AES-256-CTR and a secret key
- this internal secret key is generated from PBKDF2 derivation of OS-supplied entropy using HMAC over SHA-512
- by design, such a PRNG is as good as the cypher used - for reference, see https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator
- FillRandom() is thread-safe, and its AES process is not blocking: only the CTR is pre-computed inside a lock
- use fast hardware AES-NI, and our 8X interleaved asm on x86_64 asm:

  mORMot Random32 in 3.95ms i.e. 25,303,643/s, aver. 0us, 96.5 MB/s
  mORMot FillRandom in 46us, 2 GB/s

- it is actually much faster than OpenSSL with the same 256-bit safety level:

  OpenSSL Random32 in 288.71ms i.e. 346,363/s, aver. 2us, 1.3 MB/s
  OpenSSL FillRandom in 240us, 397.3 MB/s

- on i386, numbers are similar, but for FillRandom which is not interleaved:

 mORMot Random32 in 5.54ms i.e. 18,044,027/s, aver. 0us, 68.8 MB/s
 mORMot FillRandom in 203us, 469.7 MB/s
 OpenSSL Random32 in 364.24ms i.e. 274,540/s, aver. 3us, 1 MB/s
 OpenSSL FillRandom in 371us, 257 MB/s

constructor Create(Pbkdf2Round: integer; ReseedAfterBytes: integer = 32 * 1024 * 1024; AesKeyBits: integer = 256); reintroduce; overload; virtual;

Initialize the internal secret key, using Operating System entropy
- entropy is gathered from the OS, using GetEntropy() method
- you can specify how many Pbkdf2HmacSha512 rounds are applied to the OS-gathered entropy - the higher, the better, but also the slower
- internal private key would be re-seeded after ReseedAfterBytes bytes (32MB by default) are generated, using GetEntropy()
- by default, AES-256 will be used, unless AesKeySize is set to 128, which may be slightly faster (especially if AES-NI is not available)


constructor Create; overload; override;

Initialize the internal secret key, using Operating System entropy


class function GetEntropy(Len: integer; Source: TAesPrngGetEntropySource = gesSystemAndUser): RawByteString; virtual;

Retrieve some entropy bytes from the Operating System
- system entropy comes from CryptGenRandom API on Windows (which may be very slow), and /dev/urandom or /dev/random on Linux/POSIX (which may block waiting from OS entropy if gesSystemOnlyMayBlock is set)
- user entropy comes from the output of a SHA-3 cryptographic SHAKE-256 generator in XOF mode, from several sources (timestamp, thread, hardware and system information, mormot.core.base XorEntropy)
- Source will mix one or both of those entropy sources - note that gesSystemAndUser is the default, but gesUserOnly is the fastest, and also derivated from 512-bit of OS entropy retrieved once at startup
- to gather randomness, use TAesPrng.Main.FillRandom() or TAesPrng.Fill() methods, NOT this class function (which will be much slower, BTW)


class function Main: TAesPrngAbstract; override;

Returns a shared instance of a TAesPrng instance
- if you need to generate some random content, just call the TAesPrng.Main.FillRandom() overloaded methods, or directly TAesPrng.Fill()


procedure FillRandom(Buffer: pointer; Len: PtrInt); override;

Fill a binary buffer with some pseudorandom data
- this method is thread-safe
- is just a wrapper around FillSystemRandom()


procedure FillRandom(out Block: TAesBlock); override;

Fill a TAesBlock with some pseudorandom data
- this method is thread-safe


procedure FillRandom(out Buffer: THash256); override;

Fill a 256-bit buffer with some pseudorandom data
- this method is thread-safe


procedure Seed; override;

Would force the internal generator to re-seed its private key
- avoid potential attacks on backward or forward security
- would be called by FillRandom() methods, according to SeedAfterBytes
- this method is thread-safe


property AesKeySize: integer read fAesKeySize;

How many bits (128 or 256 - which is the default) are used for the AES


property SeedAfterBytes: PtrUInt read fSeedAfterBytes;

After how many generated bytes Seed method would be called
- default is 32 MB - i.e. 21-bit CTR rounds which seems paranoid enough
- if set to 0 - e.g. for TSystemPrng - no seeding will occur


property SeedEntropySource: TAesPrngGetEntropySource read fSeedEntropySource;

The source of entropy used during seeding - faster gesUserOnly by default


property SeedPbkdf2Round: cardinal read fSeedPbkdf2Round;

How many Pbkdf2HmacSha512 count is applied by Seed to the entropy
- default is 16 rounds, which is more than enough for entropy gathering, since GetEntropy output comes from a SHAKE-256 generator in XOF mode


1.3.33. TSystemPrng

TSystemPrng = class(TAesPrngAbstract)

TAesPrng-compatible class using Operating System pseudorandom source
- may be used instead of TAesPrng if a "standard" generator is required - you could override MainAesPrng global variable
- will call /dev/urandom under POSIX, and CryptGenRandom API on Windows
- warning: may block on some BSD flavors, depending on /dev/urandom
- from the cryptographic point of view, our TAesPrng class doesn't suffer from the "black-box" approach of Windows, give consistent randomness over all supported cross-platform, and is indubitably faster


class function Main: TAesPrngAbstract; override;

Returns the single system-wide instance of TSystemPrng
- if you need to generate some random content, just call the TSystemPrng.Main.FillRandom() overloaded methods, or directly TSystemPrng.Fill() class methods


procedure FillRandom(Buffer: pointer; Len: PtrInt); override;

Fill a binary buffer with some pseudorandom data
- this method is thread-safe
- is just a wrapper around FillSystemRandom()


1.3.34. TSha256

TSha256 = object(TObject)

Implements SHA-256 hashing
- we defined a record instead of a class, to allow stack allocation and thread-safe reuse of one initialized instance, e.g. for THmacSha256
- see TSynHasher if you expect to support more than one algorithm at runtime
- can use several asm versions with HW opcodes support on x86_64 and aarch64


function Final(NoInit: boolean = false): TSha256Digest; overload;

Finalize and compute the resulting SHA-256 hash Digest of all data affected to Update() method


procedure Final(out Digest: TSha256Digest; NoInit: boolean = false); overload;

Finalize and compute the resulting SHA-256 hash Digest of all data affected to Update() method


procedure Full(Buffer: pointer; Len: integer; out Digest: TSha256Digest);

One method to rule them all
- call Init, then Update(), then Final()


procedure Init;

Initialize SHA-256 context for hashing


procedure Update(Buffer: pointer; Len: integer); overload;

Update the SHA-256 context with some data


procedure Update(const Buffer: RawByteString); overload;

Update the SHA-256 context with some data


1.3.35. TSha384512

TSha384512 = object(TObject)

Abstract parent for implementing SHA-384, SHA-512/256 and SHA-512 hashing


procedure Update(Buffer: pointer; Len: integer);

Update the SHA-384 / SHA-512/256 / SHA-512 context with some data


1.3.36. TSha384

TSha384 = object(TObject)

Implements SHA-384 hashing
- it is in fact a TSha512 truncated hash, with other initial hash values
- we defined a record instead of a class, to allow stack allocation and thread-safe reuse of one initialized instance, e.g. for THmacSha384
- see TSynHasher if you expect to support more than one algorithm at runtime


function Final(NoInit: boolean = false): TSha384Digest; overload;

Finalize and compute the resulting SHA-384 hash Digest of all data affected to Update() method


procedure Final(out Digest: TSha384Digest; NoInit: boolean = false); overload;

Finalize and compute the resulting SHA-384 hash Digest of all data affected to Update() method
- will also call Init to reset all internal temporary context, for safety


procedure Full(Buffer: pointer; Len: integer; out Digest: TSha384Digest);

One method to rule them all
- call Init, then Update(), then Final()


procedure Init;

Initialize SHA-384 context for hashing


procedure Update(Buffer: pointer; Len: integer); overload;

Update the SHA-384 context with some data


procedure Update(const Buffer: RawByteString); overload;

Update the SHA-384 context with some data


1.3.37. TSha512_256

TSha512_256 = object(TObject)

Implements SHA-512/256 hashing
- it is in fact a TSha512 truncated hash, with other initial hash values
- see TSynHasher if you expect to support more than one algorithm at runtime


function Final(NoInit: boolean = false): TSha256Digest; overload;

Finalize and compute the resulting SHA-384 hash Digest of all data affected to Update() method


procedure Final(out Digest: TSha256Digest; NoInit: boolean = false); overload;

Finalize and compute the resulting SHA-512/256 hash Digest of all data affected to Update() method
- will also call Init to reset all internal temporary context, for safety


procedure Full(Buffer: pointer; Len: integer; out Digest: TSha256Digest);

One method to rule them all
- call Init, then Update(), then Final()


procedure Init;

Initialize SHA-512/256 context for hashing


procedure Update(Buffer: pointer; Len: integer); overload;

Update the SHA-512/256 context with some data


procedure Update(const Buffer: RawByteString); overload;

Update the SHA-512/256 context with some data


1.3.38. TSha512

TSha512 = object(TObject)

Implements SHA-512 hashing
- by design, this algorithm is expected to be much faster on 64-bit CPU, since all internal process involves QWord - but we included a SSE3 asm optimized version on 32-bit CPU under Windows and Linux, which is almost as fast as on plain x64, and even faster than SHA-256 and SHA-3
- under x86/Delphi, plain pascal is 40MB/s, SSE3 asm 180MB/s
- on x64, pascal Delphi is 150MB/s, and FPC is 190MB/s (thanks to native RorQWord intrinsic compiler function) - we also included a SSE4 asm version which outperforms other cryptographic hashes to more than 380MB/s
- we defined a record instead of a class, to allow stack allocation and thread-safe reuse of one initialized instance, e.g. for THmacSha512
- see TSynHasher if you expect to support more than one algorithm at runtime


function Final(NoInit: boolean = false): TSha512Digest; overload;

Finalize and compute the resulting SHA-512 hash Digest of all data affected to Update() method


procedure Final(out Digest: TSha512Digest; NoInit: boolean = false); overload;

Finalize and compute the resulting SHA-512 hash Digest of all data affected to Update() method
- will also call Init to reset all internal temporary context, for safety


procedure Full(Buffer: pointer; Len: integer; out Digest: TSha512Digest);

One method to rule them all
- call Init, then Update(), then Final()


procedure Init;

Initialize SHA-512 context for hashing


procedure Update(Buffer: pointer; Len: integer); overload;

Update the SHA-512 context with some data


procedure Update(const Buffer: RawByteString); overload;

Update the SHA-512 context with some data


1.3.39. TSha3

TSha3 = object(TObject)

Implements SHA-3 (Keccak) hashing
- Keccak was the winner of the NIST hashing competition for a new hashing algorithm to provide an alternative to SHA-256. It became SHA-3 and was named by NIST a FIPS 180-4, then FIPS 202 hashing standard in 2015
- by design, SHA-3 doesn't need to be encapsulated into a HMAC algorithm, since it already includes proper padding, so keys could be concatenated
- this implementation is based on Wolfgang Ehrhardt's and Eric Grange's, with manually optimized x64 assembly, with AVX2 runtime detection
- we defined a record instead of a class, to allow stack allocation and thread-safe reuse of one initialized instance, e.g. after InitCypher
- see TSynHasher if you expect to support more than one algorithm at runtime


function Algorithm: TSha3Algo;

Returns the algorithm specified at Init()


function Cypher(const Source: RawByteString): RawByteString; overload;

Uses SHA-3 in "Extendable-Output Function" (XOF) to cypher some content
- this overloaded function expects the instance to have been prepared by previous InitCypher call
- resulting string will have the very same size than the Source
- XOF is implemented as a symmetrical algorithm: use this Cypher() method for both encryption and decryption of any buffer
- you can call this method several times, to work with a stream buffer; but for safety, you should eventually call Done


function Cypher(const Key, Source: RawByteString; Algo: TSha3Algo = SHAKE_256): RawByteString; overload;

Uses SHA-3 in "Extendable-Output Function" (XOF) to cypher some content
- this overloaded function works with RawByteString content
- resulting string will have the very same size than the Source
- XOF is implemented as a symmetrical algorithm: use this Cypher() method for both encryption and decryption of any buffer


function Final256(NoInit: boolean = false): THash256;

Finalize and compute the resulting SHA-3 hash 256-bit Digest


function Final512(NoInit: boolean = false): THash512;

Finalize and compute the resulting SHA-3 hash 512-bit Digest


function FullStr(Algo: TSha3Algo; Buffer: pointer; Len: integer; DigestBits: integer = 0): RawUtf8;

Compute a SHA-3 hash hexadecimal Digest from a buffer, in one call
- call Init, then Update(), then Final() using the supplied algorithm
- default DigestBits=0 will write the default number of bits to Digest output memory buffer, according to the specified TSha3Algo


procedure Cypher(Source, Dest: pointer; DataLen: integer); overload;

Uses SHA-3 in "Extendable-Output Function" (XOF) to cypher some content
- this overloaded function expects the instance to have been prepared by previous InitCypher call
- resulting Dest buffer will have the very same size than the Source
- XOF is implemented as a symmetrical algorithm: use this Cypher() method for both encryption and decryption of any buffer
- you can call this method several times, to work with a stream buffer; but for safety, you should eventually call Done


procedure Cypher(Key, Source, Dest: pointer; KeyLen, DataLen: integer; Algo: TSha3Algo = SHAKE_256); overload;

Uses SHA-3 in "Extendable-Output Function" (XOF) to cypher some content
- there is no MAC stored in the resulting binary
- Source and Dest will have the very same DataLen size in bytes, and Dest will be Source XORed with the XOF output, so encryption and decryption are just obtained by the same symmetric call
- in this implementation, Source and Dest should point to two diverse buffers
- for safety, the Key should be a secret value, pre-pended with a random salt/IV or a resource-specific identifier (e.g. a record ID or a S/N), to avoid reverse composition of the cypher from known content - note that concatenating keys with SHA-3 is as safe as computing a HMAC for SHA-2


procedure Done;

Fill all used memory context with zeros, for safety
- is necessary only when NoInit is set to true (e.g. after InitCypher)


procedure Final(out Digest: THash512; NoInit: boolean = false); overload;

Finalize and compute the resulting SHA-3 hash 512-bit Digest


procedure Final(out Digest: THash256; NoInit: boolean = false); overload;

Finalize and compute the resulting SHA-3 hash 256-bit Digest


procedure Final(Digest: pointer; DigestBits: integer = 0; NoInit: boolean = false); overload;

Finalize and compute the resulting SHA-3 hash Digest
- Digest destination buffer must contain enough bytes
- default DigestBits=0 will write the default number of bits to Digest output memory buffer, according to the current TSha3Algo
- you can call this method several times, to use this SHA-3 hasher as "Extendable-Output Function" (XOF), e.g. for stream encryption (ensure NoInit is set to true, to enable recall)


procedure Full(Buffer: pointer; Len: integer; out Digest: THash256); overload;

Compute a SHA-3 hash 256-bit Digest from a buffer, in one call
- call Init, then Update(), then Final() using SHA3_256 into a THash256


procedure Full(Buffer: pointer; Len: integer; out Digest: THash512); overload;

Compute a SHA-3 hash 512-bit Digest from a buffer, in one call
- call Init, then Update(), then Final() using SHA3_512 into a THash512


procedure Full(Algo: TSha3Algo; Buffer: pointer; Len: integer; Digest: pointer; DigestBits: integer = 0); overload;

Compute a SHA-3 hash Digest from a buffer, in one call
- call Init, then Update(), then Final() using the supplied algorithm
- default DigestBits=0 will write the default number of bits to Digest output memory buffer, according to the specified TSha3Algo


procedure Init(Algo: TSha3Algo);

Initialize SHA-3 context for hashing
- in practice, you may use SHA3_256 or SHA3_512 to return THash256 or THash512 digests


procedure InitCypher(Key: pointer; KeyLen: integer; Algo: TSha3Algo = SHAKE_256); overload;

Uses SHA-3 in "Extendable-Output Function" (XOF) to cypher some content
- prepare the instance to further Cypher() calls
- you may reuse the very same TSha3 instance by copying it to a local variable before calling this method (this copy is thread-safe)
- works with RawByteString content


procedure InitCypher(const Key: RawByteString; Algo: TSha3Algo = SHAKE_256); overload;

Uses SHA-3 in "Extendable-Output Function" (XOF) to cypher some content
- prepare the instance to further Cypher() calls
- you may reuse the very same TSha3 instance by copying it to a local variable before calling this method (this copy is thread-safe)
- works with RawByteString content


procedure Update(Buffer: pointer; Len: integer); overload;

Update the SHA-3 context with some data


procedure Update(const Buffer: RawByteString); overload;

Update the SHA-3 context with some data


1.3.40. TMd5

TMd5 = object(TObject)

Implements MD5 hashing - and could also implement MD4 if really needed
- those algorithms have known weaknesses, so should not be considered as cryptographic secure, but are available for compatibility purposes
- we defined a record instead of a class, to allow stack allocation and thread-safe reuse of one initialized instance
- see TSynHasher if you expect to support more than one algorithm at runtime
- this implementation has optimized x86 and x64 assembly, and a pure-pascal fallback code on other CPUs (and for the MD4 algorithm)


function Final: TMd5Digest; overload;

Finalize and compute the resulting MD5 hash Digest of all data affected to Update() method


procedure Final(out result: TMd5Digest); overload;

Finalize and compute the resulting MD5 hash Digest of all data affected to Update() method


procedure Finalize;

Finalize the MD5 hash process
- the resulting hash digest would be stored in buf public variable


procedure Full(Buffer: pointer; Len: integer; out Digest: TMd5Digest; ForceMD4: boolean = false);

One method to rule them all
- call Init/InitMD4, Update(), then Final() with a stack-allocated context


procedure Init;

Initialize MD5 context for hashing


procedure InitMD4;

Initialize MD4 context for hashing
- will reuse the whole MD5 context but setup the MD4 transform function
- MD4 is clearly deprecated, but available here for compatibility usage


procedure Update(const buffer; Len: cardinal); overload;

Update the MD5 context with some data


procedure Update(const Buffer: RawByteString); overload;

Update the MD5 context with some data


1.3.41. TRC4

TRC4 = object(TObject)

Implements RC4 encryption/decryption
- this algorithm has known weaknesses, so should not be considered as cryptographic secure, but is available for other purposes
- we defined a record instead of a class, to allow stack allocation and thread-safe reuse of one initialized instance
- you can also restore and backup any previous state of the RC4 encryption by copying the whole TRC4 variable into another (stack-allocated) variable


procedure Drop(Count: cardinal);

Drop the next Count bytes from the RC4 cypher state
- may be used in Stream mode, or to initialize in RC4-drop[n] mode


procedure Encrypt(const BufIn; var BufOut; Count: cardinal);

Perform the RC4 cypher encryption/decryption on a buffer
- each call to this method shall be preceded with an Init() call
- RC4 is a symmetrical algorithm: use this Encrypt() method for both encryption and decryption of any buffer


procedure EncryptBuffer(BufIn, BufOut: PByte; Count: cardinal);

Perform the RC4 cypher encryption/decryption on a buffer
- each call to this method shall be preceded with an Init() call
- RC4 is a symmetrical algorithm: use this EncryptBuffer() method for both encryption and decryption of any buffer


procedure Init(const aKey; aKeyLen: integer);

Initialize the RC4 encryption/decryption
- KeyLen is in bytes, and should be within 1..255 range
- warning: aKey is an untyped constant, i.e. expects a raw set of memory bytes: do NOT use assign it with a string or a TBytes instance: you would use the pointer to the data as key


procedure InitSha3(const aKey; aKeyLen: integer);

Initialize RC4-drop[3072] encryption/decryption after SHA-3 hashing
- will use SHAKE-128 generator in XOF mode to generate a 256 bytes key, then drop the first 3072 bytes from the RC4 stream
- this initializer is much safer than plain Init, so should be considered for any use on RC4 for new projects - even if AES-NI is 2 times faster, and safer SHAKE-128 operates in XOF mode at a similar speed range


1.3.42. TSha1

TSha1 = object(TObject)

Implements SHA-1 hashing
- this algorithm has known weaknesses, so should not be considered as cryptographic secure, but is available for other purposes
- we defined a record instead of a class, to allow stack allocation and thread-safe reuse of one initialized instance, e.g. for THmacSha1
- see TSynHasher if you expect to support more than one algorithm at runtime


function Final(NoInit: boolean = false): TSha1Digest; overload;

Finalize and compute the resulting SHA-1 hash Digest of all data affected to Update() method
- will also call Init to reset all internal temporary context, for safety


procedure Final(out Digest: TSha1Digest; NoInit: boolean = false); overload;

Finalize and compute the resulting SHA-1 hash Digest of all data affected to Update() method
- will also call Init to reset all internal temporary context, for safety


procedure Full(Buffer: pointer; Len: integer; out Digest: TSha1Digest);

One method to rule them all
- call Init, then Update(), then Final()


procedure Init;

Initialize SHA-1 context for hashing


procedure Update(Buffer: pointer; Len: integer); overload;

Update the SHA-1 context with some data


procedure Update(const Buffer: RawByteString); overload;

Update the SHA-1 context with some data


1.3.43. THmacSha1

THmacSha1 = object(TObject)

Compute the HMAC message authentication code using SHA-1 as hash function
- you may use HmacSha1() overloaded functions for one-step process
- we defined a record instead of a class, to allow stack allocation and thread-safe reuse of one initialized instance via Compute(), e.g. for fast PBKDF2


procedure Compute(msg: pointer; msglen: integer; out result: TSha1Digest);

Computes the HMAC of the supplied message according to the key
- expects a previous call on Init() to setup the shared key
- similar to a single Update(msg,msglen) followed by Done, but re-usable
- this method is thread-safe on any shared THmacSha1 instance


procedure Done(out result: RawUtf8; NoInit: boolean = false); overload;

Computes the HMAC of all supplied message according to the key


procedure Done(out result: TSha1Digest; NoInit: boolean = false); overload;

Computes the HMAC of all supplied message according to the key


procedure Init(key: pointer; keylen: integer);

Prepare the HMAC authentication with the supplied key
- content of this record is stateless, so you can prepare a HMAC for a key using Init, then copy this THmacSha1 instance to a local variable, and use this local thread-safe copy for actual HMAC computing


procedure Update(msg: pointer; msglen: integer);

Call this method for each continuous message block
- iterate over all message blocks, then call Done to retrieve the HMAC


1.3.44. THmacSha256

THmacSha256 = object(TObject)

Compute the HMAC message authentication code using SHA-256 as hash function
- you may use HmacSha256() overloaded functions for one-step process
- we defined a record instead of a class, to allow stack allocation and thread-safe reuse of one initialized instance via Compute(), e.g. for fast PBKDF2


procedure Compute(msg: pointer; msglen: integer; out result: TSha256Digest);

Computes the HMAC of the supplied message according to the key
- expects a previous call on Init() to setup the shared key
- similar to a single Update(msg,msglen) followed by Done, but re-usable
- this method is thread-safe on any shared THmacSha256 instance


procedure Done(out result: TSha256Digest; NoInit: boolean = false); overload;

Computes the HMAC of all supplied message according to the key


procedure Done(out result: RawUtf8; NoInit: boolean = false); overload;

Computes the HMAC of all supplied message according to the key


procedure Init(key: pointer; keylen: integer);

Prepare the HMAC authentication with the supplied key
- content of this record is stateless, so you can prepare a HMAC for a key using Init, then copy this THmacSha256 instance to a local variable, and use this local thread-safe copy for actual HMAC computing


procedure Update(const msg: RawByteString); overload;

Call this method for each continuous message block
- iterate over all message blocks, then call Done to retrieve the HMAC


procedure Update(msg: pointer; msglen: integer); overload;

Call this method for each continuous message block
- iterate over all message blocks, then call Done to retrieve the HMAC


procedure Update(const msg: THash128); overload;

Call this method for each continuous message block
- iterate over all message blocks, then call Done to retrieve the HMAC


procedure Update(const msg: THash256); overload;

Call this method for each continuous message block
- iterate over all message blocks, then call Done to retrieve the HMAC


1.3.45. THmacSha384

THmacSha384 = object(TObject)

Compute the HMAC message authentication code using SHA-384 as hash function
- you may use HmacSha384() overloaded functions for one-step process
- we defined a record instead of a class, to allow stack allocation and thread-safe reuse of one initialized instance via Compute(), e.g. for fast PBKDF2


procedure Compute(msg: pointer; msglen: integer; out result: TSha384Digest);

Computes the HMAC of the supplied message according to the key
- expects a previous call on Init() to setup the shared key
- similar to a single Update(msg,msglen) followed by Done, but re-usable
- this method is thread-safe on any shared THmacSha384 instance


procedure Done(out result: RawUtf8; NoInit: boolean = false); overload;

Computes the HMAC of all supplied message according to the key


procedure Done(out result: TSha384Digest; NoInit: boolean = false); overload;

Computes the HMAC of all supplied message according to the key


procedure Init(key: pointer; keylen: integer);

Prepare the HMAC authentication with the supplied key
- content of this record is stateless, so you can prepare a HMAC for a key using Init, then copy this THmacSha384 instance to a local variable, and use this local thread-safe copy for actual HMAC computing


procedure Update(msg: pointer; msglen: integer);

Call this method for each continuous message block
- iterate over all message blocks, then call Done to retrieve the HMAC


1.3.46. THmacSha512

THmacSha512 = object(TObject)

Compute the HMAC message authentication code using SHA-512 as hash function
- you may use HmacSha512() overloaded functions for one-step process
- we defined a record instead of a class, to allow stack allocation and thread-safe reuse of one initialized instance via Compute(), e.g. for fast PBKDF2


procedure Compute(msg: pointer; msglen: integer; out result: TSha512Digest);

Computes the HMAC of the supplied message according to the key
- expects a previous call on Init() to setup the shared key
- similar to a single Update(msg,msglen) followed by Done, but re-usable
- this method is thread-safe on any shared THmacSha512 instance


procedure Done(out result: RawUtf8; NoInit: boolean = false); overload;

Computes the HMAC of all supplied message according to the key


procedure Done(out result: TSha512Digest; NoInit: boolean = false); overload;

Computes the HMAC of all supplied message according to the key


procedure Init(key: pointer; keylen: integer);

Prepare the HMAC authentication with the supplied key
- content of this record is stateless, so you can prepare a HMAC for a key using Init, then copy this THmacSha512 instance to a local variable, and use this local thread-safe copy for actual HMAC computing


procedure Update(msg: pointer; msglen: integer);

Call this method for each continuous message block
- iterate over all message blocks, then call Done to retrieve the HMAC


1.3.47. THmacCrc32c

THmacCrc32c = object(TObject)

Compute the HMAC message authentication code using crc32c as hash function
- HMAC over a non cryptographic hash function like crc32c is known to be a safe enough MAC, if the supplied key comes e.g. from cryptographic HmacSha256
- SSE 4.2 will let MAC be computed at 13 GB/s on a Core i7 / x86_64
- you may use HmacCrc32c() overloaded functions for one-step process
- we defined a record instead of a class, to allow stack allocation and thread-safe reuse of one initialized instance via Compute()


function Compute(msg: pointer; msglen: integer): cardinal;

Computes the HMAC of the supplied message according to the key
- expects a previous call on Init() to setup the shared key
- similar to a single Update(msg,msglen) followed by Done, but re-usable
- this method is thread-safe


function Done(NoInit: boolean = false): cardinal;

Computes the HMAC of all supplied message according to the key


procedure Init(key: pointer; keylen: integer); overload;

Prepare the HMAC authentication with the supplied key
- consider using Compute to re-use a prepared HMAC instance


procedure Init(const key: RawByteString); overload;

Prepare the HMAC authentication with the supplied key
- consider using Compute to re-use a prepared HMAC instance


procedure Update(msg: pointer; msglen: integer); overload;

Call this method for each continuous message block
- iterate over all message blocks, then call Done to retrieve the HMAC


procedure Update(const msg: RawByteString); overload;

Call this method for each continuous message block
- iterate over all message blocks, then call Done to retrieve the HMAC


1.3.48. TAesFullHeader

TAesFullHeader = object(TObject)

Internal header for storing our AES data with salt and CRC
- memory size matches an TAesBlock on purpose, for direct encryption
- TAesFull uses unsafe direct AES-ECB chain mode, so is considered deprecated


HeaderCheck: cardinal;

CRC from header


OriginalLen: cardinal;

Len before compression (if any)


SomeSalt: cardinal;

Random Salt for better encryption


SourceLen: cardinal;

Len before AES encoding


function Calc(const Key; KeySize: cardinal): cardinal;

Computes the Key checksum, using Adler32 algorithm


1.3.49. TAesFull

TAesFull = object(TObject)

AES and XOR encryption object for easy direct memory or stream access
- calls internally TAes objet methods, and handle memory and streams for best speed
- a TAesFullHeader is encrypted at the begining, allowing fast Key validation, but the resulting stream is not compatible with raw TAes object
- will use unsafe direct AES-ECB chain mode, so is considered deprecated


Head: TAesFullHeader;

Header, stored at the beginning of struct -> 16-byte aligned


outStreamCreated: TMemoryStream;

This memory stream is used in case of EncodeDecode(outStream=bOut=nil) method call


function EncodeDecode(const Key; KeySize, inLen: cardinal; Encrypt: boolean; inStream, outStream: TStream; bIn, bOut: pointer; OriginalLen: cardinal = 0): integer;

Main method of AES or XOR cypher/uncypher
- return out size, -1 if error on decoding (Key not correct)
- valid KeySize: 0=nothing, 32=xor, 128,192,256=AES
- if outStream is TMemoryStream -> auto-reserve space (no Realloc:)
- for normal usage, you just have to Assign one In and one Out
- if outStream AND bOut are both nil, an outStream is created via TMemoryStream.Create
- if Encrypt -> OriginalLen can be used to store unCompressed Len


1.3.50. TAesWriteStream

TAesWriteStream = class(TStream)

AES encryption stream (deprecated)
- encrypt the Data on the fly, in a compatible way with AES() - last bytes are coded with XOR (not compatible with TAesFull format)
- not optimized for small blocks -> ok if used AFTER TBZCompressor/TZipCompressor
- warning: Write() will crypt Buffer memory in place -> use AFTER T*Compressor
- will use unsafe direct AES-ECB chain mode, so is considered deprecated: consider TAesPkcs7Writer and TAesPkcs7Reader instead


DestSize: cardinal;

CRC from uncrypted compressed data - for Key check


constructor Create(outStream: TStream; const Key; KeySize: cardinal);

If KeySize=0 initialize the AES encryption stream for an output stream (e.g. a TMemoryStream or a TFileStreamEx)


destructor Destroy; override;

Finalize the AES encryption stream
- internally call the Finish method


function Read(var Buffer; Count: Longint): Longint; override;

Read some data is not allowed -> this method will raise an exception on call


function Seek(Offset: Longint; Origin: Word): Longint; override;

Read some data is not allowed -> this method will raise an exception on call


function Write(const Buffer; Count: Longint): Longint; override;

Append some data to the outStream, after encryption


procedure Finish;

Write pending data
- should always be called before closing the outStream (some data may still be in the internal buffers)


1.4. Types implemented in the mormot.crypt.core unit

1.4.1. PAes

PAes = ^TAes;

Points to a TAes encryption/decryption instance


1.4.2. PHmacCrc32c

PHmacCrc32c = ^THmacCrc32c;

Points to HMAC message authentication code using crc32c as hash function


1.4.3. PHmacSha1

PHmacSha1 = ^THmacSha1;

Points to a HMAC message authentication context using SHA-1


1.4.4. PHmacSha256

PHmacSha256 = ^THmacSha256;

Points to a HMAC message authentication context using SHA-256


1.4.5. PHmacSha384

PHmacSha384 = ^THmacSha384;

Points to a HMAC message authentication context using SHA-384


1.4.6. PHmacSha512

PHmacSha512 = ^THmacSha512;

Points to a HMAC message authentication context using SHA-512


1.4.7. PSha1

PSha1 = ^TSha1;

Points to SHA-1 hashing instance


1.4.8. PSha256

PSha256 = ^TSha256;

Points to SHA-256 hashing instance


1.4.9. PSha3

PSha3 = ^TSha3;

Points to SHA-3 hashing instance


1.4.10. PSha384

PSha384 = ^TSha384;

Points to SHA-384 hashing instance


1.4.11. PSha512

PSha512 = ^TSha512;

Points to SHA-512 hashing instance


1.4.12. PSha512_256

PSha512_256= ^TSha512_256;

Points to SHA-512/256 hashing instance


1.4.13. Short32

Short32 = string[32];

32-characters ASCII string, e.g. as returned by AesBlockToShortString()


1.4.14. TAesAbstractClass

TAesAbstractClass = class of TAesAbstract;

Class-reference type (metaclass) of an AES cypher/uncypher


1.4.15. TAesBlock

TAesBlock = THash128;

128-bit memory block for AES data cypher/uncypher


1.4.16. TAesCtrAny

TAesCtrAny = TAesC64;

BREAKING CHANGE since mORMOt 1.18: our 64-bit CTR was not standard, so SynCrypto.pas' TAESCTR class was wrongly named and TAesCtr in this unit refers to the standard NIST implementation (also much faster on x86_64)
- so you need to rename any mORMot 1 TAESCTR class into TAesC64


1.4.17. TAesGcmAbstractClass

TAesGcmAbstractClass = class of TAesGcmAbstract;

Meta-class of TAesGcmAbstract types


1.4.18. TAesKey

TAesKey = THash256;

256-bit memory block for maximum AES key storage


1.4.19. TAesMode

TAesMode = ( mEcb, mCbc, mCfb, mOfb, mC64, mCtr, mCfc, mOfc, mCtc, mGcm );

The AES chaining modes implemented by this unit
- mEcb is unsafe and should not be used as such
- mC64 is a non standard AES-CTR mode with 64-bit CRC - use mCtr for NIST
- mCfc, mOfc and mCtc are non standard AEAD modes with 256-bit crc32c
- matching algo names are e.g. 'aes-128-cfb', 'aes-256-ctc' or 'aes-256-gcm'


1.4.20. TAesPrngClass

TAesPrngClass = class of TAesPrngAbstract;

Meta-class for our CSPRNG implementations


1.4.21. TAesPrngGetEntropySource

TAesPrngGetEntropySource = ( gesSystemAndUser, gesSystemOnly, gesSystemOnlyMayBlock, gesUserOnly );

Which sources uses TAesPrng.GetEntropy() to gather its entropy
- gesSystemAndUser uses OS and mORMot random sources
- gesSystemOnly and gesSystemOnlyMayBlock use OS random sources, the later may block on some systems (so keep it small)
- gesUserOnly uses mORMot random sources, and 512-bit of OS source once


1.4.22. TAesPrngSystem

TAesPrngSystem = TSystemPrng;

Most Operating System PRNG are very unlikely AES based - confusing


1.4.23. TMd5Digest

TMd5Digest = THash128;

128-bit memory block for MD5 hash digest storage


1.4.24. TSha1Digest

TSha1Digest = THash160;

160 bits memory block for SHA-1 hash digest storage


1.4.25. TSha256Digest

TSha256Digest = THash256;

256-bit (32 bytes) memory block for SHA-256 hash digest storage


1.4.26. TSha384Digest

TSha384Digest = THash384;

384 bits (64 bytes) memory block for SHA-384 hash digest storage


1.4.27. TSha3Algo

TSha3Algo = ( SHA3_224, SHA3_256, SHA3_384, SHA3_512, SHAKE_128, SHAKE_256 );

SHA-3 instances, as defined by NIST Standard for Keccak sponge construction
- SHA3_224..SHA3_512 output 224, 256, 384 and 512 bits of cryptographic hash
- SHAKE_128 and SHAKE_256 implements a XOF/cipher generator


1.4.28. TSha512Digest

TSha512Digest = THash512;

512 bits (64 bytes) memory block for SHA-512 hash digest storage


1.5. Constants implemented in the mormot.crypt.core unit

1.5.1. AesBlockMod

AesBlockMod = 15;

Bit mask for fast modulo of AES block size


1.5.2. AesBlockShift

AesBlockShift = 4;

Power of two for a standard AES block size during cypher/uncypher
- to be used as 1 shl AesBlockShift or 1 shr AesBlockShift for fast div/mod


1.5.3. AES_AEAD

AES_AEAD = [mCfc, mOfc, mCtc, mGcm];

The AES chaining modes which supports AEAD process


1.5.4. AES_CONTEXT_SIZE

AES_CONTEXT_SIZE = 276 + SizeOf(pointer) + SizeOf(pointer) ;

Hide all AES Context complex code


1.5.5. AES_INTERNAL

AES_INTERNAL = [mC64, mCfc, mOfc, mCtc];

Our non standard chaining modes, which do not exist e.g. on OpenSSL


1.5.6. AES_PKCS7WRITER

AES_PKCS7WRITER = [mCbc .. mGcm] - AES_AEAD;

The AES chaining modes supported by TAesPkcs7Writer/TAesPkcs7Reader
- ECB is unsafe and has no IV, and AEAD modes are out of context because we don't handle the additional AEAD information yet


1.5.7. GMAC_SIZE

GMAC_SIZE = 16;

The AES-GCM GMAC size (in bytes)


1.5.8. SHA3_CONTEXT_SIZE

SHA3_CONTEXT_SIZE = 410;

Hide TSha3Context complex code by storing the Keccak/SHA-3 Sponge as buffer


1.5.9. SHA_CONTEXT_SIZE

SHA_CONTEXT_SIZE = 108;

Hide TSha1/TSha256 complex code by storing the SHA-1/SHA-2 context as buffer


1.5.10. TAesInternal

TAesInternal: TAesAbstractClasses = ( TAesEcb, TAesCbc, TAesCfb, TAesOfb, TAesC64, TAesCtr, TAesCfc, TAesOfc, TAesCtc, TAesGcm);

The internal AES implementation classes available on the system, per mode
- mormot.crypt.openssl won't override those classes


1.5.11. _xasmdivn

_xasmdivn = SizeOf(pointer) * 16;

256/512 bits per call


1.5.12. _xasmmodn

_xasmmodn = SizeOf(pointer) * 16;

512/1024 bits per call


1.5.13. _xasmmuladdn

_xasmmuladdn = SizeOf(pointer) * 8;

256/512 bits per call


1.5.14. _xasmmuln

_xasmmuln = SizeOf(pointer) * 8;

512/1024 bits per call


1.5.15. _xasmsubn

_xasmsubn = SizeOf(pointer) * 16;

512/1024 bits per call


1.6. Functions or procedures implemented in the mormot.crypt.core unit

Functions or proceduresDescription
Adler32AsmFast Adler32 implementation
Adler32PasSimple Adler32 implementation
AESDirect Encrypt/Decrypt of data using the TAes class (deprecated)
AESDirect Encrypt/Decrypt of data using the TAes class (deprecated)
AESDirect Encrypt/Decrypt of data using the TAes class (deprecated)
AESDirect Encrypt/Decrypt of data using the TAes class (deprecated)
AesAlgoNameDecodeOpenSSL-like Cipher name decoding into a mormot.crypt.core TAesAbstract class
AesAlgoNameDecodeOpenSSL-like Cipher name decoding into mormot.crypt.core AES engines
AesAlgoNameEncodeOpenSSL-like Cipher name encoding of mormot.crypt.core AES engines
AesAlgoNameEncodeOpenSSL-like Cipher name encoding of mormot.crypt.core AES engines
AesBlockToShortStringCompute the hexadecial representation of an AES 16-byte block
AesBlockToShortStringCompute the hexadecial representation of an AES 16-byte block
AesBlockToStringCompute the hexadecial representation of an AES 16-byte block
AESFullAES and XOR encryption using the TAesFull format (deprecated)
AESFullAES and XOR encryption using the TAesFull format (deprecated)
AESFullKeyOKAES and XOR decryption check using the TAesFull format (deprecated)
AesIvUpdatedCreateCreate one AES instance which updates its IV between Encrypt/Decrypt calls
AesPkcs7Cypher/decypher any buffer using AES and PKCS7 padding, from a key buffer
AesPkcs7Cypher/decypher any buffer using AES and PKCS7 padding, from a key buffer
AesPkcs7FileCypher/decypher any file using AES and PKCS7 padding, from a password
AesPkcs7FileCypher/decypher any file using AES and PKCS7 padding, from a key buffer
AESSHA256AES encryption using the TAes format with a supplied password (deprecated)
AESSHA256AES encryption using the TAes format with a supplied password (deprecated)
AESSHA256AES encryption using the TAes format with a supplied password (deprecated)
AESSHA256FullAES encryption using the TAesFull format with a supplied password (deprecated)
AesTablesTestUsed for paranoid safety by test.core.crypto.pas
AFDiffusionLow-level anti-forensic diffusion of a memory buffer using SHA-256
bswap160Little endian fast conversion
bswap256Little endian fast conversion
CompressShaAesEncrypt data content using the DEPRECATED AES-256/CFB algorithm, after SynLZ
CompressShaAesSetKeySet an text-based encryption key for DEPRECATED CompressShaAes() global function
CryptDataForCurrentUserProtect some data via AES-256-CFB and a secret known by the current user only
Hash128ToDoubleLow-level function able to derivate a 0..1 64-bit floating-point from 128-bit of data
Hash128ToExtLow-level function able to derivate a 0..1 floating-point from 128-bit of data
Hash128ToSingleLow-level function able to derivate a 0..1 32-bit floating-point from 128-bit of data
HmacCrc256cCompute the HMAC message authentication code using crc256c as hash function
HmacCrc256cCompute the HMAC message authentication code using crc256c as hash function
HmacCrc256cCompute the HMAC message authentication code using crc256c as hash function
HmacCrc32cCompute the HMAC message authentication code using crc32c as hash function
HmacCrc32cCompute the HMAC message authentication code using crc32c as hash function
HmacCrc32cCompute the HMAC message authentication code using crc32c as hash function
HmacSha1Compute the HMAC message authentication code using SHA-1 as hash function
HmacSha1Compute the HMAC message authentication code using SHA-1 as hash function
HmacSha1Compute the HMAC message authentication code using SHA-1 as hash function
HmacSha256Compute the HMAC message authentication code using SHA-256 as hash function
HmacSha256Compute the HMAC message authentication code using SHA-256 as hash function
HmacSha256Compute the HMAC message authentication code using SHA-256 as hash function
HmacSha384Compute the HMAC message authentication code using SHA-384 as hash function
HmacSha384Compute the HMAC message authentication code using SHA-384 as hash function
HmacSha384Compute the HMAC message authentication code using SHA-384 as hash function
HmacSha512Compute the HMAC message authentication code using SHA-512 as hash function
HmacSha512Compute the HMAC message authentication code using SHA-512 as hash function
HmacSha512Compute the HMAC message authentication code using SHA-512 as hash function
HTDigestCompute the HTDigest for a user and a realm, according to a supplied password
Md4Direct MD4 hash calculation of some data (string-encoded)
Md4BufDirect MD4 hash calculation of some data
Md5Direct MD5 hash calculation of some data (string-encoded)
Md5BufDirect MD5 hash calculation of some data
Md5DigestToStringCompute the lowercase hexadecimal representation of a MD5 digest
Md5StringToDigestCompute the MD5 digest from its hexadecimal representation
Pbkdf2HmacSha1Compute the PBKDF2 derivation of a password using HMAC over SHA-1
Pbkdf2HmacSha256Compute the PBKDF2 derivations of a password using HMAC over SHA-256, into several 256-bit items, so can be used to return any size of output key
Pbkdf2HmacSha256Compute the PBKDF2 derivation of a password using HMAC over SHA-256
Pbkdf2HmacSha384Compute the PBKDF2 derivation of a password using HMAC over SHA-384
Pbkdf2HmacSha512Compute the PBKDF2 derivation of a password using HMAC over SHA-512
Pbkdf2Sha3Safe key derivation using iterated SHA-3 hashing
Pbkdf2Sha3CryptEncryption/decryption of any data using iterated SHA-3 hashing key derivation
RawMd5CompressEntry point of the raw MD5 transform function - for low-level use
RawSha1CompressEntry point of the raw SHA-1 transform function - for low-level use
RawSha256CompressEntry point of the raw SHA-256 transform function - for low-level use
RawSha512CompressEntry point of the raw SHA-512 transform function - for low-level use
Sha1Direct SHA-1 hash calculation of some data (string-encoded)
Sha1DigestToStringCompute the hexadecimal representation of a SHA-1 digest
Sha1StringToDigestCompute the SHA-1 digest from its hexadecimal representation
Sha256Direct SHA-256 hash calculation of some data (string-encoded)
Sha256Direct SHA-256 hash calculation of some binary data
Sha256DigestDirect SHA-256 hash calculation of some binary data
Sha256DigestDirect SHA-256 hash calculation of some binary data
Sha256DigestToStringCompute the hexadecimal representation of a SHA-256 digest
Sha256StringToDigestCompute the SHA-256 digest from its hexadecimal representation
Sha256WeakSHA-256 hash calculation with padding if shorter than 255 bytes
Sha3Direct SHA-3 hash calculation of some data (string-encoded)
Sha3Direct SHA-3 hash calculation of some binary buffer
Sha384Direct SHA-384 hash calculation of some data (string-encoded)
Sha384DigestToStringCompute the hexadecimal representation of a SHA-384 digest
Sha512Direct SHA-512 hash calculation of some data (string-encoded)
Sha512DigestToStringCompute the hexadecimal representation of a SHA-512 digest
Sha512_256Direct SHA-512/256 hash calculation of some data (string-encoded)
XorBlockSimple XOR encryption according to Cod - not Compression or Stream compatible
XorBlock16Apply the B = A XOR C operation to the supplied binary buffers of 16 bytes
XorBlock16Apply the A = A XOR B operation to the supplied binary buffers of 16 bytes
XorConstWeak XOR Cypher changing by Count value
XorOffsetSimple XOR Cypher using Index (=Position in Dest Stream)
_add256Optimized 256-bit addition (with Intel/AMD asm) - used by ecc256r1
_bswap256Move and change endianness of a 256-bit value
_cmp256Returns sign of 256-bit Left - Right comparison - used by ecc256r1
_dec256Optimized 256-bit substraction (with Intel/AMD asm) - used by ecc256r1
_inc128Optimized 128-bit addition (with Intel/AMD asm) - used by ecc256r1
_inc256Optimized 256-bit addition (with Intel/AMD asm) - used by ecc256r1
_inc64Optimized 64-bit addition (with Intel/AMD asm) - used by ecc256r1
_lshiftComputes Output = Input shl Shift, returning carry, of a 256-bit value
_lshift1Left shift of 1 bit of a 256-bit value - used by ecc256r1
_mult128128-to-256-bit multiplication (with Intel/AMD asm) - used by ecc256r1
_mult256256-to-512-bit multiplication (with x86_64 asm) - used by ecc256r1
_numbits256Compute the highest bit set of a 256-bit value - used by ecc256r1
_rshift1Right shift of 1 bit of a 256-bit value - used by ecc256r1
_square256256-to-512-bit ^2 computation - used by ecc256r1
_sub256Optimized 256-bit substraction (with Intel/AMD asm) - used by ecc256r1
_xasmaddAdd of two TBigInt 512/1024-bit buffers - as used by mormot.crypt.rsa
_xasmdivDiv-by-integer of a TBigInt 512/1024-bit buffer - as used by mormot.crypt.rsa
_xasmmodMod-by-integer of a TBigInt 512/1024-bit buffer - as used by mormot.crypt.rsa
_xasmmulMul-by-integer of a TBigInt 256/512-bit buffer - as used by mormot.crypt.rsa
_xasmmuladdMul-and-add of a TBigInt 256/512-bit buffer - as used by mormot.crypt.rsa
_xasmsubSub of two TBigInt 512/1024-bit buffers - as used by mormot.crypt.rsa

1.6.1. Adler32Asm

function Adler32Asm(Adler: cardinal; p: pointer; Count: integer): cardinal;

Fast Adler32 implementation
- 16-bytes-chunck unrolled asm version on i386
- note: the adler32() included in libdeflate is much faster than this


1.6.2. Adler32Pas

function Adler32Pas(Adler: cardinal; p: pointer; Count: integer): cardinal;

Simple Adler32 implementation
- a bit slower than Adler32Asm() version below, but shorter code size


1.6.3. AES

function AES(const Key; KeySize: cardinal; buffer: pointer; Len: cardinal; Stream: TStream; Encrypt: boolean): boolean; overload; deprecated;

Direct Encrypt/Decrypt of data using the TAes class (deprecated)
- last bytes (not part of 16 bytes blocks) are not crypted by AES, but with XOR
- will use unsafe direct AES-ECB chain mode, so is marked as deprecated


1.6.4. AES

procedure AES(const Key; KeySize: cardinal; buffer: pointer; Len: integer; Encrypt: boolean); overload; deprecated;

Direct Encrypt/Decrypt of data using the TAes class (deprecated)
- last bytes (not part of 16 bytes blocks) are not crypted by AES, but with XOR
- will use unsafe direct AES-ECB chain mode, so is marked as deprecated


1.6.5. AES

procedure AES(const Key; KeySize: cardinal; bIn, bOut: pointer; Len: integer; Encrypt: boolean); overload; deprecated;

Direct Encrypt/Decrypt of data using the TAes class (deprecated)
- last bytes (not part of 16 bytes blocks) are not crypted by AES, but with XOR
- will use unsafe direct AES-ECB chain mode, so is marked as deprecated


1.6.6. AES

function AES(const Key; KeySize: cardinal; const s: RawByteString; Encrypt: boolean): RawByteString; overload; deprecated;

Direct Encrypt/Decrypt of data using the TAes class (deprecated)
- last bytes (not part of 16 bytes blocks) are not crypted by AES, but with XOR
- will use unsafe direct AES-ECB chain mode, so is marked as deprecated


1.6.7. AesAlgoNameDecode

function AesAlgoNameDecode(AesAlgoName: PUtf8Char; out Mode: TAesMode; out KeyBits: integer): boolean; overload;

OpenSSL-like Cipher name decoding into mormot.crypt.core AES engines
- input AesAlgoName length should be already checked as 11
- decode e.g. 'aes-128-cfb' into Mode=mCfb and KeyBits=128


1.6.8. AesAlgoNameDecode

function AesAlgoNameDecode(const AesAlgoName: RawUtf8; out KeyBits: integer): TAesAbstractClass; overload;

OpenSSL-like Cipher name decoding into a mormot.crypt.core TAesAbstract class
- decode e.g. 'aes-256-cfb' into TAesFast[mCfb] and KeyBits=256


1.6.9. AesAlgoNameEncode

function AesAlgoNameEncode(Mode: TAesMode; KeyBits: integer): RawUtf8; overload;

OpenSSL-like Cipher name encoding of mormot.crypt.core AES engines
- return e.g. 'aes-128-cfb' or 'aes-256-gcm'
- our mC64, mCfc, mOfc, mCtc custom algorithms use non-standard trailing 'c64', 'cfc', 'ofc' and 'ctc' mode names e.g. as 'aes-256-cfc'


1.6.10. AesAlgoNameEncode

procedure AesAlgoNameEncode(Mode: TAesMode; KeyBits: integer; out Result: TShort15); overload;

OpenSSL-like Cipher name encoding of mormot.crypt.core AES engines
- returned TShort15 is #0 ended so @Result[1] can be transtyped to a PUtf8Char


1.6.11. AesBlockToShortString

procedure AesBlockToShortString(const block: TAesBlock; out result: short32); overload;

Compute the hexadecial representation of an AES 16-byte block
- fill a stack-allocated short string


1.6.12. AesBlockToShortString

function AesBlockToShortString(const block: TAesBlock): short32; overload;

Compute the hexadecial representation of an AES 16-byte block
- returns a stack-allocated short string


1.6.13. AesBlockToString

function AesBlockToString(const block: TAesBlock): RawUtf8;

Compute the hexadecial representation of an AES 16-byte block


1.6.14. AESFull

function AESFull(const Key; KeySize: cardinal; bIn: pointer; Len: integer; outStream: TStream; Encrypt: boolean; OriginalLen: cardinal = 0): boolean; overload; deprecated;

AES and XOR encryption using the TAesFull format (deprecated)
- outStream will be larger/smaller than Len (full AES encrypted)
- if KeySize is not in [128,192,256], will use a naive simple Xor Cypher
- returns true if OK
- will use unsafe direct AES-ECB chain mode, so is marked as deprecated


1.6.15. AESFull

function AESFull(const Key; KeySize: cardinal; bIn, bOut: pointer; Len: integer; Encrypt: boolean; OriginalLen: cardinal = 0): integer; overload; deprecated;

AES and XOR encryption using the TAesFull format (deprecated)
- bOut must be at least bIn+32/Encrypt bIn-16/Decrypt
- if KeySize is not in [128,192,256], will use a naive simple Xor Cypher
- returns outLength, -1 if error
- will use unsafe direct AES-ECB chain mode, so is marked as deprecated


1.6.16. AESFullKeyOK

function AESFullKeyOK(const Key; KeySize: cardinal; buff: pointer): boolean; deprecated;

AES and XOR decryption check using the TAesFull format (deprecated)
- return true if the beginning of buff contains some data AESFull-encrypted with this Key
- if not KeySize in [128,192,256], will always return true
- will use unsafe direct AES-ECB chain mode, so is marked as deprecated


1.6.17. AesIvUpdatedCreate

function AesIvUpdatedCreate(aesMode: TAesMode; const key; keySizeBits: cardinal): TAesAbstract;

Create one AES instance which updates its IV between Encrypt/Decrypt calls
- will return either TAesFast[aesMode] or TAesInternal[aesMode] as fallback


1.6.18. AesPkcs7

function AesPkcs7(const src: RawByteString; encrypt: boolean; const key; keySizeBits: cardinal; aesMode: TAesMode = mCtr; IV: PAesBlock = nil): RawByteString; overload;

Cypher/decypher any buffer using AES and PKCS7 padding, from a key buffer
- on decryption, returns '' in case of invalid input


1.6.19. AesPkcs7

function AesPkcs7(const src: RawByteString; encrypt: boolean; const password: RawUtf8; const salt: RawByteString = ''; rounds: cardinal = 1000; aesMode: TAesMode = mCtr): RawByteString; overload;

Cypher/decypher any buffer using AES and PKCS7 padding, from a key buffer
- will derivate the password using PBKDF2 over HMAC-SHA256, using lower 128-bit as AES-CTR-128 key, and the upper 128-bit as IV


1.6.20. AesPkcs7File

function AesPkcs7File(const src, dst: TFileName; encrypt: boolean; const key; keySizeBits: cardinal; aesMode: TAesMode = mCtr; IV: PAesBlock = nil): Int64; overload;

Cypher/decypher any file using AES and PKCS7 padding, from a key buffer
- just a wrapper around TAesPkcs7Writer/TAesPkcs7Reader and TFileStreamEx
- by default, a trailing random IV is expected, unless IV is supplied
- if src=dst a temporary .partial file is created, then will replace src
- raise an exception on error (e.g. missing or invalid input file)
- returns the number of bytes written to dst file


1.6.21. AesPkcs7File

function AesPkcs7File(const src, dst: TFileName; encrypt: boolean; const password: RawUtf8; const salt: RawByteString = ''; rounds: cardinal = 1000; aesMode: TAesMode = mCtr): Int64; overload;

Cypher/decypher any file using AES and PKCS7 padding, from a password
- just a wrapper around TAesPkcs7Writer/TAesPkcs7Reader and TFileStreamEx
- will derivate the password using PBKDF2 over HMAC-SHA256, using lower 128-bit as AES-CTR-128 key, and the upper 128-bit as IV
- returns the number of bytes written to dst file


1.6.22. AESSHA256

function AESSHA256(const s, Password: RawByteString; Encrypt: boolean): RawByteString; overload; deprecated;

AES encryption using the TAes format with a supplied password (deprecated)
- last bytes (not part of 16 bytes blocks) are not crypted by AES, but with XOR
- will use unsafe direct AES-ECB chain mode and weak direct SHA-256 (HMAC-256 is preferred), so is marked as deprecated


1.6.23. AESSHA256

procedure AESSHA256(bIn, bOut: pointer; Len: integer; const Password: RawByteString; Encrypt: boolean); overload; deprecated;

AES encryption using the TAes format with a supplied password (deprecated)
- last bytes (not part of 16 bytes blocks) are not crypted by AES, but with XOR
- will use unsafe direct AES-ECB chain mode and weak direct SHA-256 (HMAC-256 is preferred), so is marked as deprecated


1.6.24. AESSHA256

procedure AESSHA256(Buffer: pointer; Len: integer; const Password: RawByteString; Encrypt: boolean); overload; deprecated;

AES encryption using the TAes format with a supplied password (deprecated)
- last bytes (not part of 16 bytes blocks) are not crypted by AES, but with XOR
- will use unsafe direct AES-ECB chain mode and weak direct SHA-256 (HMAC-256 is preferred), so is marked as deprecated


1.6.25. AESSHA256Full

procedure AESSHA256Full(bIn: pointer; Len: integer; outStream: TStream; const Password: RawByteString; Encrypt: boolean); overload; deprecated;

AES encryption using the TAesFull format with a supplied password (deprecated)
- outStream will be larger/smaller than Len: this is a full AES version with a triming TAesFullHeader at the beginning
- will use unsafe direct AES-ECB chain mode and weak direct SHA-256 (HMAC-256 is preferred), so is marked as deprecated


1.6.26. AesTablesTest

function AesTablesTest: boolean;

Used for paranoid safety by test.core.crypto.pas


1.6.27. AFDiffusion

procedure AFDiffusion(buf, rnd: pointer; size: cardinal);

Low-level anti-forensic diffusion of a memory buffer using SHA-256
- as used by TAesPrng.AFSplit and TAesPrng.AFUnSplit


1.6.28. bswap160

procedure bswap160(s, d: PIntegerArray);

Little endian fast conversion
- 160 bits = 5 integers
- use fast bswap asm in x86/x64 mode


1.6.29. bswap256

procedure bswap256(s, d: PIntegerArray);

Little endian fast conversion
- 256-bit = 8 integers
- use fast bswap asm in x86/x64 mode


1.6.30. CompressShaAes

function CompressShaAes(var Data: RawByteString; Compress: boolean): RawUtf8;

Encrypt data content using the DEPRECATED AES-256/CFB algorithm, after SynLZ
- DO NOT USE: since HTTP compression is optional, this scheme is not safe
- as expected by THttpSocket.RegisterCompress()
- will return 'synshaaes' as ACCEPT-ENCODING: header parameter
- will use global CompressShaAesKey / CompressShaAesClass variables to be set according to the expected algorithm and Key e.g. via a call to CompressShaAesSetKey()
- if you want to change the chaining mode, you can customize the global CompressShaAesClass variable to the expected TAes* class name
- will store a hash of both cyphered and clear stream: if the data is corrupted during transmission, will instantly return ''


1.6.31. CompressShaAesSetKey

procedure CompressShaAesSetKey(const Key: RawByteString; AesClass: TAesAbstractClass = nil);

Set an text-based encryption key for DEPRECATED CompressShaAes() global function
- DO NOT USE: since HTTP compression is optional, this scheme is not safe
- will compute the key via Sha256Weak() and set CompressShaAesKey
- the key is global to the whole process


1.6.32. CryptDataForCurrentUser

function CryptDataForCurrentUser(const Data, AppSecret: RawByteString; Encrypt: boolean): RawByteString;

Protect some data via AES-256-CFB and a secret known by the current user only
- the application can specify a secret salt text, which should reflect the current execution context, to ensure nobody could decrypt the data without knowing this application-specific AppSecret value
- here data is cyphered using a random secret key, stored in a file located in

 GetSystemPath(spUserData)+sep+Pbkdf2HmacSha256(CryptProtectDataEntropy,User)

with sep='_' under Windows, and sep='.syn-' under Linux/Posix
- under Windows, it will encode the secret file via CryptProtectData DPAPI, so has the same security level than plain CryptDataForCurrentUserDPAPI(), but will be much faster, since it won't call the API each time
- under Linux/POSIX, access to the $HOME user's .xxxxxxxxxxx secret file with chmod 400 is considered to be a safe enough approach
- this function is up to 100 times faster than CryptDataForCurrentUserDPAPI, generates smaller results, and is consistent on all Operating Systems
- you can use this function over a specified variable, to cypher it in place, with try ... finally block to protect memory access of the plain data:

  constructor TMyClass.Create;
  ...
    fSecret := CryptDataForCurrentUser('Some Secret Value','appsalt',true);
  ...
  procedure TMyClass.DoSomething;
  var plain: RawByteString;
  begin
    plain := CryptDataForCurrentUser(fSecret,'appsalt',false);
    try
      // here plain = 'Some Secret Value'
    finally
      FillZero(plain); // safely erase uncyphered content from heap
    end;
  end;

1.6.33. Hash128ToDouble

function Hash128ToDouble(P: PHash128Rec): double;

Low-level function able to derivate a 0..1 64-bit floating-point from 128-bit of data
- used e.g. by TAesPrng.RandomDouble
- only the higher part of P^ will be used for derivation thanks to AES input


1.6.34. Hash128ToExt

function Hash128ToExt(P: PHash128Rec): TSynExtended;

Low-level function able to derivate a 0..1 floating-point from 128-bit of data
- used e.g. by TAesPrng.RandomExt
- only the lower part of P^ will be used for derivation thanks to AES input


1.6.35. Hash128ToSingle

function Hash128ToSingle(P: PHash128Rec): single;

Low-level function able to derivate a 0..1 32-bit floating-point from 128-bit of data
- only the lower part of P^ will be used for derivation thanks to AES input


1.6.36. HmacCrc256c

procedure HmacCrc256c(key, msg: pointer; keylen, msglen: integer; out result: THash256); overload;

Compute the HMAC message authentication code using crc256c as hash function
- HMAC over a non cryptographic hash function like crc256c is known to be safe as MAC, if the supplied key comes e.g. from cryptographic HmacSha256
- performs two crc32c hashes, so SSE 4.2 gives more than 2.2 GB/s on a Core i7


1.6.37. HmacCrc256c

procedure HmacCrc256c(const key: THash256; const msg: RawByteString; out result: THash256); overload;

Compute the HMAC message authentication code using crc256c as hash function
- HMAC over a non cryptographic hash function like crc256c is known to be safe as MAC, if the supplied key comes e.g. from cryptographic HmacSha256
- performs two crc32c hashes, so SSE 4.2 gives more than 2.2 GB/s on a Core i7


1.6.38. HmacCrc256c

procedure HmacCrc256c(const key, msg: RawByteString; out result: THash256); overload;

Compute the HMAC message authentication code using crc256c as hash function
- HMAC over a non cryptographic hash function like crc256c is known to be safe as MAC, if the supplied key comes e.g. from cryptographic HmacSha256
- performs two crc32c hashes, so SSE 4.2 gives more than 2.2 GB/s on a Core i7


1.6.39. HmacCrc32c

function HmacCrc32c(const key: THash256; const msg: RawByteString): cardinal; overload;

Compute the HMAC message authentication code using crc32c as hash function
- HMAC over a non cryptographic hash function like crc32c is known to be a safe enough MAC, if the supplied key comes e.g. from cryptographic HmacSha256
- SSE 4.2 will let MAC be computed at 13 GB/s on a Core i7 / x86_64


1.6.40. HmacCrc32c

function HmacCrc32c(key, msg: pointer; keylen, msglen: integer): cardinal; overload;

Compute the HMAC message authentication code using crc32c as hash function
- HMAC over a non cryptographic hash function like crc32c is known to be a safe enough MAC, if the supplied key comes e.g. from cryptographic HmacSha256
- SSE 4.2 will let MAC be computed at 13 GB/s on a Core i7 / x86_64


1.6.41. HmacCrc32c

function HmacCrc32c(const key, msg: RawByteString): cardinal; overload;

Compute the HMAC message authentication code using crc32c as hash function
- HMAC over a non cryptographic hash function like crc32c is known to be a safe enough MAC, if the supplied key comes e.g. from cryptographic HmacSha256
- SSE 4.2 will let MAC be computed at 13 GB/s on a Core i7 / x86_64


1.6.42. HmacSha1

procedure HmacSha1(const key, msg: RawByteString; out result: TSha1Digest); overload;

Compute the HMAC message authentication code using SHA-1 as hash function


1.6.43. HmacSha1

procedure HmacSha1(key, msg: pointer; keylen, msglen: integer; out result: TSha1Digest); overload;

Compute the HMAC message authentication code using SHA-1 as hash function


1.6.44. HmacSha1

procedure HmacSha1(const key: TSha1Digest; const msg: RawByteString; out result: TSha1Digest); overload;

Compute the HMAC message authentication code using SHA-1 as hash function


1.6.45. HmacSha256

procedure HmacSha256(const key, msg: RawByteString; out result: TSha256Digest); overload;

Compute the HMAC message authentication code using SHA-256 as hash function


1.6.46. HmacSha256

procedure HmacSha256(const key: TSha256Digest; const msg: RawByteString; out result: TSha256Digest); overload;

Compute the HMAC message authentication code using SHA-256 as hash function


1.6.47. HmacSha256

procedure HmacSha256(key, msg: pointer; keylen, msglen: integer; out result: TSha256Digest); overload;

Compute the HMAC message authentication code using SHA-256 as hash function


1.6.48. HmacSha384

procedure HmacSha384(key, msg: pointer; keylen, msglen: integer; out result: TSha384Digest); overload;

Compute the HMAC message authentication code using SHA-384 as hash function


1.6.49. HmacSha384

procedure HmacSha384(const key: TSha384Digest; const msg: RawByteString; out result: TSha384Digest); overload;

Compute the HMAC message authentication code using SHA-384 as hash function


1.6.50. HmacSha384

procedure HmacSha384(const key, msg: RawByteString; out result: TSha384Digest); overload;

Compute the HMAC message authentication code using SHA-384 as hash function


1.6.51. HmacSha512

procedure HmacSha512(const key: TSha512Digest; const msg: RawByteString; out result: TSha512Digest); overload;

Compute the HMAC message authentication code using SHA-512 as hash function


1.6.52. HmacSha512

procedure HmacSha512(key, msg: pointer; keylen, msglen: integer; out result: TSha512Digest); overload;

Compute the HMAC message authentication code using SHA-512 as hash function


1.6.53. HmacSha512

procedure HmacSha512(const key, msg: RawByteString; out result: TSha512Digest); overload;

Compute the HMAC message authentication code using SHA-512 as hash function


1.6.54. HTDigest

function HTDigest(const user, realm, pass: RawByteString): RawUtf8;

Compute the HTDigest for a user and a realm, according to a supplied password
- apache-compatible: 'agent007:download area:8364d0044ef57b3defcfa141e8f77b65'


1.6.55. Md4

function Md4(const s: RawByteString): RawUtf8;

Direct MD4 hash calculation of some data (string-encoded)
- result is returned in lowercase hexadecimal format


1.6.56. Md4Buf

function Md4Buf(const Buffer; Len: cardinal): TMd5Digest;

Direct MD4 hash calculation of some data


1.6.57. Md5

function Md5(const s: RawByteString): RawUtf8;

Direct MD5 hash calculation of some data (string-encoded)
- result is returned in lowercase hexadecimal format


1.6.58. Md5Buf

function Md5Buf(const Buffer; Len: cardinal): TMd5Digest;

Direct MD5 hash calculation of some data


1.6.59. Md5DigestToString

function Md5DigestToString(const D: TMd5Digest): RawUtf8;

Compute the lowercase hexadecimal representation of a MD5 digest


1.6.60. Md5StringToDigest

function Md5StringToDigest(const Source: RawUtf8; out Dest: TMd5Digest): boolean;

Compute the MD5 digest from its hexadecimal representation
- returns true on success (i.e. Source has the expected size and characters)
- just a wrapper around mormot.core.text.HexToBin()


1.6.61. Pbkdf2HmacSha1

procedure Pbkdf2HmacSha1(const password, salt: RawByteString; count: integer; out result: TSha1Digest);

Compute the PBKDF2 derivation of a password using HMAC over SHA-1
- this function expect the resulting key length to match SHA-1 digest size


1.6.62. Pbkdf2HmacSha256

procedure Pbkdf2HmacSha256(const password, salt: RawByteString; count: integer; out result: TSha256Digest; const saltdefault: RawByteString = ''); overload;

Compute the PBKDF2 derivation of a password using HMAC over SHA-256
- this function expect the resulting key length to match SHA-256 digest size


1.6.63. Pbkdf2HmacSha256

procedure Pbkdf2HmacSha256(const password, salt: RawByteString; count: integer; var result: THash256DynArray; const saltdefault: RawByteString = ''); overload;

Compute the PBKDF2 derivations of a password using HMAC over SHA-256, into several 256-bit items, so can be used to return any size of output key
- this function expect the result array to have the expected output length
- allows resulting key length to be more than one SHA-256 digest size, e.g. to be used for both Encryption and MAC


1.6.64. Pbkdf2HmacSha384

procedure Pbkdf2HmacSha384(const password, salt: RawByteString; count: integer; out result: TSha384Digest);

Compute the PBKDF2 derivation of a password using HMAC over SHA-384
- this function expect the resulting key length to match SHA-384 digest size


1.6.65. Pbkdf2HmacSha512

procedure Pbkdf2HmacSha512(const password, salt: RawByteString; count: integer; out result: TSha512Digest);

Compute the PBKDF2 derivation of a password using HMAC over SHA-512
- this function expect the resulting key length to match SHA-512 digest size


1.6.66. Pbkdf2Sha3

procedure Pbkdf2Sha3(algo: TSha3Algo; const password, salt: RawByteString; count: integer; result: PByte; resultbytes: integer = 0);

Safe key derivation using iterated SHA-3 hashing
- you can use SHA3_224, SHA3_256, SHA3_384, SHA3_512 algorithm to fill the result buffer with the default sized derivated key of 224,256,384 or 512 bits (leaving resultbytes = 0)
- or you may select SHAKE_128 or SHAKE_256, and specify any custom key size in resultbytes (used e.g. by Pbkdf2Sha3Crypt)


1.6.67. Pbkdf2Sha3Crypt

procedure Pbkdf2Sha3Crypt(algo: TSha3Algo; const password, salt: RawByteString; count: integer; var data: RawByteString);

Encryption/decryption of any data using iterated SHA-3 hashing key derivation
- specified algo is expected to be SHAKE_128 or SHAKE_256
- expected the supplied data buffer to be small, because the whole buffer will be hashed in XOF mode count time, so it would be slow - for big content, consider using an AES Cypher after 256-bit Pbkdf2Sha3 key derivation


1.6.68. RawMd5Compress

procedure RawMd5Compress(var Hash; Data: pointer);

Entry point of the raw MD5 transform function - for low-level use


1.6.69. RawSha1Compress

procedure RawSha1Compress(var Hash; Data: pointer);

Entry point of the raw SHA-1 transform function - for low-level use


1.6.70. RawSha256Compress

procedure RawSha256Compress(var Hash; Data: pointer);

Entry point of the raw SHA-256 transform function - for low-level use


1.6.71. RawSha512Compress

procedure RawSha512Compress(var Hash; Data: pointer);

Entry point of the raw SHA-512 transform function - for low-level use


1.6.72. Sha1

function Sha1(const s: RawByteString): RawUtf8;

Direct SHA-1 hash calculation of some data (string-encoded)
- result is returned in hexadecimal format


1.6.73. Sha1DigestToString

function Sha1DigestToString(const D: TSha1Digest): RawUtf8;

Compute the hexadecimal representation of a SHA-1 digest


1.6.74. Sha1StringToDigest

function Sha1StringToDigest(const Source: RawUtf8; out Dest: TSha1Digest): boolean;

Compute the SHA-1 digest from its hexadecimal representation
- returns true on success (i.e. Source has the expected size and characters)
- just a wrapper around mormot.core.text.HexToBin()


1.6.75. Sha256

function Sha256(Data: pointer; Len: integer): RawUtf8; overload;

Direct SHA-256 hash calculation of some binary data
- result is returned in hexadecimal format


1.6.76. Sha256

function Sha256(const s: RawByteString): RawUtf8; overload;

Direct SHA-256 hash calculation of some data (string-encoded)
- result is returned in hexadecimal format


1.6.77. Sha256Digest

function Sha256Digest(Data: pointer; Len: integer): TSha256Digest; overload;

Direct SHA-256 hash calculation of some binary data
- result is returned in TSha256Digest binary format
- since the result would be stored temporarly in the stack, it may be safer to use an explicit TSha256Digest variable, which would be filled with zeros by a ... finally FillZero(


1.6.78. Sha256Digest

function Sha256Digest(const Data: RawByteString): TSha256Digest; overload;

Direct SHA-256 hash calculation of some binary data
- result is returned in TSha256Digest binary format
- since the result would be stored temporarly in the stack, it may be safer to use an explicit TSha256Digest variable, which would be filled with zeros by a ... finally FillZero(


1.6.79. Sha256DigestToString

function Sha256DigestToString(const D: TSha256Digest): RawUtf8;

Compute the hexadecimal representation of a SHA-256 digest


1.6.80. Sha256StringToDigest

function Sha256StringToDigest(const Source: RawUtf8; out Dest: TSha256Digest): boolean;

Compute the SHA-256 digest from its hexadecimal representation
- returns true on success (i.e. Source has the expected size and characters)
- just a wrapper around mormot.core.text.HexToBin()


1.6.81. Sha256Weak

procedure Sha256Weak(const s: RawByteString; out Digest: TSha256Digest);

SHA-256 hash calculation with padding if shorter than 255 bytes
- WARNING: this algorithm is DEPRECATED, and supplied only for backward compatibility of existing code (CryptDataForCurrentUser or TProtocolAes)
- use Pbkdf2HmacSha256() or similar functions for safer password derivation


1.6.82. Sha3

function Sha3(Algo: TSha3Algo; Buffer: pointer; Len: integer; DigestBits: integer = 0): RawUtf8; overload;

Direct SHA-3 hash calculation of some binary buffer
- result is returned in hexadecimal format
- default DigestBits=0 will write the default number of bits to Digest output memory buffer, according to the specified TSha3Algo


1.6.83. Sha3

function Sha3(Algo: TSha3Algo; const s: RawByteString; DigestBits: integer = 0): RawUtf8; overload;

Direct SHA-3 hash calculation of some data (string-encoded)
- result is returned in hexadecimal format
- default DigestBits=0 will write the default number of bits to Digest output memory buffer, according to the specified TSha3Algo


1.6.84. Sha384

function Sha384(const s: RawByteString): RawUtf8;

Direct SHA-384 hash calculation of some data (string-encoded)
- result is returned in hexadecimal format


1.6.85. Sha384DigestToString

function Sha384DigestToString(const D: TSha384Digest): RawUtf8;

Compute the hexadecimal representation of a SHA-384 digest


1.6.86. Sha512

function Sha512(const s: RawByteString): RawUtf8;

Direct SHA-512 hash calculation of some data (string-encoded)
- result is returned in hexadecimal format


1.6.87. Sha512DigestToString

function Sha512DigestToString(const D: TSha512Digest): RawUtf8;

Compute the hexadecimal representation of a SHA-512 digest


1.6.88. Sha512_256

function Sha512_256(const s: RawByteString): RawUtf8;

Direct SHA-512/256 hash calculation of some data (string-encoded)
- result is returned in hexadecimal format


1.6.89. XorBlock

procedure XorBlock(p: PIntegerArray; Count, Cod: integer);

Simple XOR encryption according to Cod - not Compression or Stream compatible
- used in deprecated AESFull() for KeySize=32
- Cod is used to derivate some pseudo-random content from internal constant tables, so encryption is weak but fast


1.6.90. XorBlock16

procedure XorBlock16(A, B: PPtrIntArray); overload;

Apply the A = A XOR B operation to the supplied binary buffers of 16 bytes


1.6.91. XorBlock16

procedure XorBlock16(A, B, C: PPtrIntArray); overload;

Apply the B = A XOR C operation to the supplied binary buffers of 16 bytes


1.6.92. XorConst

procedure XorConst(p: PIntegerArray; Count: integer);

Weak XOR Cypher changing by Count value
- Compression compatible, since the XOR value is always the same, the compression rate will not change a lot
- this encryption is very weak, so should be used only for basic obfuscation, not data protection


1.6.93. XorOffset

procedure XorOffset(P: PByteArray; Index, Count: PtrInt);

Simple XOR Cypher using Index (=Position in Dest Stream)
- Compression not compatible with this function: should be applied after compress (e.g. as outStream for TAesWriteStream)
- Stream compatible (with updated Index)
- used in deprecated AES() and TAesWriteStream
- Index is used to derivate some pseudo-random content from internal constant tables, so encryption is weak but fast


1.6.94. _add256

function _add256(out Output: THash256Rec; const Left, Right: THash256Rec): PtrUInt;

Optimized 256-bit addition (with Intel/AMD asm) - used by ecc256r1


1.6.95. _bswap256

procedure _bswap256(dest, source: PQWordArray);

Move and change endianness of a 256-bit value
- warning: this code requires dest <> source


1.6.96. _cmp256

function _cmp256(const Left, Right: THash256Rec): integer;

Returns sign of 256-bit Left - Right comparison - used by ecc256r1


1.6.97. _dec256

function _dec256(var Value: THash256Rec; const Subs: THash256Rec): PtrUInt;

Optimized 256-bit substraction (with Intel/AMD asm) - used by ecc256r1


1.6.98. _inc128

procedure _inc128(var Value: THash256Rec; var Added: THash128Rec);

Optimized 128-bit addition (with Intel/AMD asm) - used by ecc256r1


1.6.99. _inc256

function _inc256(var Value: THash256Rec; const Added: THash256Rec): PtrUInt;

Optimized 256-bit addition (with Intel/AMD asm) - used by ecc256r1


1.6.100. _inc64

procedure _inc64(var Value: THash128Rec; var Added: QWord);

Optimized 64-bit addition (with Intel/AMD asm) - used by ecc256r1


1.6.101. _lshift

function _lshift(var Output: THash256Rec; const Input: THash256Rec; Shift: integer): QWord;

Computes Output = Input shl Shift, returning carry, of a 256-bit value
- can modify in place (if Output == Input). 0 < Shift < 64


1.6.102. _lshift1

function _lshift1(var V: THash256Rec): PtrUInt;

Left shift of 1 bit of a 256-bit value - used by ecc256r1


1.6.103. _mult128

procedure _mult128(const l, r: THash128Rec; out product: THash256Rec);

128-to-256-bit multiplication (with Intel/AMD asm) - used by ecc256r1


1.6.104. _mult256

procedure _mult256(out Output: THash512Rec; const Left, Right: THash256Rec);

256-to-512-bit multiplication (with x86_64 asm) - used by ecc256r1


1.6.105. _numbits256

function _numbits256(const V: THash256Rec): integer;

Compute the highest bit set of a 256-bit value - used by ecc256r1


1.6.106. _rshift1

procedure _rshift1(var V: THash256Rec);

Right shift of 1 bit of a 256-bit value - used by ecc256r1


1.6.107. _square256

procedure _square256(out Output: THash512Rec; const Left: THash256Rec);

256-to-512-bit ^2 computation - used by ecc256r1


1.6.108. _sub256

function _sub256(out Output: THash256Rec; const Left, Right: THash256Rec): PtrUInt;

Optimized 256-bit substraction (with Intel/AMD asm) - used by ecc256r1


1.6.109. _xasmadd

function _xasmadd(Value, Adds: pointer; Carry: PtrUInt): PtrUInt;

Add of two TBigInt 512/1024-bit buffers - as used by mormot.crypt.rsa


1.6.110. _xasmdiv

function _xasmdiv(Value: pointer; Factor, Carry: PtrUInt): PtrUInt;

Div-by-integer of a TBigInt 512/1024-bit buffer - as used by mormot.crypt.rsa


1.6.111. _xasmmod

function _xasmmod(Value: pointer; Factor, Carry: PtrUInt): PtrUInt;

Mod-by-integer of a TBigInt 512/1024-bit buffer - as used by mormot.crypt.rsa


1.6.112. _xasmmul

function _xasmmul(Src, Dst: pointer; Factor, Carry: PtrUInt): PtrUInt;

Mul-by-integer of a TBigInt 256/512-bit buffer - as used by mormot.crypt.rsa


1.6.113. _xasmmuladd

function _xasmmuladd(Src, Dst: pointer; Factor, Carry: PtrUInt): PtrUInt;

Mul-and-add of a TBigInt 256/512-bit buffer - as used by mormot.crypt.rsa


1.6.114. _xasmsub

function _xasmsub(Value, Subs: pointer; Carry: PtrUInt): PtrUInt;

Sub of two TBigInt 512/1024-bit buffers - as used by mormot.crypt.rsa


1.7. Variables implemented in the mormot.crypt.core unit

1.7.1. AesNiHash128

AesNiHash128: procedure(hash: PHash128; data: pointer; len: PtrUInt);

128-bit aeshash as implemented in Go runtime, using aesni opcode
- access to the raw function implementing both AesNiHash64 and AesNiHash32
- only defined if AES-NI and SSE 4.1 are available on this CPU
- warning: the hashes will be consistent only during a process: at startup, a random AES key is computed to prevent attacks on forged input
- DefaultHasher128() is assigned to this function, when available on the CPU


1.7.2. AesNiHash32

AesNiHash32: THasher;

32-bit truncation of Go runtime aeshash, using aesni opcode
- just a wrapper around AesNiHash128() with proper 32-bit zeroing
- only defined if AES-NI and SSE 4.1 are available on this CPU
- faster than our SSE4.2+pclmulqdq crc32c() function, with less collision
- warning: the hashes will be consistent only during a process: at startup, a random AES key is computed to prevent attacks on forged input
- DefaultHasher() is assigned to this function, when available on the CPU


1.7.3. AesNiHash64

AesNiHash64: function(seed: QWord; data: pointer; len: PtrUInt): QWord;

64-bit aeshash as implemented in Go runtime, using aesni opcode
- is the fastest and probably one of the safest non-cryptographic hash
- just a wrapper around AesNiHash128() with proper 64-bit zeroing
- only defined if AES-NI and SSE 4.1 are available on this CPU, so you should always check if Assigned(AesNiHash64) then ...
- warning: the hashes will be consistent only during a process: at startup, a random AES key is computed to prevent attacks on forged input
- DefaultHasher64() is assigned to this function, when available on the CPU


1.7.4. CompressShaAesClass

CompressShaAesClass: TAesAbstractClass = TAesCfb;

The DEPRECATED AES-256 encoding class used by CompressShaAes() global function
- DO NOT USE: since HTTP compression is optional, this scheme is not safe
- use any of the implementation classes, corresponding to the chaining mode required - TAesEcb, TAesCbc, TAesCfb, TAesOfb and TAesCtr* classes to handle in ECB, CBC, CFB, OFB and CTR mode (including PKCS7-like padding)
- set to the secure and efficient CFB mode by default


1.7.5. CryptProtectDataEntropy

CryptProtectDataEntropy: THash256 = ( $19, $8E, $BA, $52, $FA, $D6, $56, $99, $7B, $73, $1B, $D0, $8B, $3A, $95, $AB, $94, $63, $C2, $C0, $78, $05, $9C, $8B, $85, $B7, $A1, $E3, $ED, $93, $27, $18);

Salt for CryptDataForCurrentUser function
- is filled with some random bytes by default, but you may override it for a set of custom processes calling CryptDataForCurrentUser


1.7.6. DisabledAsm

DisabledAsm: set of ( daAesNiSse41, daAesNiSse42, daAesGcmAvx, daKeccakAvx2);

Low-level flags to globally disable some asm optimization at runtime
- flags are platform-dependent and may have no effect


1.7.7. HasOpenSsl

HasOpenSsl: boolean;

Global flag set by mormot.crypt.openssl when the OpenSSL engine is used


1.7.8. MainAesPrng

MainAesPrng: TAesPrngAbstract;

The shared TAesPrng instance returned by TAesPrng.Main class function
- you may override this to a customized instance, e.g. for a specific random generator to be used, like TSystemPrng or TAesPrngOsl


1.7.9. OpenSslRandBytes

OpenSslRandBytes: function(buf: PByte; num: integer): integer; cdecl;

Low-level RAND_bytes() OpenSSL API function set by mormot.crypt.openssl
- used by TAesPrng.GetEntropy if available to add some audited entropy


1.7.10. TAesFast

TAesFast: TAesAbstractClasses = ( TAesEcb, TAesCbc, TAesCfb, TAesOfb, TAesC64, TAesCtr, TAesCfc, TAesOfc, TAesCtc, TAesGcm);

The fastest AES implementation classes available on the system, per mode
- mormot.crypt.openssl may register its own classes, e.g. TAesGcmOsl