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
Unit Name | Description | |
---|---|---|
mormot.core.base | Framework Core Shared Types and RTL-like Functions | |
mormot.core.os | Framework Core Low-Level Wrappers to the Operating-System API | |
mormot.core.rtti | Framework Core Low-Level Cross-Compiler RTTI Definitions | |
mormot.core.text | Framework Core Low-Level Text Processing | |
mormot.core.unicode | Framework Core Low-Level Unicode UTF-8 UTF-16 Ansi Conversion |
Objects | Description | |
---|---|---|
ESynCrypto | Class of Exceptions raised by this unit | |
TAes | Handle AES cypher/uncypher | |
TAesAbstract | Handle AES cypher/uncypher with chaining | |
TAesAbstractAead | AEAD (authenticated-encryption with associated-data) abstract class | |
TAesAbstractApi | Handle AES cypher/uncypher using Windows CryptoApi and the official Microsoft AES Cryptographic Provider (PROV_RSA_AES) | |
TAesAbstractEncryptOnly | Abstract parent class for chaining modes using only AES encryption | |
TAesAbstractSyn | Handle AES cypher/uncypher with chaining with our own optimized code | |
TAesC64 | Handle AES cypher/uncypher with non-standard 64-bit Counter mode (CTR) | |
TAesCbc | Handle AES cypher/uncypher with Cipher-block chaining (CBC) | |
TAesCbcApi | Handle AES cypher/uncypher Cipher-block chaining (CBC) using Windows CryptoApi | |
TAesCfb | Handle AES cypher/uncypher with Cipher feedback (CFB) | |
TAesCfbApi | Handle AES cypher/uncypher Cipher feedback (CFB) using Windows CryptoApi | |
TAesCfc | AEAD combination of AES with Cipher feedback (CFB) and 256-bit crc32c MAC | |
TAesCtc | AEAD combination of AES with Counter (CTR) and 256-bit crc32c MAC | |
TAesCtr | Handle AES cypher/uncypher with 128-bit Counter mode (CTR) | |
TAesEcb | Handle AES cypher/uncypher without chaining (ECB) | |
TAesEcbApi | Handle AES cypher/uncypher without chaining (ECB) using Windows CryptoApi | |
TAesFull | AES and XOR encryption object for easy direct memory or stream access | |
TAesFullHeader | Internal header for storing our AES data with salt and CRC | |
TAesGcm | Handle AES-GCM cypher/uncypher using our TAesGcmEngine | |
TAesGcmAbstract | Abstract parent to handle AES-GCM cypher/uncypher with built-in authentication | |
TAesGcmEngine | Low-level AES-GCM processing | |
TAesLocked | Thread-safe class containing a TAes encryption/decryption engine | |
TAesMac256 | Internal 256-bit structure used for TAesAbstractAead MAC storage | |
TAesOfb | Handle AES cypher/uncypher with Output feedback (OFB) | |
TAesOfbApi | Handle AES cypher/uncypher Output feedback (OFB) using Windows CryptoApi | |
TAesOfc | AEAD combination of AES with Output feedback (OFB) and 256-bit crc32c MAC | |
TAesPkcs7Abstract | Abstract parent class to TAesPkcs7Writer and TAesPkcs7Reader | |
TAesPkcs7Reader | Multi-mode PKCS7 buffered AES decryption stream | |
TAesPkcs7Writer | Multi-mode PKCS7 buffered AES encryption stream | |
TAesPrng | Cryptographic pseudorandom number generator (CSPRNG) based on AES-256 | |
TAesPrngAbstract | Abstract parent for TAesPrng* classes | |
TAesSymCrc | AEAD combination of AES and 256-bit MAC with symmetrical Encrypt/Decrypt | |
TAesWriteStream | AES encryption stream (deprecated) | |
THmacCrc32c | Compute the HMAC message authentication code using crc32c as hash function | |
THmacSha1 | Compute the HMAC message authentication code using SHA-1 as hash function | |
THmacSha256 | Compute the HMAC message authentication code using SHA-256 as hash function | |
THmacSha384 | Compute the HMAC message authentication code using SHA-384 as hash function | |
THmacSha512 | Compute the HMAC message authentication code using SHA-512 as hash function | |
TMacAndCryptData | Header layout used for TAesAbstract.MacAndCrypt format | |
TMd5 | Implements MD5 hashing - and could also implement MD4 if really needed | |
TRC4 | Implements RC4 encryption/decryption | |
TSha1 | Implements SHA-1 hashing | |
TSha256 | Implements SHA-256 hashing | |
TSha3 | Implements SHA-3 (Keccak) hashing | |
TSha384 | Implements SHA-384 hashing | |
TSha384512 | Abstract parent for implementing SHA-384, SHA-512/256 and SHA-512 hashing | |
TSha512 | Implements SHA-512 hashing | |
TSha512_256 | Implements SHA-512/256 hashing | |
TSystemPrng | TAesPrng-compatible class using Operating System pseudorandom source |
ESynCrypto = class(ESynException)
Class of Exceptions raised by this unit
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;
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;
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
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)
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
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
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)
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
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
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
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
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
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
()
TMacAndCryptData = packed record
Header layout used for TAesAbstract.MacAndCrypt
format
data: byte;
Crc32c
(nonce
+mac
) to avoid naive fuzzing
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
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
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
()
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
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
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
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)
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
TAesEcbApi = class(TAesAbstractApi)
Handle AES
cypher/uncypher without chaining (ECB) using Windows CryptoApi
TAesCbcApi = class(TAesAbstractApi)
Handle AES
cypher/uncypher Cipher
-block chaining (CBC) using Windows CryptoApi
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
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
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
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)
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
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
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
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
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
()
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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)
PAes = ^TAes;
Points to a TAes
encryption/decryption instance
PHmacCrc32c = ^THmacCrc32c;
Points to HMAC
message authentication code using crc32c
as hash
function
PHmacSha1 = ^THmacSha1;
Points to a HMAC
message authentication context using SHA-1
PHmacSha256 = ^THmacSha256;
Points to a HMAC
message authentication context using SHA-256
PHmacSha384 = ^THmacSha384;
Points to a HMAC
message authentication context using SHA-384
PHmacSha512 = ^THmacSha512;
Points to a HMAC
message authentication context using SHA-512
PSha1 = ^TSha1;
Points to SHA-1 hashing instance
PSha256 = ^TSha256;
Points to SHA-256 hashing instance
PSha3 = ^TSha3;
Points to SHA-3 hashing instance
PSha384 = ^TSha384;
Points to SHA-384 hashing instance
PSha512 = ^TSha512;
Points to SHA-512 hashing instance
PSha512_256= ^TSha512_256;
Points to SHA-512/256 hashing instance
Short32 = string[32];
32-characters ASCII string, e.g. as returned by AesBlockToShortString
()
TAesAbstractClass = class of TAesAbstract;
Class-reference type (metaclass) of an AES
cypher/uncypher
TAesBlock = THash128;
128-bit memory block for AES
data cypher/uncypher
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
TAesGcmAbstractClass = class of TAesGcmAbstract;
Meta-class of TAesGcmAbstract
types
TAesKey = THash256;
256-bit memory block for maximum AES
key storage
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'
TAesPrngClass = class of TAesPrngAbstract;
Meta-class for our CSPRNG implementations
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
TAesPrngSystem = TSystemPrng;
Most Operating System PRNG are very unlikely AES
based - confusing
TMd5Digest = THash128;
128-bit memory block for MD5
hash
digest
storage
TSha1Digest = THash160;
160 bits memory block for SHA-1 hash
digest
storage
TSha256Digest = THash256;
256-bit (32 bytes) memory block for SHA-256 hash
digest
storage
TSha384Digest = THash384;
384 bits (64 bytes) memory block for SHA-384 hash
digest
storage
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
TSha512Digest = THash512;
512 bits (64 bytes) memory block for SHA-512 hash
digest
storage
AesBlockMod = 15;
Bit mask for fast modulo of AES
block size
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
AES_AEAD = [mCfc, mOfc, mCtc, mGcm];
The AES
chaining modes which supports AEAD process
AES_CONTEXT_SIZE = 276 + SizeOf(pointer) + SizeOf(pointer) ;
Hide all AES
Context complex code
AES_INTERNAL = [mC64, mCfc, mOfc, mCtc];
Our non standard chaining modes, which do not exist e.g. on OpenSSL
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
GMAC_SIZE = 16;
The AES
-GCM GMAC size (in bytes)
SHA3_CONTEXT_SIZE = 410;
Hide TSha3Context complex code by storing the Keccak/SHA-3 Sponge as buffer
SHA_CONTEXT_SIZE = 108;
Hide TSha1
/TSha256
complex code by storing the SHA-1/SHA-2 context as buffer
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
_xasmdivn = SizeOf(pointer) * 16;
256/512 bits per call
_xasmmodn = SizeOf(pointer) * 16;
512/1024 bits per call
_xasmmuladdn = SizeOf(pointer) * 8;
256/512 bits per call
_xasmmuln = SizeOf(pointer) * 8;
512/1024 bits per call
_xasmsubn = SizeOf(pointer) * 16;
512/1024 bits per call
Functions or procedures | Description | |
---|---|---|
Adler32Asm | Fast Adler32 implementation | |
Adler32Pas | Simple Adler32 implementation | |
AES | Direct Encrypt/Decrypt of data using the TAes class (deprecated) | |
AES | Direct Encrypt/Decrypt of data using the TAes class (deprecated) | |
AES | Direct Encrypt/Decrypt of data using the TAes class (deprecated) | |
AES | Direct Encrypt/Decrypt of data using the TAes class (deprecated) | |
AesAlgoNameDecode | OpenSSL-like Cipher name decoding into a mormot.crypt.core TAesAbstract class | |
AesAlgoNameDecode | OpenSSL-like Cipher name decoding into mormot.crypt.core AES engines | |
AesAlgoNameEncode | OpenSSL-like Cipher name encoding of mormot.crypt.core AES engines | |
AesAlgoNameEncode | OpenSSL-like Cipher name encoding of mormot.crypt.core AES engines | |
AesBlockToShortString | Compute the hexadecial representation of an AES 16-byte block | |
AesBlockToShortString | Compute the hexadecial representation of an AES 16-byte block | |
AesBlockToString | Compute the hexadecial representation of an AES 16-byte block | |
AESFull | AES and XOR encryption using the TAesFull format (deprecated) | |
AESFull | AES and XOR encryption using the TAesFull format (deprecated) | |
AESFullKeyOK | AES and XOR decryption check using the TAesFull format (deprecated) | |
AesIvUpdatedCreate | Create one AES instance which updates its IV between Encrypt/Decrypt calls | |
AesPkcs7 | Cypher/decypher any buffer using AES and PKCS7 padding, from a key buffer | |
AesPkcs7 | Cypher/decypher any buffer using AES and PKCS7 padding, from a key buffer | |
AesPkcs7File | Cypher/decypher any file using AES and PKCS7 padding, from a password | |
AesPkcs7File | Cypher/decypher any file using AES and PKCS7 padding, from a key buffer | |
AESSHA256 | AES encryption using the TAes format with a supplied password (deprecated) | |
AESSHA256 | AES encryption using the TAes format with a supplied password (deprecated) | |
AESSHA256 | AES encryption using the TAes format with a supplied password (deprecated) | |
AESSHA256Full | AES encryption using the TAesFull format with a supplied password (deprecated) | |
AesTablesTest | Used for paranoid safety by test.core.crypto.pas | |
AFDiffusion | Low-level anti-forensic diffusion of a memory buffer using SHA-256 | |
bswap160 | Little endian fast conversion | |
bswap256 | Little endian fast conversion | |
CompressShaAes | Encrypt data content using the DEPRECATED AES-256/CFB algorithm, after SynLZ | |
CompressShaAesSetKey | Set an text-based encryption key for DEPRECATED CompressShaAes() global function | |
CryptDataForCurrentUser | Protect some data via AES-256-CFB and a secret known by the current user only | |
Hash128ToDouble | Low-level function able to derivate a 0..1 64-bit floating-point from 128-bit of data | |
Hash128ToExt | Low-level function able to derivate a 0..1 floating-point from 128-bit of data | |
Hash128ToSingle | Low-level function able to derivate a 0..1 32-bit floating-point from 128-bit of data | |
HmacCrc256c | Compute the HMAC message authentication code using crc256c as hash function | |
HmacCrc256c | Compute the HMAC message authentication code using crc256c as hash function | |
HmacCrc256c | Compute the HMAC message authentication code using crc256c as hash function | |
HmacCrc32c | Compute the HMAC message authentication code using crc32c as hash function | |
HmacCrc32c | Compute the HMAC message authentication code using crc32c as hash function | |
HmacCrc32c | Compute the HMAC message authentication code using crc32c as hash function | |
HmacSha1 | Compute the HMAC message authentication code using SHA-1 as hash function | |
HmacSha1 | Compute the HMAC message authentication code using SHA-1 as hash function | |
HmacSha1 | Compute the HMAC message authentication code using SHA-1 as hash function | |
HmacSha256 | Compute the HMAC message authentication code using SHA-256 as hash function | |
HmacSha256 | Compute the HMAC message authentication code using SHA-256 as hash function | |
HmacSha256 | Compute the HMAC message authentication code using SHA-256 as hash function | |
HmacSha384 | Compute the HMAC message authentication code using SHA-384 as hash function | |
HmacSha384 | Compute the HMAC message authentication code using SHA-384 as hash function | |
HmacSha384 | Compute the HMAC message authentication code using SHA-384 as hash function | |
HmacSha512 | Compute the HMAC message authentication code using SHA-512 as hash function | |
HmacSha512 | Compute the HMAC message authentication code using SHA-512 as hash function | |
HmacSha512 | Compute the HMAC message authentication code using SHA-512 as hash function | |
HTDigest | Compute the HTDigest for a user and a realm, according to a supplied password | |
Md4 | Direct MD4 hash calculation of some data (string-encoded) | |
Md4Buf | Direct MD4 hash calculation of some data | |
Md5 | Direct MD5 hash calculation of some data (string-encoded) | |
Md5Buf | Direct MD5 hash calculation of some data | |
Md5DigestToString | Compute the lowercase hexadecimal representation of a MD5 digest | |
Md5StringToDigest | Compute the MD5 digest from its hexadecimal representation | |
Pbkdf2HmacSha1 | Compute the PBKDF2 derivation of a password using HMAC over SHA-1 | |
Pbkdf2HmacSha256 | 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 | |
Pbkdf2HmacSha256 | Compute the PBKDF2 derivation of a password using HMAC over SHA-256 | |
Pbkdf2HmacSha384 | Compute the PBKDF2 derivation of a password using HMAC over SHA-384 | |
Pbkdf2HmacSha512 | Compute the PBKDF2 derivation of a password using HMAC over SHA-512 | |
Pbkdf2Sha3 | Safe key derivation using iterated SHA-3 hashing | |
Pbkdf2Sha3Crypt | Encryption/decryption of any data using iterated SHA-3 hashing key derivation | |
RawMd5Compress | Entry point of the raw MD5 transform function - for low-level use | |
RawSha1Compress | Entry point of the raw SHA-1 transform function - for low-level use | |
RawSha256Compress | Entry point of the raw SHA-256 transform function - for low-level use | |
RawSha512Compress | Entry point of the raw SHA-512 transform function - for low-level use | |
Sha1 | Direct SHA-1 hash calculation of some data (string-encoded) | |
Sha1DigestToString | Compute the hexadecimal representation of a SHA-1 digest | |
Sha1StringToDigest | Compute the SHA-1 digest from its hexadecimal representation | |
Sha256 | Direct SHA-256 hash calculation of some data (string-encoded) | |
Sha256 | Direct SHA-256 hash calculation of some binary data | |
Sha256Digest | Direct SHA-256 hash calculation of some binary data | |
Sha256Digest | Direct SHA-256 hash calculation of some binary data | |
Sha256DigestToString | Compute the hexadecimal representation of a SHA-256 digest | |
Sha256StringToDigest | Compute the SHA-256 digest from its hexadecimal representation | |
Sha256Weak | SHA-256 hash calculation with padding if shorter than 255 bytes | |
Sha3 | Direct SHA-3 hash calculation of some data (string-encoded) | |
Sha3 | Direct SHA-3 hash calculation of some binary buffer | |
Sha384 | Direct SHA-384 hash calculation of some data (string-encoded) | |
Sha384DigestToString | Compute the hexadecimal representation of a SHA-384 digest | |
Sha512 | Direct SHA-512 hash calculation of some data (string-encoded) | |
Sha512DigestToString | Compute the hexadecimal representation of a SHA-512 digest | |
Sha512_256 | Direct SHA-512/256 hash calculation of some data (string-encoded) | |
XorBlock | Simple XOR encryption according to Cod - not Compression or Stream compatible | |
XorBlock16 | Apply the B = A XOR C operation to the supplied binary buffers of 16 bytes | |
XorBlock16 | Apply the A = A XOR B operation to the supplied binary buffers of 16 bytes | |
XorConst | Weak XOR Cypher changing by Count value | |
XorOffset | Simple XOR Cypher using Index (=Position in Dest Stream) | |
_add256 | Optimized 256-bit addition (with Intel/AMD asm) - used by ecc256r1 | |
_bswap256 | Move and change endianness of a 256-bit value | |
_cmp256 | Returns sign of 256-bit Left - Right comparison - used by ecc256r1 | |
_dec256 | Optimized 256-bit substraction (with Intel/AMD asm) - used by ecc256r1 | |
_inc128 | Optimized 128-bit addition (with Intel/AMD asm) - used by ecc256r1 | |
_inc256 | Optimized 256-bit addition (with Intel/AMD asm) - used by ecc256r1 | |
_inc64 | Optimized 64-bit addition (with Intel/AMD asm) - used by ecc256r1 | |
_lshift | Computes Output = Input shl Shift, returning carry, of a 256-bit value | |
_lshift1 | Left shift of 1 bit of a 256-bit value - used by ecc256r1 | |
_mult128 | 128-to-256-bit multiplication (with Intel/AMD asm) - used by ecc256r1 | |
_mult256 | 256-to-512-bit multiplication (with x86_64 asm) - used by ecc256r1 | |
_numbits256 | Compute the highest bit set of a 256-bit value - used by ecc256r1 | |
_rshift1 | Right shift of 1 bit of a 256-bit value - used by ecc256r1 | |
_square256 | 256-to-512-bit ^2 computation - used by ecc256r1 | |
_sub256 | Optimized 256-bit substraction (with Intel/AMD asm) - used by ecc256r1 | |
_xasmadd | Add of two TBigInt 512/1024-bit buffers - as used by mormot.crypt.rsa | |
_xasmdiv | Div-by-integer of a TBigInt 512/1024-bit buffer - as used by mormot.crypt.rsa | |
_xasmmod | Mod-by-integer of a TBigInt 512/1024-bit buffer - as used by mormot.crypt.rsa | |
_xasmmul | Mul-by-integer of a TBigInt 256/512-bit buffer - as used by mormot.crypt.rsa | |
_xasmmuladd | Mul-and-add of a TBigInt 256/512-bit buffer - as used by mormot.crypt.rsa | |
_xasmsub | Sub of two TBigInt 512/1024-bit buffers - as used by mormot.crypt.rsa |
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
function Adler32Pas(Adler: cardinal; p: pointer; Count: integer): cardinal;
Simple Adler32
implementation
- a bit slower than Adler32Asm
() version below, but shorter code size
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
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
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
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
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
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
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'
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
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
function AesBlockToShortString(const block: TAesBlock): short32; overload;
Compute the hexadecial representation of an AES
16-byte block
- returns a stack-allocated short string
function AesBlockToString(const block: TAesBlock): RawUtf8;
Compute the hexadecial representation of an AES
16-byte block
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
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
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
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
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
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
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
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
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
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
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
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
function AesTablesTest: boolean;
Used for paranoid safety by test.core.crypto.pas
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
procedure bswap160(s, d: PIntegerArray);
Little endian fast conversion
- 160 bits = 5 integers
- use fast bswap asm in x86/x64 mode
procedure bswap256(s, d: PIntegerArray);
Little endian fast conversion
- 256-bit = 8 integers
- use fast bswap asm in x86/x64 mode
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 ''
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
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;
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
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
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
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
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
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
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
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
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
procedure HmacSha1(const key, msg: RawByteString; out result: TSha1Digest); overload;
Compute the HMAC
message authentication code using SHA-1 as hash
function
procedure HmacSha1(key, msg: pointer; keylen, msglen: integer; out result: TSha1Digest); overload;
Compute the HMAC
message authentication code using SHA-1 as hash
function
procedure HmacSha1(const key: TSha1Digest; const msg: RawByteString; out result: TSha1Digest); overload;
Compute the HMAC
message authentication code using SHA-1 as hash
function
procedure HmacSha256(const key, msg: RawByteString; out result: TSha256Digest); overload;
Compute the HMAC
message authentication code using SHA-256 as hash
function
procedure HmacSha256(const key: TSha256Digest; const msg: RawByteString; out result: TSha256Digest); overload;
Compute the HMAC
message authentication code using SHA-256 as hash
function
procedure HmacSha256(key, msg: pointer; keylen, msglen: integer; out result: TSha256Digest); overload;
Compute the HMAC
message authentication code using SHA-256 as hash
function
procedure HmacSha384(key, msg: pointer; keylen, msglen: integer; out result: TSha384Digest); overload;
Compute the HMAC
message authentication code using SHA-384 as hash
function
procedure HmacSha384(const key: TSha384Digest; const msg: RawByteString; out result: TSha384Digest); overload;
Compute the HMAC
message authentication code using SHA-384 as hash
function
procedure HmacSha384(const key, msg: RawByteString; out result: TSha384Digest); overload;
Compute the HMAC
message authentication code using SHA-384 as hash
function
procedure HmacSha512(const key: TSha512Digest; const msg: RawByteString; out result: TSha512Digest); overload;
Compute the HMAC
message authentication code using SHA-512 as hash
function
procedure HmacSha512(key, msg: pointer; keylen, msglen: integer; out result: TSha512Digest); overload;
Compute the HMAC
message authentication code using SHA-512 as hash
function
procedure HmacSha512(const key, msg: RawByteString; out result: TSha512Digest); overload;
Compute the HMAC
message authentication code using SHA-512 as hash
function
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'
function Md4(const s: RawByteString): RawUtf8;
Direct MD4
hash
calculation of some data (string-encoded)
- result is returned in lowercase
hexadecimal format
function Md4Buf(const Buffer; Len: cardinal): TMd5Digest;
Direct MD4
hash
calculation of some data
function Md5(const s: RawByteString): RawUtf8;
Direct MD5
hash
calculation of some data (string-encoded)
- result is returned in lowercase
hexadecimal format
function Md5Buf(const Buffer; Len: cardinal): TMd5Digest;
Direct MD5
hash
calculation of some data
function Md5DigestToString(const D: TMd5Digest): RawUtf8;
Compute the lowercase
hexadecimal representation of a MD5
digest
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()
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
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
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
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
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
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
)
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
procedure RawMd5Compress(var Hash; Data: pointer);
Entry point of the raw MD5
transform function - for low-level use
procedure RawSha1Compress(var Hash; Data: pointer);
Entry point of the raw SHA-1 transform function - for low-level use
procedure RawSha256Compress(var Hash; Data: pointer);
Entry point of the raw SHA-256 transform function - for low-level use
procedure RawSha512Compress(var Hash; Data: pointer);
Entry point of the raw SHA-512 transform function - for low-level use
function Sha1(const s: RawByteString): RawUtf8;
Direct SHA-1 hash
calculation of some data (string-encoded)
- result is returned in hexadecimal format
function Sha1DigestToString(const D: TSha1Digest): RawUtf8;
Compute the hexadecimal representation of a SHA-1 digest
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()
function Sha256(Data: pointer; Len: integer): RawUtf8; overload;
Direct SHA-256 hash
calculation of some binary data
- result is returned in hexadecimal format
function Sha256(const s: RawByteString): RawUtf8; overload;
Direct SHA-256 hash
calculation of some data (string-encoded)
- result is returned in hexadecimal format
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
(
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
(
function Sha256DigestToString(const D: TSha256Digest): RawUtf8;
Compute the hexadecimal representation of a SHA-256 digest
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()
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
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
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
function Sha384(const s: RawByteString): RawUtf8;
Direct SHA-384 hash
calculation of some data (string-encoded)
- result is returned in hexadecimal format
function Sha384DigestToString(const D: TSha384Digest): RawUtf8;
Compute the hexadecimal representation of a SHA-384 digest
function Sha512(const s: RawByteString): RawUtf8;
Direct SHA-512 hash
calculation of some data (string-encoded)
- result is returned in hexadecimal format
function Sha512DigestToString(const D: TSha512Digest): RawUtf8;
Compute the hexadecimal representation of a SHA-512 digest
function Sha512_256(const s: RawByteString): RawUtf8;
Direct SHA-512/256 hash
calculation of some data (string-encoded)
- result is returned in hexadecimal format
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
procedure XorBlock16(A, B: PPtrIntArray); overload;
Apply the A = A XOR B operation to the supplied binary buffers of 16 bytes
procedure XorBlock16(A, B, C: PPtrIntArray); overload;
Apply the B = A XOR C operation to the supplied binary buffers of 16 bytes
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
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
function _add256(out Output: THash256Rec; const Left, Right: THash256Rec): PtrUInt;
Optimized 256-bit addition (with Intel/AMD asm) - used by ecc256r1
procedure _bswap256(dest, source: PQWordArray);
Move and change endianness of a 256-bit value
- warning: this code requires dest <> source
function _cmp256(const Left, Right: THash256Rec): integer;
Returns sign
of 256-bit Left - Right comparison - used by ecc256r1
function _dec256(var Value: THash256Rec; const Subs: THash256Rec): PtrUInt;
Optimized 256-bit substraction (with Intel/AMD asm) - used by ecc256r1
procedure _inc128(var Value: THash256Rec; var Added: THash128Rec);
Optimized 128-bit addition (with Intel/AMD asm) - used by ecc256r1
function _inc256(var Value: THash256Rec; const Added: THash256Rec): PtrUInt;
Optimized 256-bit addition (with Intel/AMD asm) - used by ecc256r1
procedure _inc64(var Value: THash128Rec; var Added: QWord);
Optimized 64-bit addition (with Intel/AMD asm) - used by ecc256r1
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
function _lshift1(var V: THash256Rec): PtrUInt;
Left shift of 1 bit of a 256-bit value - used by ecc256r1
procedure _mult128(const l, r: THash128Rec; out product: THash256Rec);
128-to-256-bit multiplication (with Intel/AMD asm) - used by ecc256r1
procedure _mult256(out Output: THash512Rec; const Left, Right: THash256Rec);
256-to-512-bit multiplication (with x86_64 asm) - used by ecc256r1
function _numbits256(const V: THash256Rec): integer;
Compute the highest bit set of a 256-bit value - used by ecc256r1
procedure _rshift1(var V: THash256Rec);
Right shift of 1 bit of a 256-bit value - used by ecc256r1
procedure _square256(out Output: THash512Rec; const Left: THash256Rec);
256-to-512-bit ^2 computation - used by ecc256r1
function _sub256(out Output: THash256Rec; const Left, Right: THash256Rec): PtrUInt;
Optimized 256-bit substraction (with Intel/AMD asm) - used by ecc256r1
function _xasmadd(Value, Adds: pointer; Carry: PtrUInt): PtrUInt;
Add of two TBigInt
512/1024-bit buffers - as used by mormot.crypt.rsa
function _xasmdiv(Value: pointer; Factor, Carry: PtrUInt): PtrUInt;
Div-by-integer of a TBigInt
512/1024-bit buffer - as used by mormot.crypt.rsa
function _xasmmod(Value: pointer; Factor, Carry: PtrUInt): PtrUInt;
Mod-by-integer of a TBigInt
512/1024-bit buffer - as used by mormot.crypt.rsa
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
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
function _xasmsub(Value, Subs: pointer; Carry: PtrUInt): PtrUInt;
Sub of two TBigInt
512/1024-bit buffers - as used by mormot.crypt.rsa
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
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
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
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
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
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
HasOpenSsl: boolean;
Global flag set by mormot.crypt.openssl when the OpenSSL engine is used
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
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
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