
Purpose: Framework Core Authentication and Security Features
- 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.buffers | Framework Core Low-Level Memory Buffer Process | |
| mormot.core.data | Framework Core Low-Level Data Processing Functions | |
| mormot.core.datetime | Framework Core Low-Level Date and Time Support | |
| mormot.core.json | Framework Core Low-Level JSON Processing | |
| 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 | |
| mormot.core.variants | Framework Core Low-Level Variants / TDocVariant process | |
| mormot.crypt.core | Framework Core Cryptographic Process (Hashing and Cypher) | |
| mormot.lib.sspi | Low-level access to the SSPI/SChannel API for Win32/Win64 |
| Objects | Description | |
|---|---|---|
| ECryptCert | Exception class raised by our High-Level Certificates Process | |
| EDigest | The exception class raised during Digest access authentication | |
| EStuffExe | Exception raised by StuffExeCertificate() in case of processing error | |
| IBasicAuthServer | HTTP BASIC access authentication on server side | |
| ICryptCert | Abstract interface to a Certificate, as returned by Cert() factory | |
| ICryptCipher | Interface as implemented e.g. by TCryptCipher from TCryptCipherAlgo.New | |
| ICryptHash | Interface as implemented e.g. by TCryptHash | |
| ICryptPrivateKey | Abstract interface to a Private Key, as returned by CryptPrivateKey[] factory | |
| ICryptPublicKey | Abstract interface to a Public Key, as returned by CryptPublicKey[] factory | |
| ICryptStore | Abstract interface to a Certificates Store, as returned by Store() factory | |
| IDigestAuthServer | HTTP DIGEST access authentication on server side | |
| IHttpAuthServer | Parent abstract HTTP access authentication on server side | |
| IProtocol | Perform safe communication after unilateral or mutual authentication | |
| TBasicAuthServer | Abstract BASIC access authentication on server side | |
| TBinaryCookieGenerator | Efficient thread-safe cookie generation | |
| TCryptAbstractKey | Abstract parent class to TCryptPublicKey and TCryptPrivateKey | |
| TCryptAlgo | Abstract class implemented e.g. by TCryptRandom/TCryptHasher/TCryptAsym | |
| TCryptAsym | Asymmetric public-key cryptography parent class, as returned by Asym() | |
| TCryptCert | Abstract parent class to implement ICryptCert, as returned by Cert() factory | |
| TCryptCertAbstractList | Abstract parent of TCryptCertList and TCryptCertCache storage classes | |
| TCryptCertAlgo | Abstract parent class for ICryptCert factories | |
| TCryptCertCache | Abstract class to cache ICryptCert instances, from their DER/binary | |
| TCryptCertFields | Convenient wrapper of X.509 Certificate subject name X.501 fields | |
| TCryptCertList | Store several ICryptCert instances | |
| TCryptCertPerUsage | Maintains a list of ICryptCert, easily reachable per TCryptCertUsage | |
| TCryptCipher | Symmetric encryption parent class, as returned by Cipher() factory | |
| TCryptCipherAlgo | Symmetric encryption class, as resolved by CipherAlgo() | |
| TCryptHash | Hashing/signing parent class, as returned by Hash/Sign() factories | |
| TCryptHasher | Hashing parent class, as resolved by Hasher() | |
| TCryptInstance | Abstract class implemented e.g. by TCryptHash/TCryptCipher/TCryptKey | |
| TCryptPrivateKey | Abstract private key parent class, as returned by the CryptPrivateKey[] factory | |
| TCryptPublicKey | Abstract public key parent class, as returned by CryptPublicKey[] factory | |
| TCryptRandom | Randomness generator parent class, as resolved by Rnd() | |
| TCryptSigner | Signing parent class, as resolved by Signer() | |
| TCryptStore | Abstract parent class to implement ICryptCert, as returned by Cert() factory | |
| TCryptStoreAlgo | Abstract parent class for ICryptStore factories | |
| TDigestAuthServer | Abstract DIGEST and BASIC access authentication on server side | |
| TDigestAuthServerFile | Digest access authentication on server side using a .htdigest file | |
| TDigestAuthServerMem | Digest access authentication on server side using in-memory storage | |
| TIPBan | Optimized thread-safe storage of a list of IP v4 adresses | |
| TProtocolAes | Implements a secure protocol using symmetric AES encryption | |
| TProtocolNone | Implements a fake no-encryption protocol | |
| TStreamRedirectMd5 | TStreamRedirect with MD5 cryptographic hashing | |
| TStreamRedirectSha1 | TStreamRedirect with SHA-1 cryptographic hashing | |
| TStreamRedirectSha256 | TStreamRedirect with SHA-256 cryptographic hashing | |
| TStreamRedirectSha384 | TStreamRedirect with SHA-384 cryptographic hashing | |
| TStreamRedirectSha3_256 | TStreamRedirect with SHA-3-256 cryptographic hashing | |
| TStreamRedirectSha3_512 | TStreamRedirect with SHA-3-512 cryptographic hashing | |
| TStreamRedirectSha512 | TStreamRedirect with SHA-512 cryptographic hashing | |
| TStreamRedirectSha512_256 | TStreamRedirect with SHA-512/256 cryptographic hashing | |
| TStreamRedirectSynHasher | TStreamRedirect with TSynHasher cryptographic hashing | |
| TSynAuthentication | Simple authentication class, implementing safe token/challenge security | |
| TSynAuthenticationAbstract | Abstract authentication class, implementing safe token/challenge security and a list of active sessions | |
| TSynConnectionDefinition | Handle safe storage of any connection properties | |
| TSynHasher | Convenient multi-algorithm hashing wrapper | |
| TSynPersistentWithPassword | Abstract TSynPersistent class allowing safe storage of a password | |
| TSynSigner | A generic wrapper object to handle digital HMAC-SHA-2/SHA-3 signatures | |
| TSynSignerParams | JSON-serialization ready object as used by TSynSigner.Pbkdf2() overloaded methods | |
| TSynUniqueIdentifierBits | Map 64-bit integer unique identifier internal memory structure | |
| TSynUniqueIdentifierGenerator | Thread-safe 64-bit integer unique identifier computation | |
| TSynUserPassword | Could be used to store a credential pair, as user name and password | |
| TX509Parsed | Output of the X509Parse() function |
TSynPersistentWithPassword = class(TSynPersistent)
Abstract TSynPersistent class allowing safe storage of a password
- the associated Password, e.g. for storage or transmission encryption will be persisted encrypted with a private key (which can be customized)
- if default simple symmetric encryption is not enough, it will also read passwords strongly obfuscated for a given user using mormot.crypt.core.pas' CryptDataForCurrentUser()
- a published property should be defined as such in inherited class:
property PasswordPropertyName: RawUtf8 read fPassword write fPassword;
- use the PassWordPlain property to access to its uncyphered value
destructor Destroy; override;
Finalize the instance
class function ComputePassword(PlainPassword: pointer; PlainPasswordLen: integer; CustomKey: cardinal = 0): SpiUtf8; overload;
This class method could be used to compute the encrypted password from a binary digest, ready to be stored as JSON, according to a given private key
- just a wrapper around ComputePassword(BinToBase64Uri())
class function ComputePassword(const PlainPassword: SpiUtf8; CustomKey: cardinal = 0): SpiUtf8; overload;
This class method could be used to compute the encrypted password, ready to be stored as JSON, according to a given private key
class function ComputePlainPassword(const CypheredPassword: SpiUtf8; CustomKey: cardinal = 0; const AppSecret: RawUtf8 = ''): SpiUtf8;
This class method could be used to decrypt a password, stored as JSON, according to a given private key
- may trigger a ECrypt if the password was stored using hardened CryptDataForCurrentUser, and the current user doesn't match the expected user stored in the field
property Key: cardinal read GetKey write fKey;
The private key used to cypher the password storage on serialization
- application can override the default 0 value at runtime
property PasswordPlain: SpiUtf8 read GetPassWordPlain write SetPassWordPlain;
Access to the associated unencrypted Password value
- may trigger a ECrypt if the password was stored using hardened CryptDataForCurrentUser, and the current user doesn't match the expected user stored in the field
TSynUserPassword = class(TSynPersistentWithPassword)
Could be used to store a credential pair, as user name and password
- password will be stored with TSynPersistentWithPassword encryption
property Password: SpiUtf8 read fPassword write fPassword;
The associated encrypted password
- use the PasswordPlain public property to access to the uncrypted password
property UserName: RawUtf8 read fUserName write fUserName;
The associated user name
TSynConnectionDefinition = class(TSynPersistentWithPassword)
Handle safe storage of any connection properties
- would be used by mormot.db to serialize TSqlDBConnectionProperties, or by mormot.rest.core.pas to serialize TRest instances
- the password will be stored as Base64, after a simple encryption as defined by TSynPersistentWithPassword
- typical content could be:
{
}- the "Kind" value will be used to let the corresponding TRest or TSqlDBConnectionProperties NewInstance*() class methods create the actual instance, from its class name
constructor CreateFromJson(const Json: RawUtf8; Key: cardinal = 0); virtual;
Unserialize the database definition from JSON
- as previously serialized with the SaveToJson method
- you can specify a custom Key used for password encryption, if the default value is not safe enough for you
function SaveToJson: RawUtf8; virtual;
Serialize the database definition as JSON
property DatabaseName: RawUtf8 read fDatabaseName write fDatabaseName;
The associated database name (if any), or additional options
property Kind: string read fKind write fKind;
The class name implementing the connection or TRest instance
- will be used to instantiate the expected class type
property Password: SpiUtf8 read fPassword write fPassword;
The associated Password, e.g. for storage or transmission encryption
- will be persisted encrypted with a private key
- use the PassWordPlain property to access to its uncyphered value
property ServerName: RawUtf8 read fServerName write fServerName;
The associated server name (or file, for SQLite3) to be connected to
property User: RawUtf8 read fUser write fUser;
The associated User Identifier (if any)
TSynAuthenticationAbstract = class(TObject)
Abstract authentication class, implementing safe token/challenge security and a list of active sessions
- do not use this class, but plain TSynAuthentication
constructor Create;
Initialize the authentication scheme
destructor Destroy; override;
Finalize the authentation
class function ComputeHash(Token: Int64; const UserName, PassWord: RawUtf8): cardinal; virtual;
To be used to compute a Hash on the client sude, for a given Token
- the token should have been retrieved from the server, and the client should compute and return this hash value, to perform the authentication challenge and create the session
- internal algorithm is not cryptographic secure, but fast and safe
function CreateSession(const User: RawUtf8; Hash: cardinal): integer; virtual;
Create a new session
- should return 0 on authentication error, or an integer session ID
- this method will check the User name and password, and create a new session
function CurrentToken: Int64;
Returns the current identification token
- to be sent to the client for its authentication challenge
function SessionExists(aID: integer): boolean;
Check if the session exists in the internal list
procedure AuthenticateUser(const aName, aPassword: RawUtf8); virtual;
Register one credential for a given user
- this abstract method will raise an exception: inherited classes should implement them as expected
procedure DisauthenticateUser(const aName: RawUtf8); virtual;
Unregister one credential for a given user
- this abstract method will raise an exception: inherited classes should implement them as expected
procedure RemoveSession(aID: integer);
Delete a session
property SessionsCount: integer read fSessionsCount;
The number of current opened sessions
property UsersCount: integer read GetUsersCount;
The number of registered users
TSynAuthentication = class(TSynAuthenticationAbstract)
Simple authentication class, implementing safe token/challenge security
- maintain a list of user / name credential pairs, and a list of sessions
- is not meant to handle authorization, just plain user access validation
- used e.g. by TSqlDBConnection.RemoteProcessMessage (on server side) and TSqlDBProxyConnectionPropertiesAbstract (on client side) in mormot.db.proxy
constructor Create(const aUserName: RawUtf8 = ''; const aPassword: RawUtf8 = ''); reintroduce;
Initialize the authentication scheme
- you can optionally register one user credential
procedure AuthenticateUser(const aName, aPassword: RawUtf8); override;
Register one credential for a given user
procedure DisauthenticateUser(const aName: RawUtf8); override;
Unregister one credential for a given user
TIPBan = class(TSynPersistentStore)
Optimized thread-safe storage of a list of IP v4 adresses
- can be used e.g. as white-list or black-list of clients
- will maintain internally a sorted list of 32-bit integers for fast lookup
- with optional binary persistence
- as used by TRestServer.BanIP/JwtForUnauthenticatedRequestWhiteIP
- see also more efficient and lower level THttpAcceptBan in mormot.net.http
function Add(const aIP: RawUtf8): boolean;
Register one IP to the list
function Delete(const aIP: RawUtf8): boolean;
Unregister one IP to the list
function DynArrayLocked(aLock: TRWLockContext = cWrite): TDynArray;
Creates a TDynArray wrapper around the stored list of values
- could be used e.g. for binary persistence
- warning: caller should make Safe.Unlock(aLock) when finished
function Exists(const aIP: RawUtf8): boolean;
Returns true if the IP is in the list
property Count: integer read fCount;
How many IPs are currently banned
property IP4: TIntegerDynArray read fIP4;
Low-level access to the internal IPv4 list
- 32-bit unsigned values are sorted, for fast O(log(n)) binary search
TSynUniqueIdentifierBits = object(TObject)
Map 64-bit integer unique identifier internal memory structure
- as stored in TSynUniqueIdentifier = TID = Int64 values, and computed by TSynUniqueIdentifierGenerator
- bits 0..14 map a 15-bit increasing counter (collision-free)
- bits 15..30 map a 16-bit process identifier
- bits 31..63 map a 33-bit UTC time, encoded as seconds since Unix epoch
Value: TSynUniqueIdentifier;
The actual 64-bit storage value
- in practice, only first 63 bits are used
function AsVariant: variant;
Convert this identifier as an explicit TDocVariant JSON object
- returns e.g.
{"Created":"2016-04-19T15:27:58","Identifier":1,"Counter":1,
"Value":3137644716930138113,"Hex":"2B8B273F00008001"}function Counter: word;
Extract the 15-bit counter (0..32767), starting with a random value
function CreateDateTime: TDateTime;
Extract the UTC generation timestamp as TDateTime
- time is expressed in Coordinated Universal Time (UTC), not local time
function CreateTimeLog: TTimeLog;
Extract the UTC generation timestamp as our TTimeLog
- time is expressed in Coordinated Universal Time (UTC), not local time
function CreateTimeUnix: TUnixTime;
Extract the UTC generation timestamp as seconds since the Unix epoch
- time is expressed in Coordinated Universal Time (UTC), not local time
- it uses in fact a 33-bit resolution, so is "Year 2038" bug-free
function Equal(const Another: TSynUniqueIdentifierBits): boolean;
Compare two Identifiers
function FromHexa(const hexa: RawUtf8): boolean;
Fill this unique identifier back from a 16 chars hexadecimal string
- returns TRUE if the supplied hexadecimal is on the expected format
- returns FALSE if the supplied text is invalid
function ProcessID: TSynUniqueIdentifierProcess;
Extract the 16-bit unique process identifier
- as specified to TSynUniqueIdentifierGenerator constructor
function ToHexa: RawUtf8;
Convert the identifier into a 16 chars hexadecimal string
procedure From(const aID: TSynUniqueIdentifier);
Fill this unique identifier structure from its TSynUniqueIdentifier value
- is just a wrapper around PInt64(@self)^
procedure FromDateTime(const aDateTime: TDateTime);
Fill this unique identifier with a fake value corresponding to a given timestamp
- may be used e.g. to limit database queries on a particular time range
- bits 0..30 would be 0, i.e. would set Counter = 0 and ProcessID = 0
procedure FromUnixTime(const aUnixTime: TUnixTime);
Fill this unique identifier with a fake value corresponding to a given timestamp
- may be used e.g. to limit database queries on a particular time range
- bits 0..30 would be 0, i.e. would set Counter = 0 and ProcessID = 0
procedure ToVariant(out Result: variant);
Convert this identifier to an explicit TDocVariant JSON object
- returns e.g.
{"Created":"2016-04-19T15:27:58","Identifier":1,"Counter":1,
"Value":3137644716930138113,"Hex":"2B8B273F00008001"}TSynUniqueIdentifierGenerator = class(TSynPersistent)
Thread-safe 64-bit integer unique identifier computation
- may be used on client side for something similar to a MongoDB ObjectID, but compatible with TOrm.ID: TID properties, since it will contain a 63-bit unsigned integer, following our ORM expectations
- each identifier would contain a 16-bit process identifier, which is supplied by the application, and should be unique for this process at a given time
- identifiers may be obfuscated as hexadecimal text, using both encryption and digital signature
- all its methods are thread-safe, even during obfuscation processing
constructor Create(aIdentifier: TSynUniqueIdentifierProcess; const aSharedObfuscationKey: RawUtf8 = ''; aSharedObfuscationKeyNewKdf: integer = 0); reintroduce;
Initialized if aSharedObfuscationKeyNewKdf initialize the generator for the given 16-bit process identifier
- you can supply an obfuscation key, which should be shared for the whole system, so that you may use FromObfuscated/ToObfuscated methods
- if aSharedObfuscationKeyNewKdf is > 0, indicates the rounds count for a safer AES/SHA3 algorithm used for the obfuscation cryptography - keep it as default 0 for mORMot 1.18 backward compatibility
destructor Destroy; override;
Finalize the generator structure
function ComputeNew: Int64; overload;
Return a new unique ID, type-casted to an Int64
function FromObfuscated(const aObfuscated: TSynUniqueIdentifierObfuscated; out aIdentifier: TSynUniqueIdentifier): boolean;
Retrieve a TSynUniqueIdentifier from 24/32 chars cyphered hexadecimal text
- any file extension (e.g. '.jpeg') would be first deleted from the supplied obfuscated text
- returns true if the supplied obfuscated text has the expected layout and a valid digital signature
- returns false if the supplied obfuscated text is invalid
- note that this method will work for any TSynUniqueIdentifierProcess of the same aSharedObfuscationKey - not only the Identifier of this node
function ToObfuscated( const aIdentifier: TSynUniqueIdentifier): TSynUniqueIdentifierObfuscated;
Map a TSynUniqueIdentifier as 24/32 chars cyphered hexadecimal text
- cyphering includes simple key-based encryption and a CRC-32 digital signature
- returned text size is 24 for the legacy format, and 32 chars if aSharedObfuscationKeyNewKdf was set to true
procedure ComputeFromDateTime(const aDateTime: TDateTime; out result: TSynUniqueIdentifierBits);
Return an ID matching this generator pattern, at a given timestamp
- may be used e.g. to limit database queries on a particular time range
- the ID is not guaranted to be unique, but match the supplied TDateTime
procedure ComputeFromUnixTime(const aUnixTime: TUnixTime; out result: TSynUniqueIdentifierBits);
Return an ID matching this generator pattern, at a given timestamp
- may be used e.g. to limit database queries on a particular time range
- the ID is not guaranted to be unique, but match the supplied TUnixTime
procedure ComputeNew(out result: TSynUniqueIdentifierBits); overload;
Return a new unique ID
- this method is very optimized, and would use very little CPU
procedure WaitForSafeCreateTime(TimeOutSeconds: integer = 30);
Paranoid loop until LastUnixCreateTime
- may be called at server shutdown, if you expect a lot of collisions, and want to ensure the "fake" timestamp match the time at server restart
property Collisions: cardinal read fCollisions;
How many times ComputeNew method did have a collision and a fake increased timestamp has been involved
property ComputedCount: Int64 read fComputedCount;
How many times ComputeNew method has been called
property CryptoCRC: cardinal read fCryptoCRC;
Some 32-bit value, derivated from aSharedObfuscationKey as supplied to the class constructor
- FromObfuscated and ToObfuscated methods will validate their hexadecimal content with this value to secure the associated CRC
- may be used e.g. as system-depending salt
property Identifier: TSynUniqueIdentifierProcess read fIdentifier;
The process identifier, associated with this generator
property LastUnixCreateTime: cardinal read fUnixCreateTime write fUnixCreateTime;
Low-level access to the last generated timestamp
- you may need to persist this value if a lot of Collisions happened, and the timestamp was faked - you may also call WaitForSafeCreateTime
property Safe: TLightLock read fSafe;
Direct access to the associated mutex
TSynSignerParams = packed record
JSON-serialization ready object as used by TSynSigner.Pbkdf2() overloaded methods
- default value for unspecified parameters will be SHAKE_128 with rounds=1000 and a fixed salt
- a typical (extended) JSON to supply to TSynSigner.Pbkdf2() may be
{algo:"saSha512",secret:"StrongPassword",salt:"FixedSalt",rounds:10000}TSynSigner = object(TObject)
A generic wrapper object to handle digital HMAC-SHA-2/SHA-3 signatures
- used e.g. to implement TJwtSynSignerAbstract
Algo: TSignAlgo;
The algorithm used for digitial signature
SignatureSize: integer;
Enough space for all the size, in bytes, of the digital signature of this algorithm
- potential values are 20, 28, 32, 48 and 64
function Final: RawUtf8; overload;
Returns the computed digital signature as lowercase hexadecimal text
function Full(aAlgo: TSignAlgo; const aSecret: RawUtf8; aBuffer: pointer; aLen: integer): RawUtf8; overload;
One-step digital signature of a buffer as lowercase hexadecimal string
function Full(aAlgo: TSignAlgo; const aSecret, aSalt: RawUtf8; aSecretPbkdf2Round: integer; aBuffer: pointer; aLen: integer): RawUtf8; overload;
One-step digital signature of a buffer with PBKDF2 derivation
procedure AssignTo(var aDerivatedKey: THash512Rec; out aAes: TAes; aEncrypt: boolean);
Prepare a TAes object with the key derivated via a Pbkdf2() call
- aDerivatedKey is defined as "var", since it will be zeroed after use
procedure Done;
Fill the internal context with zeros, for security
procedure Final(out aSignature: THash512Rec; aNoInit: boolean = false); overload;
Returns the raw computed digital signature
- SignatureSize bytes will be written: use Signature.Lo/h0/b3/b accessors
procedure Init(aAlgo: TSignAlgo; const aSecret: RawUtf8); overload;
Initialize the digital HMAC/SHA-3 signing context with some secret text
procedure Init(aAlgo: TSignAlgo; aSecret: pointer; aSecretLen: integer); overload;
Initialize the digital HMAC/SHA-3 signing context with some secret binary
procedure Init(aAlgo: TSignAlgo; const aSecret, aSalt: RawUtf8; aSecretPbkdf2Round: integer; aPbkdf2Secret: PHash512Rec = nil); overload;
Initialize the digital HMAC/SHA-3 signing context with PBKDF2 safe iterative key derivation of a secret salted text
procedure Pbkdf2(aParamsJson: PUtf8Char; aParamsJsonLen: integer; out aDerivatedKey: THash512Rec; const aDefaultSalt: RawUtf8 = SIGNER_DEFAULT_SALT; aDefaultAlgo: TSignAlgo = saSha3S128); overload;
Convenient wrapper to perform PBKDF2 safe iterative key derivation
- accept as input a TSynSignerParams serialized as JSON object e.g.
{algo:"saSha512",secret:"StrongPassword",salt:"FixedSalt",rounds:10000}procedure Pbkdf2(const aParamsJson: RawUtf8; out aDerivatedKey: THash512Rec; const aDefaultSalt: RawUtf8 = SIGNER_DEFAULT_SALT; aDefaultAlgo: TSignAlgo = saSha3S128); overload;
Convenient wrapper to perform PBKDF2 safe iterative key derivation
- accept as input a TSynSignerParams serialized as JSON object e.g.
{algo:"saSha512",secret:"StrongPassword",salt:"FixedSalt",rounds:10000}procedure Pbkdf2(aAlgo: TSignAlgo; const aSecret, aSalt: RawUtf8; aSecretPbkdf2Round: integer; out aDerivatedKey: THash512Rec); overload;
Convenient wrapper to perform PBKDF2 safe iterative key derivation
procedure Pbkdf2(const aParams: TSynSignerParams; out aDerivatedKey: THash512Rec); overload;
Convenient wrapper to perform PBKDF2 safe iterative key derivation
procedure Update(aBuffer: pointer; aLen: integer); overload;
Process some message content supplied as memory buffer
procedure Update(const aBuffer: RawByteString); overload;
Process some message content supplied as string
TSynHasher = object(TObject)
Convenient multi-algorithm hashing wrapper
- as used e.g. by HashFile/HashFull functions
- we defined a record instead of a class, to allow stack allocation and thread-safe reuse of one initialized instance
function Final(out aDigest: THash512Rec): integer; overload;
Set the resulting hash into a binary buffer, and the size as result
function Full(aAlgo: THashAlgo; aBuffer: pointer; aLen: integer): RawUtf8; overload;
One-step hash computation of a buffer as lowercase hexadecimal string
function Full(aAlgo: THashAlgo; const aBuffer: RawByteString): RawUtf8; overload;
One-step hash computation of a buffer as lowercase hexadecimal string
function Full(aAlgo: THashAlgo; aBuffer: pointer; aLen: integer; out aDigest: THash512Rec): integer; overload;
One-step hash computation of a buffer as a binary buffer
- returns the written aDigest size in bytes
function HashSize: integer;
Returns the number of bytes of the hash of the current Algo
function Init(aAlgo: THashAlgo): boolean;
Enough space for all algorithms initialize the internal hashing structure for a specific algorithm
- returns false on unknown/unsupported algorithm
function Mgf1(aAlgo: THashAlgo; aSeed: pointer; aSeedLen, aDestLen: PtrUInt): RawByteString;
Fill a buffer with the MGF1 seed deriviation, following RFC 2437
- a Mask Generation Function expands aSeed/aSeedLen into aDestLen buffer
procedure Final(var aResult: RawUtf8); overload;
Returns the resulting hash as lowercase hexadecimal string
procedure Full(aAlgo: THashAlgo; const aBuffer: array of RawByteString; var aResult: RawUtf8); overload;
One-step hash computation of several buffers as lowercase hexadecimal string
procedure Update(aBuffer: pointer; aLen: integer); overload;
Hash the supplied memory buffer
procedure Update(const aBuffer: array of RawByteString); overload;
Hash the supplied strings content
procedure Update(const aBuffer: RawByteString); overload;
Hash the supplied string content
property Algo: THashAlgo read fAlgo;
The hash algorithm used by this instance
TStreamRedirectSynHasher = class(TStreamRedirect)
TStreamRedirect with TSynHasher cryptographic hashing
- do not use this abstract class but inherited with overloaded GetAlgo
TStreamRedirectMd5 = class(TStreamRedirectSynHasher)
TStreamRedirect with MD5 cryptographic hashing
TStreamRedirectSha1 = class(TStreamRedirectSynHasher)
TStreamRedirect with SHA-1 cryptographic hashing
TStreamRedirectSha256 = class(TStreamRedirectSynHasher)
TStreamRedirect with SHA-256 cryptographic hashing
TStreamRedirectSha384 = class(TStreamRedirectSynHasher)
TStreamRedirect with SHA-384 cryptographic hashing
TStreamRedirectSha512 = class(TStreamRedirectSynHasher)
TStreamRedirect with SHA-512 cryptographic hashing
TStreamRedirectSha512_256 = class(TStreamRedirectSynHasher)
TStreamRedirect with SHA-512/256 cryptographic hashing
TStreamRedirectSha3_256 = class(TStreamRedirectSynHasher)
TStreamRedirect with SHA-3-256 cryptographic hashing
TStreamRedirectSha3_512 = class(TStreamRedirectSynHasher)
TStreamRedirect with SHA-3-512 cryptographic hashing
EDigest = class(ESynException)
The exception class raised during Digest access authentication
IHttpAuthServer = interface(IInterface)
Parent abstract HTTP access authentication on server side
- as used e.g. by THttpServerSocketGeneric for its optional authentication
- you should use inherited IBasicAuthServer or IDigestAuthServer interfaces
function Instance: TObject;
Retrieve the implementation class instance
function Realm: RawUtf8;
The realm associated with this access authentication
IBasicAuthServer = interface(IHttpAuthServer)
HTTP BASIC access authentication on server side
- as used e.g. by THttpServerSocketGeneric for its BASIC authentication
function BasicAuth(FromClient: PUtf8Char; out ClientUser: RawUtf8): boolean;
Validate a Basic client authentication response
- FromClient typically follow 'Authorization: Basic ' header text
function BasicInit: RawUtf8;
Compute a Basic server authentication request header
- return e.g. 'WWW-Authenticate: Basic realm="Realm"'#13#10
function CheckCredential(const aUser: RawUtf8; const aPassword: SpiUtf8): TAuthServerResult;
Check the credentials stored for a given user
- returns true if supplied aUser/aPassword are correct, false otherwise
function OnBasicAuth(aSender: TObject; const aUser: RawUtf8; const aPassword: SpiUtf8): boolean;
Check the stored credentials as for the TOnHttpServerBasicAuth callback
- used for the BASIC authentication scheme in THttpServerSocketGeneric
IDigestAuthServer = interface(IHttpAuthServer)
HTTP DIGEST access authentication on server side
- as used e.g. by THttpServerSocketGeneric for its DIGEST authentication
function DigestAlgoMatch(const FromClient: RawUtf8): boolean;
Quickly check if the supplied client response is likely to be compatible
- FromClient is typically a HTTP header
- will just search for the 'algorithm=xxx,' text pattern
function DigestAuth(FromClient: PUtf8Char; const Method: RawUtf8; Opaque, Tix64: Int64; out ClientUser, ClientUrl: RawUtf8): TAuthServerResult;
Validate a Digest client authentication response
- used for the DIGEST authentication scheme in THttpServerSocketGeneric
- FromClient typically follow 'Authorization: Digest ' header text
- Opaque should match the value supplied on previous ServerInit() call
- properly implemented in TDigestAuthServer: THttpAuthServer raise EDigest
function DigestInit(Opaque, Tix64: Int64; const Prefix: RawUtf8 = 'WWW-Authenticate: Digest '; const Suffix: RawUtf8 = #13#10): RawUtf8;
Compute a Digest server authentication request
- used for the DIGEST authentication scheme in THttpServerSocketGeneric
- returns the standard HTTP header with the default Prefix/Suffix
- Opaque is a 64-bit number, typically the THttpServerConnectionID
- properly implemented in TDigestAuthServer: THttpAuthServer raise EDigest
TBasicAuthServer = class(TInterfacedObjectWithCustomCreate)
Abstract BASIC access authentication on server side
- don't use this class but e.g. TDigestAuthServerMem or TDigestAuthServerFile
- will implement the IBasicAuthServer process in an abstract way
constructor Create(const aRealm: RawUtf8); reintroduce;
Initialize the HTTP access authentication engine
function BasicAuth(FromClient: PUtf8Char; out ClientUser: RawUtf8): boolean;
Validate a Basic client authentication response
function BasicInit: RawUtf8;
Compute a Basic server authentication request header
- return e.g. 'WWW-Authenticate: Basic realm="Realm"'#13#10
function CheckCredential(const aUser: RawUtf8; const aPassword: SpiUtf8): TAuthServerResult; virtual; abstract;
Check the credentials stored for a given user
- this is the main abstract virtual method to override for BASIC auth
- will also trigger OnBeforeAuth/OnAfterAuth callbacks
- returns true if supplied aUser/aPassword are correct, false otherwise
function Instance: TObject;
Retrieve the implementation class instance
function OnBasicAuth(aSender: TObject; const aUser: RawUtf8; const aPassword: SpiUtf8): boolean;
Check the stored credentials as for the TOnHttpServerBasicAuth callback
function Realm: RawUtf8;
Retrieve the realm associated with this access authentication
- a good practice is to use the server host name or UUID as realm
property OnAfterAuth: TOnAuthServer read fOnAfterAuth write fOnAfterAuth;
Allow to reject an user after its credentials are checked
property OnBeforeAuth: TOnAuthServer read fOnBeforeAuth write fOnBeforeAuth;
Allow to reject an user before its credentials are checked
- can implement e.g. the "search and bind" pattern on a slow LDAP server
TDigestAuthServer = class(TBasicAuthServer)
Abstract DIGEST and BASIC access authentication on server side
- should be inherited with proper persistence of users credentials
- notice: won't maintain sessions in memory, just check the credentials each time so these classes should be used for authentication not authorization; a typical usage is with our TRestServer sessions or to generate a JWT bearer
- the RFC expects in-memory sessions, especially for nonce counters but we store a THttpServerConnectionID to the Opaque parameter to compensate, and we implement an expiration delay with each ServerInit request
- BasicInit and BasicAuth methods could be used to implement Basic access authentication calling the very same GetUserHash() virtual method
constructor Create(const aRealm: RawUtf8; aAlgo: TDigestAlgo); reintroduce; virtual;
Initialize the Digest access authentication engine
function CheckCredential(const aUser: RawUtf8; const aPassword: SpiUtf8): TAuthServerResult; override;
Check the credentials stored for a given user
function DigestAlgoMatch(const FromClient: RawUtf8): boolean;
Quickly check if the supplied client response is likely to be compatible
function DigestAuth(FromClient: PUtf8Char; const Method: RawUtf8; Opaque, Tix64: Int64; out ClientUser, ClientUrl: RawUtf8): TAuthServerResult;
Validate a Digest client authentication response
function DigestInit(Opaque, Tix64: Int64; const Prefix, Suffix: RawUtf8): RawUtf8;
Compute a Digest server authentication request
property Algo: TDigestAlgo read fAlgo;
The Digest algorithm used with this instance
property RequestExpSec: integer read fRequestExpSec write fRequestExpSec;
How many seconds a ServerInit() request is valid for ServerAuth()
- default is 60 seconds
TDigestAuthServerMem = class(TDigestAuthServer)
Digest access authentication on server side using in-memory storage
constructor Create(const aRealm: RawUtf8; aAlgo: TDigestAlgo); override;
Initialize the Digest access authentication engine
destructor Destroy; override;
Finalize the Digest access authentication engine
function GetUsers: TRawUtf8DynArray;
Retrieve all user names as a single array
- could be used e.g. to display a user list in the UI
procedure ClearCredentials;
Safely delete all stored credentials
- also fill TDigestAuthHash stored memory with zeros, against forensic
procedure SetCredential(const aUser: RawUtf8; const aPassword: SpiUtf8);
Change the credentials of a given user
- if aUser does not exist, the credential will be added
- if aUser does exist, the credential will be modified
- if aPassword is '', the credential will be deleted
property Count: integer read GetCount;
How many items are currently stored in memory
property Modified: boolean read fModified;
Flag set if SetCredential() was called but not persisted yet
property Users: TSynDictionary read fUsers;
Low-level access to the internal TSynDictionary storage
- to set e.g. Users.TimeOutSeconds or call Users.DeleteAll if this class is used as cache
TDigestAuthServerFile = class(TDigestAuthServerMem)
Digest access authentication on server side using a .htdigest file
- can also add, delete or update credentials
- file content is refreshed from disk when it has been modified
- only a single Realm is allowed per .htdigest file
- this class is thread-safe, with an efficient R/W lock
- file can be AES256-GCM encrypted on disk (non-standard but much safer)
constructor Create(const aRealm: RawUtf8; const aFileName: TFileName; const aFilePassword: SpiUtf8 = ''; aAlgo: TDigestAlgo = daMD5_Sess); reintroduce;
Initialize the Digest access authentication engine from a .htdigest file
- aFilePassword can optionally encrypt the .htdigest file using AES256-GCM
- default algorithm is MD5 with sessions - as used by NGINX auth_digest module
destructor Destroy; override;
Finalize the Digest access authentication engine
function RefreshFile: boolean;
Update or refresh file if needed
- typically called every few seconds in a background thread
- write any pending SetCredential() new/updated values
- reload the file if it has been modified on disk - on-disk modifications will be ignored if SetCredential() has been called in-between
procedure LoadFromFile;
Force (re)reading the .htdigest file content
procedure SaveToFile;
Save any SetCredential() pending modification to the .htdigest file
property Encrypted: boolean read GetEncrypted;
Flag if aFilePassword was specified at create, i.e. AES256-GCM is used
property FileName: TFileName read fFileName;
The .htdigest file name associated with this instance
IProtocol = interface(IInterface)
Perform safe communication after unilateral or mutual authentication
- see e.g. TProtocolNone or mormot.crypt.ecc's TEcdheProtocolClient and TEcdheProtocolServer implementation classes
function Clone: IProtocol;
Will create another instance of this communication protocol
function Decrypt(const aEncrypted: RawByteString; out aPlain: RawByteString): TProtocolResult;
Decrypt a message on one side, as transmitted from the other side
- should return sprSuccess if the
- should return sprInvalidMAC in case of wrong aEncrypted input (e.g. packet corruption, MiM or Replay attacks attempts)
- this method should be thread-safe in the implementation class
function ProcessHandshake(const MsgIn: RawUtf8; out MsgOut: RawUtf8): TProtocolResult;
Initialize the communication by exchanging some client/server information
- expects the handshaking messages to be supplied as UTF-8 text, may be as base64-encoded binary - see e.g. TWebSocketProtocolBinary.ProcessHandshake
- should return sprUnsupported if the implemented protocol does not expect any handshaking mechanism
- returns sprSuccess and set something into OutData, depending on the current step of the handshake
- returns an error code otherwise
procedure Encrypt(const aPlain: RawByteString; out aEncrypted: RawByteString);
Encrypt a message on one side, ready to be transmitted to the other side
- this method should be thread-safe in the implementation class
TProtocolNone = class(TInterfacedObject)
Implements a fake no-encryption protocol
- may be used for debugging purposes, or when encryption is not needed
function Clone: IProtocol;
Will create another instance of this communication protocol
function Decrypt(const aEncrypted: RawByteString; out aPlain: RawByteString): TProtocolResult;
Decrypt a message on one side, as transmitted from the other side
- this method will return the encrypted text with no actual decryption
function ProcessHandshake(const MsgIn: RawUtf8; out MsgOut: RawUtf8): TProtocolResult;
Initialize the communication by exchanging some client/server information
- this method will return sprUnsupported
procedure Encrypt(const aPlain: RawByteString; out aEncrypted: RawByteString);
Encrypt a message on one side, ready to be transmitted to the other side
- this method will return the plain text with no actual encryption
TProtocolAes = class(TInterfacedObject)
Implements a secure protocol using symmetric AES encryption
- as used e.g. by 'synopsebinary' WebSockets protocol
- a secret password is shared between client and server
- this class will maintain two TAesAbstract instances, one for encryption and another for decryption, with PKCS7 padding and no MAC/AEAD validation
constructor Create(aClass: TAesAbstractClass; const aKey; aKeySize: cardinal); reintroduce; virtual;
[false]=decrypt [true]=encrypt initialize this encryption protocol with the given AES settings
- 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
- if aClass is nil, TAesFast[mCtr] will be used as default
- AEAD Cfc,mOfc,mCtc,mGcm modes will be rejected since unsupported
constructor CreateFrom(aAnother: TProtocolAes); reintroduce; virtual;
Will create another instance of this communication protocol
destructor Destroy; override;
Finalize the encryption
function Clone: IProtocol;
Will create another instance of this communication protocol
function Decrypt(const aEncrypted: RawByteString; out aPlain: RawByteString): TProtocolResult;
Decrypt a message on one side, as transmitted from the other side
- wrapper around fAes[false].DecryptPkcs7(), so does not support AEAD yet
function ProcessHandshake(const MsgIn: RawUtf8; out MsgOut: RawUtf8): TProtocolResult;
Initialize the communication by exchanging some client/server information
- this method will return sprUnsupported
procedure Encrypt(const aPlain: RawByteString; out aEncrypted: RawByteString);
Encrypt a message on one side, ready to be transmitted to the other side
- wrapper around fAes[true].EncryptPkcs7(), so does not support AEAD yet
TBinaryCookieGenerator = object(TObject)
Efficient thread-safe cookie generation
- you can see it as a JWT-Of-The-Poor: faster to parse and validate its content, and with very efficience binary-based serialization
- stores a session ID, cookie name, and encryption and signature keys
- can optionally store any associated record as efficient binary
- it is NOT cryptographic secure, because cookies are not, but it is strong enough to avoid most attacks, and uses much less space and CPU than a JWT
CookieName: RawUtf8;
The cookie name, used for storage in the client side HTTP headers
- is not part of the Generate/Validate content, but could be used when the cookie is actually stored in HTTP headers
CrcAlgo: TCrc32Algo;
32-bit checksum algorithm used for digital signature
Crypt: array[byte] of byte;
Private random secret, used for encryption of the cookie content
CryptNonce: cardinal;
32-bit random IV used as CTR on Crypt[] secret key
DefaultTimeOutMinutes: word;
Used when Generate() has TimeOutMinutes=0
- if equals 0, one month delay is used as "never expire"
Padding: byte;
Padding byte for backward compatibility
Secret: cardinal;
32-bit secret information, used for digital signature of the cookie
SessionSequence: TBinaryCookieGeneratorSessionID;
31-bit increasing counter, to implement unique session ID
SessionSequenceStart: TBinaryCookieGeneratorSessionID;
The random initial value of the SessionSequence counter
function Generate(out Cookie: RawUtf8; TimeOutMinutes: cardinal = 0; PRecordData: pointer = nil; PRecordTypeInfo: PRttiInfo = nil): TBinaryCookieGeneratorSessionID;
Will initialize a new Base64Uri-encoded session cookie
- with an optional record data
- will return the 32-bit internal session ID and a Base64Uri cookie, ready to be used as HTTP cookie or a temporary URI
- you can supply a time period, after which the session will expire - default 0 will use DefaultTimeOutMinutes as supplied to Init()
function Load(const Saved: RawUtf8): boolean;
Unserialize the cookie generation context as serialized by Save
function Save: RawUtf8;
Allow the very same cookie to be recognized after server restart
- note that caDefault won't be persistable, because may map AesNiHash32
function Validate(const Cookie: RawUtf8; PRecordData: pointer = nil; PRecordTypeInfo: PRttiInfo = nil; PExpires: PUnixTime = nil; PIssued: PUnixTime = nil): TBinaryCookieGeneratorSessionID;
Decode a base64uri cookie and optionally fill an associated record
- return the associated session/sequence number, 0 on error
procedure Init(const Name: RawUtf8 = 'mORMot'; DefaultSessionTimeOutMinutes: cardinal = 0; SignAlgo: TCrc32Algo = caCrc32c);
Initialize ephemeral temporary cookie generation
- default crc32c is fast and secure enough on most platforms, but you may consider caDefault or caSha1 on recent SHA-NI Intel/AMD servers
TCryptAlgo = class(TSynPersistent)
Abstract class implemented e.g. by TCryptRandom/TCryptHasher/TCryptAsym
- we define a class and not a meta-class since it allows to resolve and store some engine-specific context ahead of time, for faster process
- inherited classes would dedicated New() factory methods; this parent features the internal registration feature of the known algorithms
constructor Create(const name: RawUtf8); reintroduce; virtual;
Inherited classes should properly initialize this kind of process
class function Implements(const name: array of RawUtf8): pointer; overload;
Register this class to override one or several identifiers implementation
- returns the last instance created for name[]
class function Instances: TCryptAlgos;
Return all the TCryptAlog instances matching this class type
- could be used e.g. as TCryptRandom.Instances
class function Names: TRawUtf8DynArray;
Return all the TCryptAlog instances matching this class type
- could be used e.g. as TCryptRandom.Names
class procedure Implements(csv: PUtf8Char; const suffix: RawUtf8 = ''); overload;
Register this class to override one or several identifiers implementation
property AlgoName: RawUtf8 read fName;
Process-wide case-insensitive identifier for quick lookup of the algorithms
- typical values may follow OpenSSL naming, e.g. 'MD5', 'AES-128-GCM' or 'prime256v1'
ICryptHash = interface(IInterface)
Interface as implemented e.g. by TCryptHash
function Final: RawUtf8; overload;
Compute the digest, and return it as UTF-8 hexadecimal text
function Final(digest: pointer; digestlen: PtrInt): PtrInt; overload;
Compute the digest, and return it in a memory buffer
function Update(buf: pointer; buflen: PtrInt): ICryptHash; overload;
Iterative process of a memory buffer
function Update(const buf: RawByteString): ICryptHash; overload;
Iterative process of a memory buffer
function UpdateStream(stream: TStream): Int64;
Iterative process of a stream content
- return the number of bytes hashed from the input TStream
procedure UpdateFile(const filename: TFileName);
Iterative process of a file content
TCryptInstance = class(TInterfacedObject)
Abstract class implemented e.g. by TCryptHash/TCryptCipher/TCryptKey
constructor Create(const name: RawUtf8); overload;
Resolve the name via TCryptAlgo.InternalFind() and initialize the instance
constructor Create(algo: TCryptAlgo); overload; virtual;
Initialize the instance
property CryptAlgo: TCryptAlgo read fCryptAlgo;
Access to the associated algorithm
TCryptRandom = class(TCryptAlgo)
Randomness generator parent class, as resolved by Rnd()
function Get(len: PtrInt): RawByteString; overload; virtual;
Retrieve some random bytes into a RawByteString
function Get32: cardinal; overload; virtual;
Retrieve a random 32-bit value
function Get32(max: cardinal): cardinal; overload;
Retrieve a random 32-bit value
function GetBytes(len: PtrInt): TBytes;
Retrieve some random bytes into a TBytes
function GetDouble: double;
Retrieve a random floating point value in the [0..1) range
procedure Get(dst: pointer; dstlen: PtrInt); overload; virtual; abstract;
Retrieve some random bytes into a buffer
TCryptHash = class(TCryptInstance)
Hashing/signing parent class, as returned by Hash/Sign() factories
function Update(buf: pointer; buflen: PtrInt): ICryptHash; overload; virtual; abstract;
ICryptHash methods
TCryptHasher = class(TCryptAlgo)
Hashing parent class, as resolved by Hasher()
- this class is to ensure a content as not been tempered: use Signer() to compute a digital signature from a given secret
function Full(buf: pointer; buflen: PtrInt; out digest: THash512Rec): PtrInt; overload;
One-step process of a whole memory buffer, into an binary digest
- returns the number of bytes stored in digest
function Full(const buf: RawByteString): RawUtf8; overload;
One-step process of a whole memory buffer, into an hexadecimal digest
function Full(buf: pointer; buflen: PtrInt): RawUtf8; overload;
One-step process of a whole memory buffer, into an hexadecimal digest
function FullFile(const filename: TFileName): RawUtf8;
One-step process of a whole file content, into an hexadecimal digest
function HashAlgo(out hasher: THashAlgo): boolean; virtual;
Return the THashAlgo equivalency of this hasher
- this default implementation returns false meaning that it is unknown
function New: ICryptHash; virtual; abstract;
Main factory to create a new hasher instance with this algorithm
TCryptSigner = class(TCryptAlgo)
Signing parent class, as resolved by Signer()
- in respect to TCryptHasher, requires a secret key to be supplied for safe HMAC content signature
function Full(const key, buf: RawByteString): RawUtf8; overload;
One-step process of a whole memory buffer, into an hexadecimal digest
function Full(key, buf: pointer; keylen, buflen: PtrInt): RawUtf8; overload;
One-step process of a whole memory buffer, into an hexadecimal digest
function FullFile(key: pointer; keylen: PtrInt; const filename: TFileName): RawUtf8;
One-step process of a whole file content, into an hexadecimal digest
function New(key: pointer; keylen: PtrInt): ICryptHash; virtual; abstract;
Main factory to create a new signer instance with this algorithm
function NewPbkdf2(const secret, salt: RawUtf8; rounds: integer): ICryptHash;
Main factory to create a new signer instance from PBKDF2 derivation
function Pbkdf2(const secret, salt: RawUtf8; rounds: integer; out key: THash512Rec): integer; overload; virtual; abstract;
Strong PBKDF2 derivation of a secret (and salt) using this algorithm
- returns the number of bytes computed in returned key memory
ICryptCipher = interface(IInterface)
Interface as implemented e.g. by TCryptCipher from TCryptCipherAlgo.New
function Clone: ICryptCipher;
Quickly generate a cipher with the same algorithm, direction and key
function Process(const src: TBytes; out dst: TBytes; const aeadinfo: TByteDynArray = nil): boolean; overload;
General encryption/decryption method using TBytes buffers
- use TByteDynArray for aeadinfo because TBytes raises a Delphi XE compiler bug - it should be assignment compatible with any TBytes value
function Process(const src: RawByteString; out dst: RawByteString; const aeadinfo: RawByteString = ''): boolean; overload;
General encryption/decryption method using RawByteString buffers
- an IV is generated at the start of this if none was specified at New()
- will do proper PKCS7 padding on the src input buffer
- return TRUE on success, FALSE if input padding or AEAD MAC is incorrect
function RawFinal(var gmac: TAesBlock): boolean;
Low-level GMAC computation for AES-GCM
- after Encrypt, fill gmac with the tag value of the data and return true
- after Decrypt, return true only if the tag value of the data match gmac
- always return false if not AES-GCM is used as algorithm
procedure RawProcess(src, dst: pointer; srclen, dstlen: PtrInt);
Low-level encryption/decryption on memory buffers
- srclen/dsstlen should match the size block of the algorithm, e.g. 16 bytes for AES or 1 byte for SHAKE (i.e. SHA-3 in XOF cipher mode)
- on AES-GCM algorithm, if dst=nil then AAD is set from src/srclen
TCryptCipherAlgo = class(TCryptAlgo)
Symmetric encryption class, as resolved by CipherAlgo()
function Decrypt(key: pointer): ICryptCipher; overload;
Main factory to create a new decryption instance with this algorithm
function Decrypt(const sign, secret, salt: RawUtf8; rounds: integer): ICryptCipher; overload;
Main factory to create a new decryption instance from PBKDF2 key derivation
function Encrypt(const sign, secret, salt: RawUtf8; rounds: integer): ICryptCipher; overload;
Main factory to create a new encryption instance from PBKDF2 key derivation
function Encrypt(key: pointer): ICryptCipher; overload;
Main factory to create a new encryption instance with this algorithm
function IsAead: boolean; virtual; abstract;
Check if this algorithm is of AEAD kind, i.e. can cipher and authenticate
- note that currently our OpenSSL AES-GCM wrapper has troubles with AEAD associated authentication so returns false: it will compute and check the GMAC of the content as expected, but only our internal 'AES-###-GCM-INT' actually supports aeadinfo <> '' in ICryptCipher.Process
function New(key: pointer; encrypt: boolean; iv: pointer = nil): ICryptCipher; overload; virtual; abstract;
Main factory to create a new instance with this algorithm
- the supplied key should match the size expected by the algorithm
function New(const hash, secret, salt: RawUtf8; rounds: integer; encrypt: boolean): ICryptCipher; overload;
Main factory to create a new instance from PBKDF2 key derivation
TCryptCipher = class(TCryptInstance)
Symmetric encryption parent class, as returned by Cipher() factory
function Clone: ICryptCipher; virtual; abstract;
ICryptCipher methods
TCryptAsym = class(TCryptAlgo)
Asymmetric public-key cryptography parent class, as returned by Asym()
function Sign(const msg, priv: RawByteString; out sig: RawByteString; const hashername: RawUtf8 = ''; const privpwd: RawUtf8 = ''): boolean; overload;
Digital signature of some message using a private key
- the message is first hashed with the default hasher of this algorithm, or the specific hashername
function Sign(const msg, priv: TBytes; out sig: TBytes; const hashername: RawUtf8 = ''; const privpwd: RawUtf8 = ''): boolean; overload;
Digital signature of some message using a private key
- the message is first hashed with the default hasher of this algorithm, or the specific hashername
function Sign(hasher: TCryptHasher; msg: pointer; msglen: PtrInt; const priv: RawByteString; out sig: RawByteString; const privpwd: RawUtf8 = ''): boolean; overload; virtual; abstract;
Digital signature of some message using a private key
- the message is first hashed with the supplied TCryptHasher
- the signature is returned in binary DER format
function Verify(const msg, pub, sig: RawByteString; const hashername: RawUtf8 = ''): boolean; overload;
Digital signature verification of some message using a public key
- the message is first hashed with the default hasher of this algorithm, or the specific hashername
function Verify(const msg, pub, sig: TBytes; const hashername: RawUtf8 = ''): boolean; overload;
Digital signature verification of some message using a public key
- the message is first hashed with the default hasher of this algorithm, or the specific hashername
function Verify(hasher: TCryptHasher; msg: pointer; msglen: PtrInt; const pub, sig: RawByteString): boolean; overload; virtual; abstract;
Digital signature verification of some message using a public key
- the message is first hashed with the supplied TCryptHasher
procedure GenerateDer(out pub, priv: RawByteString; const privpwd: RawUtf8); virtual;
Generate a public/private pair of keys in the DER binary format
procedure GeneratePem(out pub, priv: RawUtf8; const privpwd: RawUtf8); virtual;
TPemKind as defined below generate a public/private pair of keys in the PEM text format
ICryptPublicKey = interface(IInterface)
Abstract interface to a Public Key, as returned by CryptPublicKey[] factory
function GetParams(out x, y: RawByteString): boolean;
Return raw key information as used by TCryptCert.GetKeyParams
- for ECC, returns the x,y coordinates
- for RSA, x is set to the Exponent (e), and y to the Modulus (n)
- return false if there is no compliant key information in the provider
function Instance: TCryptAbstractKey;
Direct access to the class instance implementing this interface
function KeyAlgo: TCryptKeyAlgo;
The high-level asymmetric algorithm used for this public key
function Load(Algorithm: TCryptKeyAlgo; const PublicKeySaved: RawByteString): boolean;
Unserialize a public key content
- this instance should be void, i.e. just created with no prior Load
- will first try from X.509 SubjectPublicKey raw binary, then the main known PEM or DER usual serialization formats
function Seal(const Message: RawByteString; const Cipher: RawUtf8): RawByteString;
Use EciesSeal or RSA sealing, i.e. encryption with this public key
function Verify(Algorithm: TCryptAsymAlgo; Data, Sig: pointer; DataLen, SigLen: integer): boolean; overload;
Verify the RSA or ECC signature of a memory buffer
function Verify(Algorithm: TCryptAsymAlgo; const Data, Sig: RawByteString): boolean; overload;
Verify the RSA or ECC signature of a memory buffer
ICryptPrivateKey = interface(IInterface)
Abstract interface to a Private Key, as returned by CryptPrivateKey[] factory
function Generate(Algorithm: TCryptAsymAlgo): RawByteString;
Create a new private / public key pair
- this instance should be void, i.e. just created with no prior Load
- returns the associated public key binary in X.509 SubjectPublicKey format
function Instance: TCryptAbstractKey;
Direct access to the class instance implementing this interface
function KeyAlgo: TCryptKeyAlgo;
The high-level asymmetric algorithm used for this private key
function Load(Algorithm: TCryptKeyAlgo; const AssociatedKey: ICryptPublicKey; const PrivateKeySaved: RawByteString; const Password: SpiUtf8): boolean;
Unserialized the private key from DER binary or PEM text
- this instance should be void, i.e. just created with no prior Load
- also ensure the private key do match an associated public key (if not nil)
- is able to decode and potentially decrypt a serialized key, with a PKCS#8 Password for OpenSSL, and our proprietary PrivateKeyDecrypt()
function Open(const Message: RawByteString; const Cipher: RawUtf8): RawByteString;
Use EciesSeal or RSA un-sealing, i.e. decryption with this private key
function Save(AsPem: boolean; const Password: SpiUtf8): RawByteString;
Return the private key in the TCryptCertX509.Save expected format
- is able to encode and potentially encrypt a serialized key, with a PKCS#8 Password for OpenSSL, and our proprietary PrivateKeyEncrypt()
function SharedSecret(const PeerKey: ICryptPublicKey): RawByteString;
Compute the shared-secret with another public key
- by design, ECDHE is only available for ECC
function Sign(Algorithm: TCryptAsymAlgo; Data: pointer; DataLen: integer): RawByteString; overload;
Sign a memory buffer with RSA or ECC using the stored private key
function Sign(Algorithm: TCryptAsymAlgo; const Data: RawByteString): RawByteString; overload;
Sign a memory buffer with RSA or ECC using the stored private key
function ToDer: RawByteString;
Return the private key as raw binary
- follow PKCS#8 PrivateKeyInfo encoding for RSA and prime256v1
function ToSubjectPublicKey: RawByteString;
Return the associated public key as stored in a X509 certificate
TCryptAbstractKey = class(TInterfacedObjectWithCustomCreate)
Abstract parent class to TCryptPublicKey and TCryptPrivateKey
function KeyAlgo: TCryptKeyAlgo;
ICryptPublicKey methods
TCryptPublicKey = class(TCryptAbstractKey)
Abstract public key parent class, as returned by CryptPublicKey[] factory
function Load(Algorithm: TCryptKeyAlgo; const PublicKeySaved: RawByteString): boolean; virtual; abstract;
ICryptPublicKey methods
TCryptPrivateKey = class(TCryptAbstractKey)
Abstract private key parent class, as returned by the CryptPrivateKey[] factory
function Load(Algorithm: TCryptKeyAlgo; const AssociatedKey: ICryptPublicKey; const PrivateKeySaved: RawByteString; const Password: SpiUtf8): boolean; virtual;
ICryptPrivateKey methods
ECryptCert = class(ESynException)
Exception class raised by our High-Level Certificates Process
TCryptCertFields = record
Convenient wrapper of X.509 Certificate subject name X.501 fields
- not always implemented - mainly our 'syn-es256' certificate won't
- as defined in RFC 5280 Appendix A.1
Comment: RawUtf8;
NetscapeComment extension (not a field - OID 2.16.840.1.113730.1.13)
CommonName: RawUtf8;
CommonName field (OID 2.5.4.3)
Country: RawUtf8;
CountryName field (OID 2.5.4.6)
EmailAddress: RawUtf8;
Email field (OID 1.2.840.113549.1.9.1)
GivenName: RawUtf8;
GivenName field (OID 2.5.4.42)
Locality: RawUtf8;
LocalityName field (OID 2.5.4.7)
Organization: RawUtf8;
OrganizationName field (OID 2.5.4.10)
OrgUnit: RawUtf8;
OrganizationalUnitName field (OID 2.5.4.11)
State: RawUtf8;
StateOrProvinceName field (OID 2.5.4.8)
SurName: RawUtf8;
Surname field (OID 2.5.4.4)
ICryptCert = interface(IInterface)
Abstract interface to a Certificate, as returned by Cert() factory
- may be X.509 or not, OpenSSL implemented or not, e.g. for syn-es256
- note: features and serialization are not fully compatible between engines, but those high-level methods work as expected within each TCryptCertAlgo
function AsymAlgo: TCryptAsymAlgo;
The high-level asymmetric algorithm used for this certificate
function CertAlgo: TCryptCertAlgo;
The high-level asymmetric algorithm class used for this certificate
- i.e. the factory associated with this ICryptCert instance
function Compare(const Another: ICryptCert; Method: TCryptCertComparer): integer;
Compare one Certificate instance with another
function Decrypt(const Message: RawByteString; const Cipher: RawUtf8 = 'aes-128-ctr'): RawByteString;
Decrypt a message using the private key of this certificate
- not all algorithms support key transport, only RSA and ES256 by now
- 'x509-rs*' and 'x509-ps*' RSA algorithms use an OpenSSL Envelope key transport then our EVP_PKEY.RsaOpen decoding (or TRsa.Open)
- both 'x509-es256' and 'syn-es256' use our EciesOpen() ES256 decoding
- returns '' if this feature is not supported, or Message is incorrect
- certificate should have cuDataEncipherment or cuDecipherOnly usage
function Encrypt(const Message: RawByteString; const Cipher: RawUtf8 = 'aes-128-ctr'): RawByteString;
Encrypt a message using the public key of this certificate
- only RSA and ES256 algorithms do support this method by now
- 'x509-rs*' and 'x509-ps*' RSA algorithms use an OpenSSL Envelope key transport then our EVP_PKEY.RsaSeal encoding (or TRsa.Seal)
- both 'x509-es256' and 'syn-es256' use our EciesSeal() ES256 encoding
- returns '' if this feature is not supported
- certificate should have cuDataEncipherment or cuEncipherOnly usage
function Generate(Usages: TCryptCertUsages; const Subjects: RawUtf8 = ''; const Authority: ICryptCert = nil; ExpireDays: integer = 365; ValidDays: integer = -1; Fields: PCryptCertFields = nil): ICryptCert;
Create a new Certificate instance with its genuine private key
- Subjects is given as a CSV text, e.g. 'synopse.info,www.synopse.info'
- if Authority is nil, will generate a self-signed certificate, otherwise will use this Authority private key to sign the certificate
- ValidDays and ExpireDays are relative to the current time - ValidDays is -1 by default to avoid most clock synch issues
- additional information can be passed into Fields (e.g. common name)
- return self to be used as a fluent interface, e.g. calling Save(cccPrivateKeyOnly) to persist the newly created private key
function GenerateFromCsr(const Csr: RawByteString; const Authority: ICryptCert = nil; ExpireDays: integer = 365; ValidDays: integer = -1): ICryptCert;
Create a new Certificate instance from a supplied CSR
- will first unserialize and verify a self-signed CSR (PEM) content, e.g. as generated by a former TCryptCertAlgo.CreateSelfSignedCsr() call
- retrieve the Subjects and Usages as previously set to the CSR
- expect either a self-signed certificate as CSR, or a PKCS#10 CSR by the X.509 engines (OpenSSL or mormot.crypt.x509)
- if Authority is set, it will sign the certificate, and keep the public key stored in the CSR so that the requester could keep its private key
- if Authority is not set, a new key pair is generated to self-sign the certificate, and the public key is stored in the certificate, and the generated keys (public and private) can be retrieved using Save
- return self to be used as a fluent interface, or nil if unsupported
function GetAuthorityKey: RawUtf8;
The signing Authority Key Identifier (AKID) of this Certificate
- match the AKID on X.509 (so may be '' for a self-signed certificate), or the authority serial number for syn-es256 (so equals GetSubjectKey for a self-signed certificate)
function GetDigest(Algo: THashAlgo = hfSHA256): RawUtf8;
Compute the hexadecimal fingerprint of this Certificate
- is usually the hash of its binary (e.g. DER) serialization
function GetFileName: TFileName;
The last Source file name of LoadFromFile()
function GetIssuer(const Rdn: RawUtf8 = 'CN'): RawUtf8;
The Low-Level Certificate Main Issuer
- returns by default the CommonName, e.g. 'R3' from a X.509 CN= subject field
- can search another Relative Distinguished Name (RDN) e.g. 'O' or 'OU'
- if Rdn is a hash, e.g. 'SHA1'/'SHA256', will return the issuer digest
- if Rdn is 'DER', will return the raw DER issuer value of this certificate
function GetIssuerName: RawUtf8;
The High-Level Certificate Issuer
- actual text output depend on the provider used; for instance '/C=US/O=Let''s Encrypt/CN=R3' with OpenSSL, 'CN=R3, C=US, O=Let''s Encrypt' with mormot.crypt.x509 or some Baudot-encoded text with mormot.crypt.ecc
function GetIssuers: TRawUtf8DynArray;
An array of all Subject names covered by the issuer of this Certificate
- e.g. read from X.509 v3 Issuer Alternative Names extension
function GetKeyParams(out x, y: RawByteString): boolean;
Return the public BigInt values associated to the stored private key
- as BigInt binaries, ready e.g. for JWS / JSON Web Key responses
- for ECC, returns the x,y coordinates
- for RSA, x is set to the Exponent (e), and y to the Modulus (n)
- return false if there is no compliant key information in the provider
function GetNotAfter: TDateTime;
The maximum Validity timestamp of this Certificate
function GetNotBefore: TDateTime;
The minimum Validity timestamp of this Certificate
function GetPeerInfo: RawUtf8;
Verbose Certificate information, returned as huge text/JSON blob
function GetPrivateKey: RawByteString;
Retrieve the private key as raw binary, or '' if none
- actual format depend on the TCryptCert class and algorithm involved, but is usually using a DER format
- warning: don't forget FillZero() once done with this sensitive result
function GetPublicKey: RawByteString;
Retrieve the public key as raw binary
- actual format depend on the TCryptCert class and algorithm involved, but is usually using a DER format
function GetSerial: RawUtf8;
The Certificate Genuine Serial Number
- e.g. '04:f9:25:39:39:f8:ce:79:1a:a4:0e:b3:fa:72:e3:bc:9e:d6'
function GetSignatureInfo: RawUtf8;
The signature algorithm as engine-specific plain text
- the first value is the effective security bits of this algorithm
- e.g. '128 ecdsa-with-SHA256', '128 RSA-SHA256' or '128 ED25519' on OpenSSL, or '128 syn-es256' for our cryptography
function GetSubject(const Rdn: RawUtf8 = 'CN'): RawUtf8;
The Low-Level Certificate Main Subject
- returns by default the CommonName, e.g. 'synopse.info' from a X.509 CN= subject field
- can search another Relative Distinguished Name (RDN) e.g. 'O' or 'OU'
- if Rdn is a hash, e.g. 'SHA1'/'SHA256', will return the subject digest
- if Rdn is 'DER', will return the raw DER issuer value of this subject
function GetSubjectKey: RawUtf8;
The Subject Key Identifier (SKID) of this Certificate
- e.g. '14:2E:B3:17:B7:58:56:CB:AE:50:09:40:E6:1F:AF:9D:8B:14:C2:C6'
- match the SKID on X.509, or the serial number for syn-es256
function GetSubjectName: RawUtf8;
The High-Level Certificate Subject
- actual text output depend on the provider used; for instance '/C=US/O=Let''s Encrypt/CN=R3' with OpenSSL, 'CN=R3, C=US, O=Let''s Encrypt' with mormot.crypt.x509 or some Baudot-encoded text with mormot.crypt.ecc
function GetSubjects: TRawUtf8DynArray;
An array of all Subject names covered by this Certificate
- e.g. ['synopse.info', 'www.synopse.info']
- e.g. read from X.509 v3 Subject Alternative Names extension
function GetUsage: TCryptCertUsages;
The Key Usages of this Certificate
function Handle: pointer;
Access to the low-level implementation handle of the certificate
- e.g. a PX509 for OpenSsl, aTEccCertificate class for mormot.crypt.ecc, or a TX509 class for mormot.crypt.x509
- equals nil if there is no associated certificate yet, e.g. after New
function HasPrivateSecret: boolean;
Returns true if this ICryptCert instance holds a private key secret
function Instance: TCryptCert;
Access to the low-level implementation class instance
- used internally to quickly retrieve the TCryptCert from an ICryptCert
function IsAuthorizedBy(const Authority: ICryptCert): boolean;
Check if this certificate has been issued by the specified certificate
- e.g. on X.509 will efficiently check the certificate AKID with the Authority SKID
function IsEqual(const Another: ICryptCert): boolean;
Compare two Certificates, which should share the same algorithm
- will compare the internal properties and the public key, not the private key: you could e.g. use it to verify that a ICryptCert with HasPrivateSecret=false matches another with HasPrivateSecret=true
function IsSelfSigned: boolean;
Check if this certificate has been self-signed
function IsValidDate(date: TDateTime = 0): boolean;
Check GetNotBefore/GetNotAfter validity
- validate against current UTC date/time if none is specified
function IsVoid: boolean;
Returns true e.g. after TCryptCertAlgo.New but before Generate()
function JwkCompute: RawUtf8;
Returns the JSON Web Key (JWT) corresponding to the public key of this certificate
- the returned JWK is computed with no whitespace or line breaks before or after any syntaxic elements, and the required members are ordered lexicographically, as expected for a direct thumbprint
- typical pattern is '{"crv":..,"kty":"EC","x":..,"y":.. }' for ECC or '{"e":..,"kty":"RSA","n":..}' for RSA
- is implemented by default as a wrapper to GetKeyParams() results
function JwtCompute(const DataNameValue: array of const; const Issuer: RawUtf8 = ''; const Subject: RawUtf8 = ''; const Audience: RawUtf8 = ''; NotBefore: TDateTime = 0; ExpirationMinutes: integer = 0; Signature: PRawByteString = nil): RawUtf8;
Compute a new JWT for a given payload using this certificate private key
- will use the private key and Sign() to compute the signature
- this certificate should have the cuDigitalSignature usage
- same signature than the reusable TJwtAbstract.Compute() method
- returns '' on error, e.g. if HasPrivateSecret is false
function JwtVerify(const Jwt: RawUtf8; Issuer, Subject, Audience: PRawUtf8; Payload: PDocVariantData = nil; Signature: PRawByteString = nil; IgnoreError: TCryptCertValidities = []; TimeUtc: TDateTime = 0): TCryptCertValidity;
Verify a JWT signature from the public key of this certificate
- this certificate should have the cuDigitalSignature usage
- can optionally return the payload fields and/or the signature
function Load(const Saved: RawByteString; Content: TCryptCertContent = cccCertOnly; const PrivatePassword: SpiUtf8 = ''): boolean;
Load a Certificate from a Save() content
- use Content to specify the extent of the loaded value
- PrivatePassword is used for cccCertWithPrivateKey and cccPrivateKeyOnly
- warning: don't forget FillZero() once done with any sensitive input
function LoadFromFile(const Source: TFileName; Content: TCryptCertContent = cccCertOnly; const PrivatePassword: SpiUtf8 = ''): boolean;
Load a Certificate from a SaveToFile() content
- just a wrapper around the Load() method, reading a file from disk and setting the GetFileName method result value
function PrivateKeyHandle: pointer;
Access to the low-level implementation handle of the stored private key
- e.g. a PEVP_PKEY for OpenSsl, a PEccPrivateKey for mormot.crypt.ecc, or a ICryptPrivateKey weak instance for mormot.crypt.x509
- equals nil if there is no associated private key
function Save(Content: TCryptCertContent = cccCertOnly; const PrivatePassword: SpiUtf8 = ''; Format: TCryptCertFormat = ccfBinary): RawByteString;
Serialize the Certificate as reusable content
- use Content to specify the extent of the returned value; e.g. after Generate, this ICryptCert instance will contain both the public and private key, so cccCertWithPrivateKey and cccPrivateKeyOnly content could be used, with an optional PrivatePassword, to save the private key
- will use binary by default, but you can set e.g. ccfPem if needed
- warning: don't forget FillZero() once done with any sensitive result
function SetPrivateKey(const saved: RawByteString): boolean;
Include the raw private key as saved by GetPrivateKey
- the private key should match with the public key of the Certificate
- any previously stored private key will first be erased, therefore SetPrivateKey('') will wipe any private key currently stored in memory
- warning: don't forget FillZero() once done with this sensitive input
function SharedSecret(const pub: ICryptCert): RawByteString;
Compute a shared secret from the private key of this certificate and the public key of another certificate
- used e.g. to initialize network encryption with no key transmission
- returns '' if this algorithm doesn't support this feature (e.g. RSA)
- both current and pub certificates should have cuKeyAgreement usage
- the caller should always apply a cryptographic hash over the result
function Sign(Data: pointer; Len: integer; Usage: TCryptCertUsage = cuDigitalSignature): RawByteString; overload;
Compute a digital signature of some digital content
- memory buffer will be hashed then signed using the private secret key of this certificate instance
- you could later verify this text signature according to the public key of this certificate, using ICryptCert.Verify() or ICryptStore.Verify()
- this certificate should have the cuDigitalSignature usage
- returns '' on failure, e.g. if this Certificate has no private key
- returns the binary signature of the Data buffer on success
function Sign(const Data: RawByteString; Usage: TCryptCertUsage = cuDigitalSignature): RawByteString; overload;
Compute a digital signature of some digital content
- will use the private key of this certificate
- just a wrapper around the overloaded Sign() function
function Verify(const Signature, Data: RawByteString; IgnoreError: TCryptCertValidities = []; TimeUtc: TDateTime = 0): TCryptCertValidity; overload;
Verify a digital signature of some digital content
- just a wrapper around the overloaded Verify() function
function Verify(const Authority: ICryptCert; IgnoreError: TCryptCertValidities = []; TimeUtc: TDateTime = 0): TCryptCertValidity; overload;
Verify another certificate signature with this certificate public key (if self-signed), or a supplied Authority reference
- Authority certificate should have the cuKeyCertSign usage
- mormot.crypt.x509 will cache the last valid Authority for fast process
function Verify(Sign, Data: pointer; SignLen, DataLen: integer; IgnoreError: TCryptCertValidities = []; TimeUtc: TDateTime = 0): TCryptCertValidity; overload;
Verify a digital signature of some digital content
- will use the public key of this certificate
- this certificate should have the cuDigitalSignature usage
- see ICryptStore.Verify() for a complete CA chain validation
- depending on the engine, some errors can be ignored, e.g. cvWrongUsage and cvDeprecatedAuthority with X.509 certificates
- certificate expiration date can be specified instead of current time
procedure SaveToFile(const Dest: TFileName = ''; Content: TCryptCertContent = cccCertOnly; const PrivatePassword: SpiUtf8 = ''; Format: TCryptCertFormat = ccfBinary);
Serialize the Certificate as reusable file content
- just a wrapper to store the Save() method result as a file
- if Dest is '' then GetFileName value from last LoadFromFile() is used
procedure Sign(const Authority: ICryptCert); overload;
Sign this certificate with the private key of one CA
- Authority certificate should have the cuKeyCertSign usage
TCryptCert = class(TCryptInstance)
Abstract parent class to implement ICryptCert, as returned by Cert() factory
- you should never use this class, but the ICryptCert instances
- type is only defined here to be inherited with the actual provider units
function Generate(Usages: TCryptCertUsages; const Subjects: RawUtf8; const Authority: ICryptCert; ExpireDays, ValidDays: integer; Fields: PCryptCertFields): ICryptCert; virtual; abstract;
ICryptCert methods
TCryptCertAlgo = class(TCryptAlgo)
Abstract parent class for ICryptCert factories
function CreateSelfSignedCsr(const Subjects: RawUtf8; const PrivateKeyPassword: SpiUtf8; var PrivateKeyPem: RawUtf8; Usages: TCryptCertUsages = []; Fields: PCryptCertFields = nil): RawUtf8; virtual;
Factory for a new Certificate Signing Request over a set of (DNS) names
- if PrivateKeyPem is void, will generate a new public/private key pair, then forge a request with this new public key
- if PrivateKeyPem is supplied, will use it as public key
- you can optionally specify the expected usages and information fields
- returns both the private key and the self-signed CSR as PEM
- by default, this class returns a self-signed certificate as CSR, but will be overriden by our X.509 engines (OpenSSL and mormot.crypt.x509) to return a proper PKCS#10 standard CSR, in a Let's Encrypt compatible way
function FromHandle(Handle: pointer): ICryptCert; virtual; abstract;
Low-level factory directly from the raw implementation handle
- e.g. a PX509 for OpenSsl, or TEccCertificate for mormot.crypt.ecc
- warning: ensure Handle is of the expected type, otherwise it will GPF
- includes the private key for TEccCertificate, or not for OpenSsl
- note that this Handle will be owned by the new ICryptCert instance, so you should not make FromHandle(another.Handle)
function Generate(Usages: TCryptCertUsages; const Subjects: RawUtf8; const Authority: ICryptCert = nil; ExpireDays: integer = 365; ValidDays: integer = -1; Fields: PCryptCertFields = nil): ICryptCert;
Factory to generate a new Certificate instance
- just a wrapper around New and ICryptCert.Generate()
- Subjects is a mandatory field as with X.509
function GenerateFromCsr(const Csr: RawByteString; const Authority: ICryptCert = nil; ExpireDays: integer = 365; ValidDays: integer = -1): ICryptCert; virtual;
Factory to generate a new Certificate instance from a supplied CSR
- will first unserialize and verify a self-self CSR PEM content, as generated by a former CreateSelfSignedCsr() call
- retrieve the Subjects and Usages as previously set to the CSR, enabling only UsagesFilter items if set
- this default implementation expects the CSR to be a self-signed certificate
function JwtName: RawUtf8;
Return the corresponding JWT algorithm name, computed from AsymAlgo
- e.g. 'ES256' for 'x509-es256' or 'syn-es256-v1'
function Load(const Saved: RawByteString; Content: TCryptCertContent = cccCertOnly; const PrivatePassword: SpiUtf8 = ''): ICryptCert;
Factory to load a Certificate from a ICryptCert.Save() content
- PrivatePassword is needed if the input contains a private key
- will only recognize and support the ccfBinary and ccfPem formats
- return nil if Saved content was not in the expected format/algorithm
function New: ICryptCert; virtual; abstract;
Should be set by the overriden constructor main factory to create a new Certificate instance with this algorithm
- return a new void instance, ready to call e.g. ICryptCert.Load
property AsymAlgo: TCryptAsymAlgo read fCaa;
The asymmetric algorithm used for these certificates
ICryptStore = interface(IInterface)
Abstract interface to a Certificates Store, as returned by Store() factory
- may be X.509 or not, OpenSSL implemented or not
function Add(const cert: ICryptCert): boolean; overload;
Register a certificate in the internal certificate chain
- returns false e.g. if the certificate was not valid, or its serial was already part of the internal list, or not of a compatible class
- self-signed certificates could be included - but add them with caution because they will become root CA, or "trust anchors" in X.509 terminology
- the Certificate should have cuCA or cuKeyCertSign typical usages
function Add(const cert: array of ICryptCert): TRawUtf8DynArray; overload;
Register several certificates in the internal certificate chain
- returns the serials of added certificate(s)
function AddFromBuffer(const Content: RawByteString): TRawUtf8DynArray;
Load and register a certificate or certificate chain from a memory buffer
- returns the serials of added certificate(s)
- if there are any valid CRL, they will also be loaded to the store
function AddFromFile(const FileName: TFileName): TRawUtf8DynArray;
Load and register a certificate file or file chain
- returns the serials of added certificate(s)
- the Certificate(s) should have cuCA or cuKeyCertSign typical usages
- if there are any valid CRL, they will also be loaded to the store
function AddFromFolder(const Folder: TFileName; const Mask: TFileName = FILES_ALL; Recursive: boolean = false): TRawUtf8DynArray;
Search and register all certificate files from a given folder
- returns the serials of added certificate(s)
- the Certificate(s) should have cuCA or cuKeyCertSign typical usages
- if there are any valid CRL, they will also be loaded to the store
function Cache: TCryptCertCache;
Get the associated ICryptCert instances cache
- use Cache.Load() to retrieve a ICryptCert from its DER/PEM content
function Count: integer;
How many trusted certificates are currently stored
function CrlCount: integer;
How many CRLs are currently stored
function DefaultCertAlgo: TCryptCertAlgo;
Return the prefered algo to be used with this store
- call e.g. CertAlgo.New to prepare a new ICryptCert to add to this store
function FindOne(const Value: RawByteString; Method: TCryptCertComparer): ICryptCert;
Search for a trusted certificate from a given attribute
- return the first certificate matching a given value
- warning: some engines don't support this advanced search feature
function GetBySerial(const Serial: RawUtf8): ICryptCert;
Search for a trusted certificate from its (hexadecimal) identifier
- note that in the X.509 context, serial may be duplicated, so it is safer to use GetBySubjectKey()
function GetBySubjectKey(const Key: RawUtf8): ICryptCert;
Search for a trusted certificate from its (hexadecimal) Subject Key Identifier
- e.g. '14:2E:B3:17:B7:58:56:CB:AE:50:09:40:E6:1F:AF:9D:8B:14:C2:C6'
- search the SKID on X.509, or the serial number for syn-es256
function IsRevoked(const cert: ICryptCert): TCryptCertRevocationReason;
Quickly check if a given certificate is part of the internal CRL
- returns crrNotRevoked is the serial is not known as part of the CRL
- returns the reason why this certificate has been revoked otherwise
function IsValid(const cert: ICryptCert; date: TDateTime = 0): TCryptCertValidity;
Check if the certificate is valid, against known certificates chain
- will check internal properties of the certificate (e.g. validity dates), and validate the stored digital signature according to the public key of the associated signing authority, as found within the store, for as many level as needed until a self-signed "root anchor" is reached
function IsValidChain(const chain: ICryptCertChain; date: TDateTime = 0): TCryptCertValidity;
Check a certificate against its supplied chain and known certificates
- with a large PKI as on the Internet, a certificates chain is usually supplied for authentication with only some "trust anchors" certificates
- this overloaded method accept a chain as input, so that the first item is to be validated against the other members of the chain as intermediates (not part of the store), then eventually validating the last items of the chain with the store trusted certificates
function Load(const Saved: RawByteString): boolean;
Load a Certificates Store from a ICryptStore.Save memory buffer content
function Revoke(const Cert: ICryptCert; Reason: TCryptCertRevocationReason; RevocationDate: TDateTime = 0): boolean;
Add a Certificate information to the global Certificate Revocation List
- on some engines (our internal ECC, but not OpenSSL), Reason=crrNotRevoked could be used to unregister a certificate revocation
function Save: RawByteString;
Serialize the Certificates Store into a memory buffer
- may be our TEccCertificateChain proprietary binary, or a chain of X.509 Certificates and CRLs in PEM text format
function Verify(const Signature: RawByteString; Data: pointer; Len: integer; IgnoreError: TCryptCertValidities = []; TimeUtc: TDateTime = 0): TCryptCertValidity;
Verify the digital signature of a given memory buffer
- this signature should have come from a previous ICryptCert.Sign() call
- will check internal properties of the certificate (e.g. validity dates), and validate the stored signature according to the public key of the associated signing authority (which should be in this Store)
- warning: only supported by our 'syn-store' algorithm: OpenSSL Store has no way to lookup the X.509 certificate which actually signed the buffer
procedure Clear;
Delete all stored Certificates or CRL information
TCryptStore = class(TCryptInstance)
Abstract parent class to implement ICryptCert, as returned by Cert() factory
procedure Clear; virtual; abstract;
ICryptStore methods
TCryptStoreAlgo = class(TCryptAlgo)
Abstract parent class for ICryptStore factories
function New: ICryptStore; virtual; abstract;
Main factory to create a new Store instance with this engine
function NewFrom(const Binary: RawByteString): ICryptStore; virtual;
Main factory to create a new Store instance from saved Binary
TCryptCertAbstractList = class(TSynPersistent)
Abstract parent of TCryptCertList and TCryptCertCache storage classes
destructor Destroy; override;
Finalize the ICryptCert storage
function Find(const Value: RawByteString; Method: TCryptCertComparer = ccmSerialNumber; MaxCount: integer = 0): ICryptCerts; virtual;
Search the internal list for a given attribute
- return all the certificates matching a given value
- will use brute-force O(n) search algorithm with lockfree multi-read
function FindOne(const Value: RawByteString; Method: TCryptCertComparer = ccmSerialNumber): ICryptCert; virtual;
Search the internal list for a given attribute
- return the first certificate matching a given value
function List: ICryptCerts;
Return a copy of the internal list items
procedure SaveToPem(W: TTextWriter; WithExplanatoryText: boolean = false);
Persist all stored Certificates in PEM format
property Count: integer read GetCount;
How many instances are currently stored in this instance
property CryptCertClass: TCryptCertClass read fCryptCertClass;
The class of TCryptCert currently stored in this list
- is either set in the overriden constructor, or retrieved at runtime
property RawList: TSynDictionary read fList;
Direct low-level to the internal raw dictionary
- store a hash table of ICryptCert values
- for TCryptCertCache, RawByteString keys are DER certificates content
- for TCryptCertList, RawByteString keys are SKID/GetSubjectKey binary
- use rather the List function if you just want to access the stored values
TCryptCertList = class(TCryptCertAbstractList)
Store several ICryptCert instances
- those instances are likely to come from a TCryptCertCache holder
- maintain a hashed index of ICryptCert.GetSubjectKey values for fast certification path validation e.g. during ICryptStore.IsValid
constructor Create; override;
Initialize the ICryptCert storage
function Add(const Cert: ICryptCert): boolean; overload;
Include once a X.509 Certificate instance to the internal list
- return false if its GetSubjectKey was already present
function DeleteBySubjectKey(const Key: RawUtf8): boolean;
Remove a ICryptCert from the list using its indexed GetSubjectKey
function Find(const Value: RawByteString; Method: TCryptCertComparer = ccmSerialNumber; MaxCount: integer = 0): ICryptCerts; override;
Search the internal list for a given attribute
- overriden to let ccmSubjectKey search use the hashed index
function FindBySubjectKey(const Key: RawUtf8): ICryptCert;
Search the list for a ICryptCert.GetSubjectKey using a hashed index
- i.e. the Subject Key Identifier (SKID) of a X.509 Certificate or the serial number for syn-ecc
function FindBySubjectKeyRaw(const Key: RawByteString): ICryptCert;
Search the list for binary ICryptCert.GetSubjectKey using a hashed index
- could be used instead of FindBySubjectKey() if the key is already decoded into its HumanHexToBin() raw binary format (as stored internally)
procedure Add(const Cert: array of ICryptCert); overload;
Include once several X.509 Certificate instances to the internal list
TCryptCertCache = class(TCryptCertAbstractList)
Abstract class to cache ICryptCert instances, from their DER/binary
- should be overriden to let its InternalLoad() method be implemented
- to speed up typical PKI process, no DER parsing would be necessary
- this class is thread-safe and will flush its oldest entries automatically
- use TCryptCertCacheX509 or TCryptCertCacheOpenSsl, not this abstract class
constructor Create(TimeOutSeconds: integer = 10 * 6); reintroduce;
Instantiate a ICryptCert instances cache
- you can have several TCryptCertCache, dedicated to each bounded context
- by default, internal cache will clean up instances with RefCnt = 1 after 10 min of inactivity
function Find(const Value: RawByteString; Method: TCryptCertComparer = ccmSerialNumber; MaxCount: integer = 0): ICryptCerts; override;
Search the internal list for a given attribute
- overriden to let ccmBinary search use the hashed index
function Load(const Cert: array of RawByteString): ICryptCerts; overload;
Retrieve a chain of ICryptCert instances from an array of DER input
- any invalid Cert[] will just be ignored and not part of the result
function Load(const Cert: RawByteString): ICryptCert; overload;
Retrieve a potentially shared ICryptCert instance from DER or PEM input
- returns nil if the input is not correct or not supported
- will guess the proper TCryptCertAlgoX509 to use for the ICryptCert
function LoadPem(const Pem: RawUtf8): ICryptCerts;
Retrieve a chain of ICryptCert instances from a PEM input
- any invalid chunk in the PEM will be ignored and not part of the result
function NewList(const Pem: RawUtf8): TCryptCertList; overload;
Allocate a new TCryptCertList instance in the context of this cache
- filling the list with certificates from some PEM input
function NewList: TCryptCertList; overload; virtual;
Allocate a new TCryptCertList instance in the context of this cache
TCryptCertPerUsage = object(TObject)
Maintains a list of ICryptCert, easily reachable per TCryptCertUsage
- could be seen as a basic certificates store or "PKI of the poor" (tm)
- per usage lookup is in O(1) so faster than iterative ICryptCert.GetUsage
- also features simple PEM / binary serialization methods
- no CRL nor complex intermediate certificates lookup are available
- should be initialized by Clear at startup, or zeroed as a class field
Index: array[TCryptCertUsage] of byte;
Lookup table used by GetUsage()/PerUsage()
- 0 means no certificate, or store the index in List[] + 1
List: ICryptCerts;
The stored ICryptCert Instances
Usages: TCryptCertUsages;
All usages currently stored in this list
function Add(const cert: ICryptCert): TCryptCertUsages;
Register the certificate to the internal list
- returns the duplicated usages
- if no usage(s) was already set as in the added one, returns []
- if another certificate has already an usage, it is overwritten and the duplicated usage(s) are returned
- so the typical pattern is to add the certificate in inverse order of authority, i.e. first the CA as root cuKeyCertSign, then the less specialized cuKeyCertSign certificates - so that the weaker certificate is returned by PerUsage/GetUsage for the actual process
function AsBinary: RawByteString;
Save all items as a cccCertOnly binary blob of certificates
- binary layout is TBufferWriter.WriteVar() of all DER serialization
function AsPem: RawUtf8;
Save all items as a cccCertOnly CRLF separated list of PEM certificates
function FromBinary(algo: TCryptCertAlgo; const bin: RawByteString): TCryptCertUsages;
Clear and load a binary blob of certificates saved by AsBinary
- returns the duplicated usages found during adding certificates
function FromPem(algo: TCryptCertAlgo; const pem: RawUtf8): TCryptCertUsages;
Clear and load a CRLF separated list of PEM certificates
- returns the duplicated usages found during adding certificates
function GetUsage(u: TCryptCertUsage; var cert: ICryptCert): boolean;
Fast lookup of a certificate per its usage
- i.e. returns the last/weakest certificate having the supplied usage
function IsVoid: boolean;
Quickly check if there is no stored certificate
function PerUsage(u: TCryptCertUsage): ICryptCert;
Fast lookup of a certificate per its usage
- i.e. returns the last/weakest certificate having the supplied usage
procedure Clear;
Reset all storage and indexes
TX509Parsed = record
Output of the X509Parse() function
- contains X.509 certificate main properties and binary public key
EStuffExe = class(ESynException)
Exception raised by StuffExeCertificate() in case of processing error
ICryptCertChain = ICryptCerts;
Holds a Certificate chain, the first being the main certificate
ICryptCerts = array of ICryptCert;
A dynamic array of Certificate interface instances
IProtocolDynArray = array of IProtocol;
Stores a list of IProtocol instances
PICryptCert = ^ICryptCert;
A pointer to a Certificate interface instance
PSynSigner = ^TSynSigner;
Reference to a TSynSigner wrapper object
PSynUniqueIdentifierBits = ^TSynUniqueIdentifierBits;
Points to a 64-bit integer identifier, as computed by TSynUniqueIdentifierGenerator
- may be used to access the identifier internals, from its stored Int64 or TSynUniqueIdentifier value
TAsnObject = RawByteString;
We defined our own type to hold an ASN object binary
TAuthServerResult = ( asrUnknownUser, asrIncorrectPassword, asrRejected, asrMatch );
The result of IBasicAuthServer.CreckCredential() internal method
TBinaryCookieGeneratorSessionID = type integer;
A 31-bit increasing sequence used for TBinaryCookieGenerator sessions
TCertDer = type RawByteString;
A certificate (typically X.509) encoded as binary
TCertPem = type RawUtf8;
A certificate (typically X.509) encoded as PEM / text
TCrc32Algo = ( caCrc32c, caCrc32, caAdler32, caxxHash32, caFnv32, caDefault, caMd5, caSha1 );
The known 32-bit crc algorithms as returned by CryptCrc32()
- ccaAdler32 requires mormot.lib.z.pas to be included
- caDefault may be AesNiHash32(), therefore not persistable between executions, since is randomly seeded at process startup
- some cryptographic-level hashes are truncated to 32-bit - caSha1 could leverage Intel SHA HW opcodes to achieve pretty good performance
TCryptAsymAlgo = ( caaES256, caaES384, caaES512, caaES256K, caaRS256, caaRS384, caaRS512, caaPS256, caaPS384, caaPS512, caaEdDSA );
The supported asymmetric algorithms, following the JWT high-level naming
- caaES256, caaES384, caaES512 and caaES256K match OpenSSL EVP_PKEY_EC with prime256v1, NID_secp384r1, NID_secp521r1 and NID_secp256k1 curves
- caaRS256, caaRS384 and caaRS512 match OpenSSL EVP_PKEY_RSA with SHA-256, SHA-384 and SHA-512 digest method
- caaPS256, caaPS384 and caaPS512 match OpenSSL EVP_PKEY_RSA_PSS with SHA-256, SHA-384 and SHA-512 digest method
- caaEdDSA match OpenSSL EVP_PKEY_ED25519 curve
- mormot.crypt.ecc unit implements caaES256 with native pascal
- mormot.crypt.rsa unit implements all caaRS256 .. caaPS512 algorithms
- mormot.crypt.openssl unit implements all those algorithms
- our RSA wrappers generate with RSA_DEFAULT_GENERATION_BITS = 2048-bit, but our units can read and manage any other size of existing certificates generated e.g. by OpenSSL or our mormot.crypt.rsa unit
TCryptAsymAlgos = set of TCryptAsymAlgo;
Set of supported asymmetric algorithms
TCryptCertClass = class of TCryptCert;
Meta-class of the abstract parent to implement ICryptCert interface
TCryptCertComparer = ( ccmInstance, ccmSerialNumber, ccmSubjectName, ccmIssuerName, ccmSubjectCN, ccmIssuerCN, ccmSubjectKey, ccmAuthorityKey, ccmSubjectAltName, ccmIssuerAltName, ccmUsage, ccmBinary, ccmSha1, ccmSha256 );
How ICryptCert.Compare() should compare two certificates
- ccmSubjectCN/ccmIssuerCN/ccmSubjectAltName/ccmIssuerAltName lookup is case-insensitive
TCryptCertContent = ( cccCertOnly, cccCertWithPrivateKey, cccPrivateKeyOnly );
The ICryptCert.Load/Save content
- cccCertOnly will store the certificate as PEM or DER with its public key
- cccCertWithPrivateKey will include the private key to the output, possibly protected by a password
- cccPrivateKeyOnly will export the raw private key with no password
TCryptCertFormat = ( ccfBinary, ccfPem, ccfHexa, ccfBase64, ccfBase64Uri );
ICryptCert.Save possible output formats
- 'syn-es256' from mormot.crypt.ecc certificate will use its own proprietary format, i.e. SaveToBinary/SaveToSecureBinary for ccfBinary, or non-standard '-----BEGIN/END SYNECC CERTIFICATE-----' headers for ccfPem
- 'x509-rs256'..'x509-es256' from mormot.crypt.openssl will use the standard x509 format, as DER (or PKCS12 if PrivatePassword is set) for ccfBinary, or PEM for ccfPEM (concatenating the private key if PrivatePassword is set)
- ccfHexa, ccfBase64 and ccfBase64Uri will use the ccfBinary output, then encode it as Hexadecimal or Base-64 (URI)
TCryptCertRevocationReason = ( crrUnspecified, crrCompromised, crrAuthorityCompromised, crrUnAffiliated, crrSuperseded, crrReplaced, crrTempHold, crrNotRevoked, crrRemoved, crrWithdrawn, crrServerCompromised );
The RFC5280-compatible reasons why a Certificate could be revoked
- used for each item in a Certificate Revocation List (CRL)
- crrNotRevoked (item 7) is not used in the RFC, and used internally here
TCryptCertUsage = ( cuCA, cuEncipherOnly, cuCrlSign, cuKeyCertSign, cuKeyAgreement, cuDataEncipherment, cuKeyEncipherment, cuNonRepudiation, cuDigitalSignature, cuDecipherOnly, cuTlsServer, cuTlsClient, cuEmail, cuCodeSign, cuOcspSign, cuTimestamp );
The known Key Usages for a given Certificate
- is an exact match of TX509Usage enumerate in mormot.lib.openssl11.pas and TWinCertUsage in mormot.lib.sspi
- usually stored as a 16-bit set
TCryptCertUsages = set of TCryptCertUsage;
Set of Key Usages for a given Certificate - stored as a 16-bit word
- stored as its own 16-bit value, with CU_ALL = 65535
TCryptCertValidities = set of TCryptCertValidity;
(11) a set of Digital Signature results
TCryptCertValidity = ( cvUnknown, cvValidSigned, cvValidSelfSigned, cvNotSupported, cvBadParameter, cvCorrupted, cvInvalidDate, cvUnknownAuthority, cvDeprecatedAuthority, cvInvalidSignature, cvRevoked, cvWrongUsage );
(10) the Digital Signature results for a given Certificate
- is an exact match of TEccValidity enumerate in mormot.crypt.ecc256r1.pas
- see CV_VALIDSIGN constant for verification success
TCryptKeyAlgo = ( ckaNone, ckaRsa, ckaRsaPss, ckaEcc256, ckaEcc384, ckaEcc512, ckaEcc256k, ckaEdDSA );
The algorithms supported by a ICryptPublicKey/ICryptPrivateKey
- does not match TCryptAsymAlgo because ckaRsa/ckaRsaPss do not define the hash algorithm needed, so dedicated caaRSxxx/caaPSxxx items are needed
TCryptPrivateKeyClass = class of TCryptPrivateKey;
Abstract public key metaclass class, as stored by the CryptPrivateKey factory
TCryptPublicKeyClass = class of TCryptPublicKey;
Abstract public key metaclass, as stored by the CryptPublicKey[] factory
TCryptStoreClass = class of TCryptStore;
Meta-class of the abstract parent to implement ICryptStore interface
TDigestAlgo = ( daUndefined, daMD5, daMD5_Sess, daSHA256, daSHA256_Sess, daSHA512_256, daSHA512_256_Sess, daSHA3_256, daSHA3_256_Sess );
The Digest access authentication supported algorithms
- match the three official algorithms as registered by RFC 7616, with the addition of the unstandard (but safe) SHA3-256 algorithm
TDigestAuthServerClass = class of TDigestAuthServer;
Meta-class of server side Digest access authentication
THashAlgo = ( hfMD5, hfSHA1, hfSHA256, hfSHA384, hfSHA512, hfSHA512_256, hfSHA3_256, hfSHA3_512 );
Hash algorithms available for HashFile/HashFull functions and TSynHasher object
THashAlgos = set of THashAlgo;
Set of algorithms available for HashFile/HashFull functions and TSynHasher object
TOnAuthServer = function(Sender: TObject; const User: RawUtf8): boolean of object;
Callback event used by TBasicAuthServer.OnBeforeAuth/OnAfterAuth
- allow to reject an user before or after its credentials are checked
- should return true to continue, or false to abort the authentication and let TBasicAuthServer.CheckCredential return asrRejected
TOnDigestServerAuthGetUserHash = function( const User, Realm: RawUtf8; out HA0: THash512Rec): TAuthServerResult of object;
Callback event able to return the HA0 binary from a username
- called by DigestServerAuth() e.g. to lookup from a local .htdigest file
- should return the hash size in bytes, or 0 if User is unknown
- is typically implemented via DigestHA0() wrapper function
TPemKind = ( pemUnspecified, pemCertificate, pemCrl, pemPrivateKey, pemPublicKey, pemRsaPrivateKey, pemRsaPublicKey, pemEcPrivateKey, pemEcPublicKey, pemEncryptedPrivateKey, pemCertificateRequest, pemDhParameters, pemEcParameters, pemSsh2EncryptedPrivateKey, pemSsh2PublicKey, pemSynopseSignature, pemSynopseCertificate, pemSynopseUnencryptedPrivateKey, pemSynopseEccEncryptedPrivateKey, pemSynopseRsaEncryptedPrivateKey, pemSynopsePrivateKeyAndCertificate );
The DerToPem() supported contents of a PEM text instance
- pemSynopseSignature, pemSynopseCertificate and pemSynopseCertificateAndPrivateKey follow our proprietary mormot.crypt.ecc format, so are not compatible with other libraries
TProtocolAesClass = class of TProtocolAes;
Class-reference type (metaclass) of an AES secure protocol
TProtocolResult = ( sprSuccess, sprBadRequest, sprUnsupported, sprUnexpectedAlgorithm, sprInvalidCertificate, sprInvalidSignature, sprInvalidEphemeralKey, sprInvalidPublicKey, sprInvalidPrivateKey, sprInvalidMAC );
Possible return codes by IProtocol classes
TSignAlgo = ( saSha1, saSha256, saSha384, saSha512, saSha3224, saSha3256, saSha3384, saSha3512, saSha3S128, saSha3S256 );
The HMAC/SHA-3 algorithms known by TSynSigner
- HMAC/SHA-1 is considered unsafe, HMAC/SHA-2 are well proven, and HMAC/SHA-3 is newer but strong, so a good candidate for safety
- saSha3S128 is used by default, i.e. SHA-3 in SHAKE_128 mode
TStreamRedirectSynHasherClass = class of TStreamRedirectSynHasher;
Meta-class of TStreamRedirectSynHasher
- to access e.g. GetAlgo/GetHashFileExt class methods
TSynAuthenticationClass = class of TSynAuthenticationAbstract;
Class-reference type (metaclass) of an authentication class
TSynUniqueIdentifier = type TID;
64-bit integer unique identifier, as computed by TSynUniqueIdentifierGenerator
- they are increasing over time (so are much easier to store/shard/balance than UUID/GUID), and contain generation time and a 16-bit process ID
- mapped by TSynUniqueIdentifierBits memory structure
- may be used on client side for something similar to a MongoDB ObjectID, but compatible with TOrm.ID: TID properties
TSynUniqueIdentifierGenerators = array of TSynUniqueIdentifierGenerator;
Hold a dynamic array of TSynUniqueIdentifierGenerator instances
TSynUniqueIdentifierObfuscated = type RawUtf8;
A 24 chars cyphered hexadecimal string, mapping a TSynUniqueIdentifier
- has handled by TSynUniqueIdentifierGenerator.ToObfuscated/FromObfuscated
TSynUniqueIdentifierProcess = type word;
16-bit unique process identifier, used to compute TSynUniqueIdentifier
- each TSynUniqueIdentifierGenerator instance is expected to have its own unique process identifier, stored as a 16-bit integer 0..65535 value
ASN1_BOOL = $01;
Base ASN.1 types
ASN1_BOOLEAN_NONE: array[boolean] of TAsnObject = ( '', RawByteString(#$01#$01#$ff));
Encode a boolean value into nothing or true as ASN.1 binary
- as used e.g. in X.509 v3 extensions optional fields
ASN1_BOOLEAN_VALUE: array[boolean] of TAsnObject = ( RawByteString(#$01#$01#$00), RawByteString(#$01#$01#$ff));
Encode a boolean value into ASN.1 binary
ASN1_CL_APP = $40;
Application-specific class type bitmask
ASN1_CL_CTR = $20;
Constructed class type bitmask
ASN1_CL_CTX = $80;
Context-specific class type bitmask
ASN1_CL_PRI = $c0;
Private class type bitmask
ASN1_CTC0 = $a0;
Context-specific class, constructed, tag #n
ASN1_CTX0 = $80;
Context-specific class, tag #n
ASN1_IPADDR = $40;
Common ASN1_CL_APP types
ASN1_NULL_VALUE: TAsnObject = RawByteString(#$05#$00);
Encode a null value into ASN.1 binary
ASN1_OID_HASH: array[THashAlgo] of RawUtf8 = ( '1.2.840.113549.2.5', '1.3.14.3.2.26', '2.16.840.1.101.3.4.2.1', '2.16.840.1.101.3.4.2.2', '2.16.840.1.101.3.4.2.3', '2.16.840.1.101.3.4.2.6', '2.16.840.1.101.3.4.2.8', '2.16.840.1.101.3.4.2.10');
The OID of the supported hash algorithms, decoded as text
ASN1_OID_X962_PUBLICKEY = '1.2.840.10045.2.1';
HfMD5 hfSHA1 hfSHA256 hfSHA384 hfSHA512 hfSHA512_256 hfSHA3_256 hfSHA3_512 the OID of all ECC public keys (X962)
- is stored as prefix to CKA_OID[ckaEcc256..ckaEcc256k] parameter
ASN1_SEQ = $30;
Base ASN1_CL_CTR types
ASN1_ZERO_VALUE: TAsnObject = RawByteString(#$00);
Encode a 0 value into ASN.1 binary
CAA_CKA: array[TCryptAsymAlgo] of TCryptKeyAlgo = ( ckaEcc256, ckaEcc384, ckaEcc512, ckaEcc256K, ckaRsa, ckaRsa, ckaRsa, ckaRsaPss, ckaRsaPss, ckaRsaPss, ckaEdDSA);
CaaES256 caaES384 caaES512 caaES256K caaRS256 caaRS384 caaRS512 caaPS256 caaPS384 caaPS512 caaEdDSA - SHA-512 is included in the algorithm the TCryptKeyAlgo according to our known asymmetric algorithms
CAA_CRV: array[TCryptAsymAlgo] of RawUtf8 = ( 'P-256', 'P-384', 'P-521', 'secp256k1', '', '', '', '', '', '', 'Ed25519');
CaaES256 caaES384 caaES512 caaES256K caaRS256 caaRS384 caaRS512 caaPS256 caaPS384 caaPS512 caaEdDSA the JWS ECC curve names according to our known asymmetric algorithms
- see https://www.iana.org/assignments/jose/jose.xhtml#web-key-elliptic-curve
CAA_ECC = [caaES256, caaES384, caaES512, caaES256K, caaEdDSA];
CaaES256 caaES384 caaES512 caaES256K caaRS256 caaRS384 caaRS512 caaPS256 caaPS384 caaPS512 caaEdDSA the known asymmetric algorithms which implement ECC cryptography
CAA_HF: array[TCryptAsymAlgo] of THashAlgo = ( hfSHA256, hfSHA384, hfSHA512, hfSHA256, hfSHA256, hfSHA384, hfSHA512, hfSHA256, hfSHA384, hfSHA512, hfSHA512);
CaaES256 caaES384 caaES512, note that P-521 is not a typo ;) caaES256K caaRS256 caaRS384 caaRS512 caaPS256 caaPS384 caaPS512 caaEdDSA the THashAlgo according to our known asymmetric algorithms
CAA_JWT: array[TCryptAsymAlgo] of RawUtf8 = ( 'ES256', 'ES384', 'ES512', 'ES256K', 'RS256', 'RS384', 'RS512', 'PS256', 'PS384', 'PS512', 'EdDSA');
The JWT algorithm names according to our known asymmetric algorithms
- as implemented e.g. by mormot.crypt.jwt
CAA_RAWSIGNATURE = CAA_RSA + [caaEdDSA];
The known asymmetric algorithms which expects no ASN1_SEQ in JWT/JWS
CAA_RSA = [caaRS256, caaRS384, caaRS512, caaPS256, caaPS384, caaPS512];
The known asymmetric algorithms which implement RSA cryptography
CERT_DEPRECATION_THRESHOLD = 0.5;
Allow half a day margin when checking a Certificate date validity
CKA_ECC = [ckaEcc256, ckaEcc384, ckaEcc512, ckaEcc256k, ckaEdDSA];
The known key algorithms which implement ECC cryptography
CKA_OID: array[TCryptKeyAlgo] of RawUtf8 = ( '', '1.2.840.113549.1.1.1', '1.2.840.113549.1.1.10', '1.2.840.10045.3.1.7', '1.3.132.0.34', '1.3.132.0.35', '1.3.132.0.10', '1.3.101.112');
The OID of all supported ICryptPublicKey/ICryptPrivateKey algorithms
CKA_RSA = [ckaRsa, ckaRsaPss];
The known key algorithms which implement RSA cryptography
CU_ALL = [low(TCryptCertUsage) .. high(TCryptCertUsage)];
Such a Certificate could be used for anything
CU_FULLTEXT: array[TCryptCertUsage] of RawUtf8 = ( 'CA', 'Encipher Only', 'CRL Sign', 'Certificate Sign', 'Key Agreement', 'Data Encipherment', 'Key Encipherment', 'Non Repudiation', 'Digital Signature', 'Decipher Only', 'TLS Web Server Authentication', 'TLS Web Client Authentication', 'E-mail Protection', 'Code Signing', 'OCSP Signing', 'Time Stamping');
CuCA cuEncipherOnly cuCrlSign cuKeyCertSign cuKeyAgreement cuDataEncipherment cuKeyEncipherment cuNonRepudiation cuDigitalSignature cuDecipherOnly cuTlsServer cuTlsClient cuEmail cuCodeSign cuOcspSign cuTimestamp standard long identifier of Certificate usage
- i.e. match OpenSSL PX509.ExtendedKeyUsage/KeyUsage text
CU_TEXT: array[TCryptCertUsage, 0..1] of AnsiChar = ( 'ca', 'eo', 'rs', 'ks', 'ka', 'de', 'ke', 'nr', 'ds', 'do', 'ts', 'tc', 'em', 'cs', 'os', 'tm');
A two-char identifier of Certificate usage
- as used by ToText(u: TCryptCertUsages, from_cu_text=true)
CU_TLS_CLIENT = [cuTlsClient, cuKeyAgreement, cuKeyEncipherment];
Such a Certificate could be used for a TLS client authentication
CU_TLS_SERVER = [cuTlsServer, cuKeyAgreement, cuKeyEncipherment];
Such a Certificate could be used for a TLS server authentication
CV_VALIDSIGN = [cvValidSigned, cvValidSelfSigned];
TCryptCertValidity results indicating a valid digital signature
DIGEST_ALGO: array[daMD5.. high(TDigestAlgo)] of THashAlgo = ( hfMD5, hfMD5, hfSHA256, hfSHA256, hfSHA512_256, hfSHA512_256, hfSHA3_256, hfSHA3_256);
The Digest access authentication processing cryptographic algorithms
DIGEST_NAME: array[daMD5.. high(TDigestAlgo)] of RawUtf8 = ( 'MD5', 'MD5-sess', 'SHA-256', 'SHA-256-sess', 'SHA-512-256', 'SHA-512-256-sess', 'SHA3-256', 'SHA3-256-sess');
DaMD5 daMD5_Sess daSHA256 daSHA256_Sess daSHA512_256 daSHA512_256_Sess daSHA3_256 daSHA3_256_Sess the Digest access authentication algorithm name as used during handshake
DIGEST_SESS = [daMD5_Sess, daSHA256_Sess, daSHA512_256_Sess, daSHA3_256_Sess];
DaMD5 daMD5_Sess daSHA256 daSHA256_Sess daSHA512_256 daSHA512_256_Sess daSHA3_256 daSHA3_256_Sess the Digest access authentication algorithms which hashes the session info
- i.e. includes nonce, cnonce (and authzid) to the hashed response
- it is slightly slower, but much safer, and recommended in our use case of authentication, not authorization
HASH_EXT: array[THashAlgo] of RawUtf8 = ( '.md5', '.sha1', '.sha256', '.sha384', '.sha512', '.sha512-256', '.sha3-256', '.sha3-512');
HfMD5 hfSHA1 hfSHA256 hfSHA384 hfSHA512 hfSHA512_256 hfSHA3_256 hfSHA3_512 map the file extension text of any THashAlgo digest
HASH_SIZE: array[THashAlgo] of integer = ( SizeOf(TMd5Digest), SizeOf(TSHA1Digest), SizeOf(TSHA256Digest), SizeOf(TSHA384Digest), SizeOf(TSHA512Digest), SizeOf(THash256), SizeOf(THash256), SizeOf(THash512));
Map the size in bytes of any THashAlgo digest
HASH_STREAMREDIRECT: array[THashAlgo] of TStreamRedirectClass = ( TStreamRedirectMd5, TStreamRedirectSha1, TStreamRedirectSha256, TStreamRedirectSha384, TStreamRedirectSha512, TStreamRedirectSha512_256, TStreamRedirectSha3_256, TStreamRedirectSha3_512);
Convert a THashAlgo into a TStreamRedirectSynHasher class
PEM_BEGIN: array[TPemKind] of RawUtf8 = ( '-----BEGIN PRIVACY-ENHANCED MESSAGE-----'#13#10, '-----BEGIN CERTIFICATE-----'#13#10, '-----BEGIN X509 CRL-----'#13#10, '-----BEGIN PRIVATE KEY-----'#13#10, '-----BEGIN PUBLIC KEY-----'#13#10, '-----BEGIN RSA PRIVATE KEY-----'#13#10, '-----BEGIN RSA PUBLIC KEY-----'#13#10, '-----BEGIN EC PRIVATE KEY-----'#13#10, '-----BEGIN EC PUBLIC KEY-----'#13#10, '-----BEGIN ENCRYPTED PRIVATE KEY-----'#13#10, '-----BEGIN CERTIFICATE REQUEST-----'#13#10, '-----BEGIN DH PARAMETERS-----'#13#10, '-----BEGIN EC PARAMETERS-----'#13#10, '-----BEGIN SSH2 ENCRYPTED PRIVATE KEY-----'#13#10, '-----BEGIN SSH2 PUBLIC KEY-----'#13#10, '-----BEGIN SYNECC SIGNATURE-----'#13#10, '-----BEGIN SYNECC CERTIFICATE-----'#13#10, '-----BEGIN SYNECC PRIVATE KEY-----'#13#10, '-----BEGIN SYNECC ENCRYPTED PRIVATE KEY-----'#13#10, '-----BEGIN SYNRSA ENCRYPTED PRIVATE KEY-----'#13#10, '-----BEGIN SYNECC BOUNDED CERTIFICATE-----'#13#10);
The supported trailer markers of a PEM text instance
- only the first 10 chars after -----BEGIN will be used for recognition
PEM_END: array[TPemKind] of RawUtf8 = ( '-----END PRIVACY-ENHANCED MESSAGE-----'#13#10, '-----END CERTIFICATE-----'#13#10, '-----END X509 CRL-----'#13#10, '-----END PRIVATE KEY-----'#13#10, '-----END PUBLIC KEY-----'#13#10, '-----END RSA PRIVATE KEY-----'#13#10, '-----END RSA PUBLIC KEY-----'#13#10, '-----END EC PRIVATE KEY-----'#13#10, '-----END EC PUBLIC KEY-----'#13#10, '-----END ENCRYPTED PRIVATE KEY-----'#13#10, '-----END CERTIFICATE REQUEST-----'#13#10, '-----END DH PARAMETERS-----'#13#10, '-----END EC PARAMETERS-----'#13#10, '-----END SSH2 ENCRYPTED PRIVATE KEY-----'#13#10, '-----END SSH2 PUBLIC KEY-----'#13#10, '-----END SYNECC SIGNATURE-----'#13#10, '-----END SYNECC CERTIFICATE-----'#13#10, '-----END SYNECC PRIVATE KEY-----'#13#10, '-----END SYNECC ENCRYPTED PRIVATE KEY-----'#13#10, '-----END SYNRSA ENCRYPTED PRIVATE KEY-----'#13#10, '-----END SYNECC BOUNDED CERTIFICATE-----'#13#10);
The supported ending markers of a PEM text instance
PEM_SYNECC = [pemSynopseSignature, pemSynopseCertificate, pemSynopseUnencryptedPrivateKey, pemSynopsePrivateKeyAndCertificate, pemSynopseEccEncryptedPrivateKey];
Our proprietary SYNECC TPemKind supported formats
RSA_DEFAULT_GENERATION_BITS = 2048;
Our units generate RSA keypairs with 2048-bit by default
- anything lower than 2048-bit is unsafe and should not be used
- 2048-bit is today's norm, creating 112-bit of security
- 3072-bit is supposed to be supported up to 2030, with 128-bit of security
- 4096-bit has no security advantage, just slower process
- 7680-bit is highly impractical (e.g. generation can be more than 30 secs) and offers only 192-bit of security, so other algorithms may be preferred
| Functions or procedures | Description | |
|---|---|---|
| Asn | Create an ASN.1 binary from the aggregation of several binaries | |
| Asn | Create an ASN.1 binary from 64-bit signed integer, calling AsnEncInt() | |
| Asn | Create an ASN.1 binary from some raw data - as OCTSTR by default | |
| AsnAdd | Encode and append some raw data as ASN.1 | |
| AsnAdd | Raw append some binary to an ASN.1 object buffer | |
| AsnArr | Create an ASN.1 binary from several raw data - as OCTSTR by default | |
| AsnBigInt | Create an ASN.1 binary from an unsigned Big Integer raw buffer | |
| AsnDecChunk | Check if a DER memory buffer is a full block, e.g. a full ASN1_SEQ | |
| AsnDecHeader | Decode the header of a ASN.1 binary item | |
| AsnDecInt | Decode an ASN1_INT ASN1_ENUM ASN1_BOOL value | |
| AsnDecIp | Decode an OID ASN.1 IP Address buffer into human-readable text | |
| AsnDecLen | Decode the len of a ASN.1 binary item | |
| AsnDecOctStr | Decode an OCTSTR ASN.1 value into its raw bynary buffer | |
| AsnDecOid | Decode an OID ASN.1 value into human-readable text | |
| AsnDump | Human-readable display of a ASN.1 value binary | |
| AsnEncInt | Encode a 64-bit signed integer value into ASN.1 binary | |
| AsnEncInt | Encode a raw binary-encoded integer value into ASN.1 binary | |
| AsnEncLen | Encode the len of a ASN.1 binary item | |
| AsnEncOid | Create an ASN.1 ObjectID from '1.x.x.x.x' text | |
| AsnEncOidItem | Encode a 64-bit unsigned OID integer value into ASN.1 binary | |
| AsnNext | Parse the next ASN.1 value as text | |
| AsnNextBigInt | Parse the next ASN1_INT value as raw Big Integer binary | |
| AsnNextInit | Initialize a set of AsnNext() Pos[] with its 1 default position | |
| AsnNextInt32 | Parse the next ASN1_INT ASN1_ENUM ASN1_BOOL value as 32-bit integer | |
| AsnNextInteger | Parse the next ASN1_INT ASN1_ENUM ASN1_BOOL value as 64-bit integer | |
| AsnNextRaw | Parse the next ASN.1 value as raw buffer | |
| AsnNextTime | Parse the next ASN1_UTCTIME ASN1_GENTIME value as TDateTime | |
| AsnOid | Create an ASN.1 ObjectID from 'x.x.x.x.x' text | |
| AsnSafeOct | Internal function used to wipe any temporary string for anti-forensic | |
| AsnSeq | Create an ASN.1 SEQuence from the aggregation of several binaries | |
| AsnSeq | Create an ASN.1 SEQuence from some raw data | |
| AsnText | Create an ASN.1 PrintableString or UTF8String from some UTF-8 text | |
| AsnTime | Create an ASN.1 block from some date/time value | |
| Asym | Main resolver for asymmetric public key algorithms | |
| BasicClient | Compute the Basic access authentication client code | |
| BasicRealm | Extract the Basic access authentication realm on client side | |
| BasicServerAuth | Parse a Basic access authentication on server side | |
| Cert | Main factory of the Certificates instances as returned by CertAlgo() | |
| CertAlgo | Main resolver for Certificates algorithms | |
| ChainAdd | Append a ICryptCert to a certificates chain | |
| ChainConsolidate | Sort a certificate chain by mutual authentication | |
| ChainFind | Search for a ICryptCert to a certificates chain | |
| Cipher | Main factory for symmetric encryption/decryption with PBKDF2 key derivation | |
| Cipher | Main factory for symmetric encryption/decryption process | |
| CipherAlgo | Main resolver for symmetric encryption/decryption algorithms | |
| CkaToSeq | Raw function to generate a public key ASN1_SEQ definition with its OID(s) | |
| CryptCrc32 | HfMD5 hfSHA1 hfSHA256 hfSHA384 hfSHA512 hfSHA512_256 hfSHA3_256 hfSHA3_512 returns the 32-bit crc function for a given algorithm | |
| Decrypt | Main factory for symmetric decryption process | |
| Decrypt | Main factory for symmetric decryption process with PBKDF2 key derivation | |
| DerAppend | Low-level binary-to-DER encoder of small buf with buflen < 127 | |
| DerParse | Low-level DER sequence to binary decoding | |
| DerToPem | Convert a binary DER content into a single-instance PEM text | |
| DerToPem | CkaNone ckaRsa ckaRsaPss ckaEcc256 (with ASN1_OID_X962_PUBLICKEY) ckaEcc384 (with ASN1_OID_X962_PUBLICKEY) ckaEcc512 (with ASN1_OID_X962_PUBLICKEY) ckaEcc256k (with ASN1_OID_X962_PUBLICKEY) ckaEdDSA convert a binary DER content into a single-instance PEM text | |
| DigestClient | Compute the Digest access authentication client code for a given algorithm | |
| DigestHA0 | Compute the HA0 for a given set of Digest access credentials | |
| DigestRealm | Extract the Digest access authentication realm on client side | |
| DigestServerAuth | Validate a Digest access authentication on server side | |
| DigestServerInit | Initiate a Digest access authentication from server side for a given algorithm | |
| EccPrivKeyToSeq | Raw function to encode a PKCS#8 PrivateKeyInfo from its raw binary number | |
| Encrypt | Main factory for symmetric encryption process with PBKDF2 key derivation | |
| Encrypt | Main factory for symmetric encryption process | |
| FindStuffExeCertificate | Retrieve the text inserted by StuffExeCertificate() into the Windows executable digital signature | |
| GetFirstUsage | Return the first usage set, or cuKeyCertSign if [] was supplied | |
| GetSignatureSecurityBits | Compute the number of security bits of a digital signature | |
| GetSignatureSecurityRaw | Compute the base-64 encoding of the raw binary of a ASN.1/DER digital signature | |
| Hash | Main factory of the hashers instances as returned by Hasher() | |
| Hasher | Main resolver of the registered hashers | |
| HashFile | Compute the hexadecimal hashe(s) of one file, as external .md5/.sha256/.. files | |
| HashFile | Compute the hexadecimal hash of any (big) file | |
| HashFileMd5 | Compute the MD5 checksum of a given file | |
| HashFileRaw | Compute one or several hexadecimal hash(es) of any (big) file | |
| HashFileSha1 | Compute the SHA-1 checksum of a given file | |
| HashFileSha256 | Compute the SHA-256 checksum of a given file | |
| HashFileSha384 | Compute the SHA-384 checksum of a given file | |
| HashFileSha3_256 | Compute the SHA-3-256 checksum of a given file | |
| HashFileSha3_512 | Compute the SHA-3-512 checksum of a given file | |
| HashFileSha512 | Compute the SHA-512 checksum of a given file | |
| HashFileSha512_256 | Compute the SHA-512/256 checksum of a given file | |
| HashFull | One-step hash computation of a buffer as lowercase hexadecimal string | |
| HashFull | One-step hash computation of a buffer as lowercase hexadecimal string | |
| IsCN | Fast case-insensitive check of the 'CN' Relative Distinguished Name identifier | |
| IsDer | Fast case-insensitive check of the 'DER' fake RDNidentifier | |
| IsPem | Quickly check the begin/end of a single-instance PEM text | |
| IsPemEncrypted | Quickcly check if a PEM text is likely to be encrypted | |
| NextPem | Parse a multi-PEM text input and return the next PEM content | |
| NextPemToDer | Parse a multi-PEM text input and return the next PEM content as binary DER | |
| OidToCka | Raw function to recognize the OID(s) of a public key ASN1_SEQ definition | |
| ParsedToText | Return some multi-line text of the main TX509Parsed fields | |
| PemToCertAndPrivKey | Extract pemCertificate and a private key concatenated in a PEM text file | |
| PemToDer | Convert a single-instance PEM text file into a binary DER | |
| PrivateKeyDecrypt | Uncipher some binary into a raw private key buffer | |
| PrivateKeyEncrypt | Cipher any private key buffer into safe binary | |
| Rnd | Main resolver of the randomness generators | |
| SeqToEccPrivKey | Raw function to decode a PKCS#8 PrivateKeyInfo into its raw binary | |
| SeqToEccPubKey | Raw function to decode a specific PKCS#8 PublicKeyInfo into its raw binary | |
| SetSignatureSecurityRaw | Encode a raw digital signature into ASN.1/DER | |
| Sign | Main factory of a signer instance from strong PBKDF2 derivation | |
| Sign | Main factory of the signer instances, with PBKDF2 secret derivation | |
| Sign | Main factory of the signer instances as returned by Signer() | |
| Signer | Main resolver of the registered signers | |
| Store | Main factory of Certificates Store engines as returned by StoreAlgo() | |
| StoreAlgo | Main resolver for Certificates Store engines | |
| StuffExeCertificate | Create a NewFile executable from adding some text to MainFile digital signature | |
| SymmetricEncrypt | Simple symmetric obfuscation scheme using a 32-bit key | |
| TextToHashAlgo | Recognize a THashAlgo from a text, e.g. 'SHA1' or 'SHA3_256' | |
| ToText | CuCA cuEncipherOnly cuCrlSign cuKeyCertSign cuKeyAgreement cuDataEncipherment cuKeyEncipherment cuNonRepudiation cuDigitalSignature cuDecipherOnly cuTlsServer cuTlsClient cuEmail cuCodeSign cuOcspSign cuTimestamp | |
| WinX509Parse | The raw mormot.lib.sspi parser - published for testing | |
| X509PubKeyBits | Return the number of bits of a X.509 certificate SubjectPublicKey ASN1_BITSTR | |
| X509PubKeyFromDer | Compute the raw binary as stored in X.509 certificate from a ASN.1 public key | |
| X509PubKeyToDer | Compute the public key ASN.1 from a raw binary as stored in X.509 certificate |
function Asn(const Data: RawByteString; AsnType: integer = ASN1_OCTSTR): TAsnObject; overload;
Create an ASN.1 binary from some raw data - as OCTSTR by default
function Asn(Value: Int64; AsnType: integer = ASN1_INT): TAsnObject; overload;
Create an ASN.1 binary from 64-bit signed integer, calling AsnEncInt()
function Asn(AsnType: integer; const Content: array of TAsnObject): TAsnObject; overload;
Create an ASN.1 binary from the aggregation of several binaries
procedure AsnAdd(var Data: TAsnObject; const Buffer: TAsnObject); overload;
Raw append some binary to an ASN.1 object buffer
procedure AsnAdd(var Data: TAsnObject; const Buffer: TAsnObject; AsnType: integer); overload;
Encode and append some raw data as ASN.1
function AsnArr(const Data: array of RawUtf8; AsnType: integer = ASN1_OCTSTR): TAsnObject;
Create an ASN.1 binary from several raw data - as OCTSTR by default
function AsnBigInt(const BigInt: RawByteString; AsnType: integer = ASN1_INT): TAsnObject;
Create an ASN.1 binary from an unsigned Big Integer raw buffer
- the raw buffer is likely to come from mormot.crypt.rsa TBigInt.Save result
- will trim unneeded leading zeros, and ensure will be stored as unsigned even if starts with a $80 byte
- any temporary string will be zeroed during the process for anti-forensic, since a BigInt may be sensitive information (e.g. a RSA secret prime)
function AsnDecChunk(const der: RawByteString; exptyp: integer = ASN1_SEQ): boolean;
Check if a DER memory buffer is a full block, e.g. a full ASN1_SEQ
function AsnDecHeader(var Pos: integer; const Buffer: TAsnObject; out AsnType, AsnSize: integer): boolean;
Decode the header of a ASN.1 binary item
function AsnDecInt(var Start: integer; const Buffer: TAsnObject; AsnSize: integer): Int64;
Decode an ASN1_INT ASN1_ENUM ASN1_BOOL value
function AsnDecIp(p: PAnsiChar; len: integer): RawUtf8;
Decode an OID ASN.1 IP Address buffer into human-readable text
function AsnDecLen(var Start: integer; const Buffer: TAsnObject): cardinal;
Decode the len of a ASN.1 binary item
function AsnDecOctStr(const input: RawByteString): RawByteString;
Decode an OCTSTR ASN.1 value into its raw bynary buffer
- returns plain input value if was not a valid ASN1_OCTSTR
function AsnDecOid(Pos, EndPos: integer; const Buffer: TAsnObject): RawUtf8;
Decode an OID ASN.1 value into human-readable text
function AsnDump(const Value: TAsnObject): RawUtf8;
Human-readable display of a ASN.1 value binary
- used e.g. by the ASNDEBUG conditional
function AsnEncInt(Value: pointer; ValueLen: PtrUInt): TAsnObject; overload;
Encode a raw binary-encoded integer value into ASN.1 binary
function AsnEncInt(Value: Int64): TAsnObject; overload;
Encode a 64-bit signed integer value into ASN.1 binary
function AsnEncLen(Len: cardinal; dest: PByte): PtrInt;
Encode the len of a ASN.1 binary item
function AsnEncOid(OidText: PUtf8Char): TAsnObject;
Create an ASN.1 ObjectID from '1.x.x.x.x' text
procedure AsnEncOidItem(Value: PtrUInt; var Result: shortstring);
Encode a 64-bit unsigned OID integer value into ASN.1 binary
- append the encoded value into the Result shortstring existing content
function AsnNext(var Pos: integer; const Buffer: TAsnObject; Value: PRawByteString = nil; CtrEndPos: PInteger = nil): integer;
Parse the next ASN.1 value as text
- returns the ASN.1 value type, and optionally the ASN.1 value blob itself
function AsnNextBigInt(var Pos: integer; const Buffer: TAsnObject; out Value: RawByteString): boolean;
Parse the next ASN1_INT value as raw Big Integer binary
procedure AsnNextInit(var Pos: TIntegerDynArray; Count: PtrInt);
Initialize a set of AsnNext() Pos[] with its 1 default position
function AsnNextInt32(var Pos: integer; const Buffer: TAsnObject; out Value: integer): integer;
Parse the next ASN1_INT ASN1_ENUM ASN1_BOOL value as 32-bit integer
- warning: parameters do NOT match AsnNextInteger() signature
- returns the ASN.1 value type, and optionally the ASN.1 value blob itself
function AsnNextInteger(var Pos: integer; const Buffer: TAsnObject; out ValueType: integer): Int64;
Parse the next ASN1_INT ASN1_ENUM ASN1_BOOL value as 64-bit integer
function AsnNextRaw(var Pos: integer; const Buffer: TAsnObject; out Value: RawByteString; IncludeHeader: boolean = false): integer;
Parse the next ASN.1 value as raw buffer
- returns the ASN.1 value type, and the ASN.1 raw value blob itself
function AsnNextTime(var Pos: integer; const Buffer: TAsnObject; out Value: TDateTime): boolean;
Parse the next ASN1_UTCTIME ASN1_GENTIME value as TDateTime
function AsnOid(OidText: PUtf8Char): TAsnObject;
Create an ASN.1 ObjectID from 'x.x.x.x.x' text
function AsnSafeOct(const Content: array of TAsnObject): TAsnObject;
Internal function used to wipe any temporary string for anti-forensic
- warning: all Content[] will be filled with zeroes even if marked as "const"
function AsnSeq(const Data: TAsnObject): TAsnObject; overload;
Create an ASN.1 SEQuence from some raw data
function AsnSeq(const Content: array of TAsnObject): TAsnObject; overload;
Create an ASN.1 SEQuence from the aggregation of several binaries
function AsnText(const Text: RawUtf8): TAsnObject;
Create an ASN.1 PrintableString or UTF8String from some UTF-8 text
- will prefer ASN1_PRINTSTRING if the charset of the supplied text do suffice
function AsnTime(dt: TDateTime): TAsnObject;
Create an ASN.1 block from some date/time value
- according to X.509 profile, use UTCTime up to 2049 then GeneralizedTime
- dt = 0 will be converted as '99991231235959Z' GeneralizedTime - could be used e.g. with X.509 NotAfter field when no good expiration date can be assigned (see RFC 5280 #4.1.2.5)
function Asym(const name: RawUtf8): TCryptAsym;
Main resolver for asymmetric public key algorithms
- mormot.crypt.ecc.pas defines 'secp256r1','NISTP-256' and 'prime256v1' which are synonymous of our secp256r1 ECDSA and ECDHE pascal code
- mormot.crypt.openssl.pas will define 'es256' .. 'EdDSA' including 'rs256' for the well known 2048-bit RSA + SHA256 digital signature
- the shared TCryptAsym of this algorithm is returned: caller should NOT free it
function BasicClient(const UserName: RawUtf8; const Password: SpiUtf8): RawUtf8;
Compute the Basic access authentication client code
- as defined in https://en.wikipedia.org/wiki/Basic_access_authentication
function BasicRealm(const FromServer: RawUtf8): RawUtf8;
Extract the Basic access authentication realm on client side
- FromServer is the 'xxx' encoded value from 'WWW-Authenticate: Basic xxx'
- could be proposed to the user interation UI to specify the auth context
function BasicServerAuth(FromClient: PUtf8Char; out User, Password: RawUtf8): boolean;
Parse a Basic access authentication on server side
- returns true and the user/password from a valid input, or false on error
function Cert(const name: RawUtf8): ICryptCert;
Main factory of the Certificates instances as returned by CertAlgo()
- name is typically 'syn-es256' or 'x509-es256'
function CertAlgo(const name: RawUtf8): TCryptCertAlgo;
Main resolver for Certificates algorithms
- mormot.crypt.ecc.pas defines 'syn-es256' for our TEccCertificate proprietary format (safe and efficient), with 'syn-es256-v1' for the V1 revision with limited Usage and Subjects support
- mormot.crypt.openssl.pas will define 'x509-es256' .. 'x509-eddsa' including 'x509-rs256' for the well established 2048-bit RSA + SHA256 certificates
- the shared TCryptCertAlgo of this algorithm is returned: caller should NOT free it
procedure ChainAdd(var chain: ICryptCertChain; const cert: ICryptCert);
Append a ICryptCert to a certificates chain
function ChainConsolidate(const chain: ICryptCertChain): ICryptCertChain;
Sort a certificate chain by mutual authentication
- returns the certificates in IsAuthorizedBy() order
function ChainFind(var chain: ICryptCertChain; const cert: ICryptCert; comparer: TCryptCertComparer = ccmInstance): PtrInt;
Search for a ICryptCert to a certificates chain
- will search for the ICryptCert instance itself, or by TCryptCertComparer
function Cipher(const name: RawUtf8; key: pointer; encrypt: boolean): ICryptCipher; overload;
Main factory for symmetric encryption/decryption process
- supplied key is expected to match the algorithm size
function Cipher(const name, hash, secret, salt: RawUtf8; rounds: integer; encrypt: boolean): ICryptCipher; overload;
Main factory for symmetric encryption/decryption with PBKDF2 key derivation
function CipherAlgo(const name: RawUtf8): TCryptCipherAlgo;
Main resolver for symmetric encryption/decryption algorithms
- names are e.g. 'aes-128-cfb' or 'aes-256-gcm' standard combinations
- recognize some non-standard algorithms with trailing 'c64', 'cfc', 'ofc' and 'ctc' mode names e.g. as 'aes-256-cfc' - with AED 256-bit support (but c64)
- will return the fastest engine, which may be OpenSSL, unless 'aes-nnn-xxx-int' is used to force using our mormot.crypt.core.pas own implementation
- the shared TCryptCipherAlgo of this algorithm is returned: caller should NOT free it
function CkaToSeq(cka: TCryptKeyAlgo): RawByteString;
Raw function to generate a public key ASN1_SEQ definition with its OID(s)
function CryptCrc32(algo: TCrc32Algo): THasher;
HfMD5 hfSHA1 hfSHA256 hfSHA384 hfSHA512 hfSHA512_256 hfSHA3_256 hfSHA3_512 returns the 32-bit crc function for a given algorithm
- may return nil, e.g. for caAdler32 when mormot.lib.z is not loaded
- caSha1 has cryptographic level, with high performance on latest SHA-NI CPUs
function Decrypt(const name, hash, secret, salt: RawUtf8; rounds: integer): ICryptCipher; overload;
Main factory for symmetric decryption process with PBKDF2 key derivation
function Decrypt(const name: RawUtf8; key: pointer): ICryptCipher; overload;
Main factory for symmetric decryption process
function DerAppend(P: PAnsiChar; buf: PByteArray; buflen: PtrUInt): PAnsiChar;
Low-level binary-to-DER encoder of small buf with buflen < 127
function DerParse(P: PAnsiChar; buf: PByteArray; buflen: PtrInt): PAnsiChar;
Low-level DER sequence to binary decoding
- only support a single DER_INTEGER sequence format as generated by DerAppend()
function DerToPem(der: pointer; len: PtrInt; kind: TPemKind): TCertPem; overload;
CkaNone ckaRsa ckaRsaPss ckaEcc256 (with ASN1_OID_X962_PUBLICKEY) ckaEcc384 (with ASN1_OID_X962_PUBLICKEY) ckaEcc512 (with ASN1_OID_X962_PUBLICKEY) ckaEcc256k (with ASN1_OID_X962_PUBLICKEY) ckaEdDSA convert a binary DER content into a single-instance PEM text
function DerToPem(const der: TCertDer; kind: TPemKind): TCertPem; overload;
Convert a binary DER content into a single-instance PEM text
function DigestClient(Algo: TDigestAlgo; const FromServer, DigestMethod, DigestUri, UserName: RawUtf8; const Password: SpiUtf8; const DigestUriName: RawUtf8 = 'uri'): RawUtf8;
Compute the Digest access authentication client code for a given algorithm
- as defined in https://en.wikipedia.org/wiki/Digest_access_authentication
- FromServer is the 'xxx' encoded value from 'WWW-Authenticate: Digest xxx'
- may return '' if Algo does not match algorithm=... value (MD5 or SHA-256)
- DigestUriName is customized as "digest-uri" e.g. for LDAP digest auth
function DigestHA0(Algo: TDigestAlgo; const UserName, Realm: RawUtf8; const Password: SpiUtf8; out HA0: THash512Rec): integer;
Compute the HA0 for a given set of Digest access credentials
function DigestRealm(const FromServer: RawUtf8): RawUtf8;
Extract the Digest access authentication realm on client side
- FromServer is the 'xxx' encoded value from 'WWW-Authenticate: Digest xxx'
- could be proposed to the user interation UI to specify the auth context
function DigestServerAuth(Algo: TDigestAlgo; const Realm, Method: RawUtf8; FromClient: PUtf8Char; Opaque: Int64; const OnSearchUser: TOnDigestServerAuthGetUserHash; out User, Url: RawUtf8; NonceExpSec: PtrUInt; Tix64: Qword = 0): TAuthServerResult;
Validate a Digest access authentication on server side
- returns true and the user/uri from a valid input token, or false on error
function DigestServerInit(Algo: TDigestAlgo; const QuotedRealm, Prefix, Suffix: RawUtf8; Opaque: Int64; Tix64: Int64 = 0): RawUtf8;
Initiate a Digest access authentication from server side for a given algorithm
- Opaque could be e.g. an obfuscated HTTP connection ID to avoid MiM attacks
- Prefix/Suffix are typically 'WWW-Authenticate: Digest ' and #13#10 to construct a HTTP header
function EccPrivKeyToSeq(cka: TCryptKeyAlgo; const rawecc: RawByteString): RawByteString;
Raw function to encode a PKCS#8 PrivateKeyInfo from its raw binary number
- e.g. as generated by OpenSSL
function Encrypt(const name: RawUtf8; key: pointer): ICryptCipher; overload;
Main factory for symmetric encryption process
function Encrypt(const name, hash, secret, salt: RawUtf8; rounds: integer): ICryptCipher; overload;
Main factory for symmetric encryption process with PBKDF2 key derivation
function FindStuffExeCertificate(const FileName: TFileName): RawUtf8;
Retrieve the text inserted by StuffExeCertificate() into the Windows executable digital signature
- raise EStuffExe if MainFile has no supported signature
- returns the stuffed text, or '' if no text has been included
- this function does not require mormot.crypt.openssl
function GetFirstUsage(u: TCryptCertUsages): TCryptCertUsage;
Return the first usage set, or cuKeyCertSign if [] was supplied
function GetSignatureSecurityBits(a: TCryptAsymAlgo; len: integer): integer;
Compute the number of security bits of a digital signature
- RSA security depends on the signature size, not the hash size
- ECC security size is half of its X,Y coordinates storage size
- e.g. 112 for RSA-2048, 128 for ECC-256
function GetSignatureSecurityRaw(algo: TCryptAsymAlgo; const signature: RawByteString): RawUtf8;
Compute the base-64 encoding of the raw binary of a ASN.1/DER digital signature
- input comes e.g. from ICryptCert.Sign or ICryptPrivateKey.Sign content
- base-64 encoded output can be used e.g. for JSON Web Token/Signature (JWT/JWS)
- RSA and EdDSA signatures are not encoded, so are returnde directly
- ECC are decoded from their ASN1_SEQ into their raw xy coordinates concatenation
function Hash(const name: RawUtf8): ICryptHash;
Main factory of the hashers instances as returned by Hasher()
- if not nil, caller should call Update then Final
function Hasher(const name: RawUtf8): TCryptHasher;
Main resolver of the registered hashers
- hashers ensure a content as not been tempered: use Signer() to compute a digital signature from a given secret
- the shared TCryptHasher of this algorithm is returned: caller should NOT free it
- if not nil, you could call New or Full/FullFile methods
- this unit supports 'md5', 'sha1', 'sha256', 'sha384', 'sha512', 'sha3_256', 'sha3_512' and 32-bit non-cryptographic 'crc32', 'crc32c', 'xxhash32', 'adler32', 'fnv32', 'aesni32', 'md5-32' and 'sha1-32'
function HashFile(const aFileName: TFileName; aAlgo: THashAlgo): RawUtf8; overload;
Compute the hexadecimal hash of any (big) file
- using a temporary buffer of 1MB for the sequential reading
procedure HashFile(const aFileName: TFileName; aAlgos: THashAlgos); overload;
Compute the hexadecimal hashe(s) of one file, as external .md5/.sha256/.. files
- generate the text hash files in the very same folder
function HashFileMd5(const FileName: TFileName): RawUtf8;
Compute the MD5 checksum of a given file
- this function maps the THashFile signature as defined in mormot.core.buffers
function HashFileRaw(const aFileName: TFileName; aAlgos: THashAlgos): TRawUtf8DynArray;
Compute one or several hexadecimal hash(es) of any (big) file
- using a temporary buffer of 1MB for the sequential reading
function HashFileSha1(const FileName: TFileName): RawUtf8;
Compute the SHA-1 checksum of a given file
- this function maps the THashFile signature as defined in mormot.core.buffers
function HashFileSha256(const FileName: TFileName): RawUtf8;
Compute the SHA-256 checksum of a given file
- this function maps the THashFile signature as defined in mormot.core.buffers
function HashFileSha384(const FileName: TFileName): RawUtf8;
Compute the SHA-384 checksum of a given file
- this function maps the THashFile signature as defined in mormot.core.buffers
function HashFileSha3_256(const FileName: TFileName): RawUtf8;
Compute the SHA-3-256 checksum of a given file
- this function maps the THashFile signature as defined in mormot.core.buffers
function HashFileSha3_512(const FileName: TFileName): RawUtf8;
Compute the SHA-3-512 checksum of a given file
- this function maps the THashFile signature as defined in mormot.core.buffers
function HashFileSha512(const FileName: TFileName): RawUtf8;
Compute the SHA-512 checksum of a given file
- this function maps the THashFile signature as defined in mormot.core.buffers
function HashFileSha512_256(const FileName: TFileName): RawUtf8;
Compute the SHA-512/256 checksum of a given file
- this function maps the THashFile signature as defined in mormot.core.buffers
function HashFull(aAlgo: THashAlgo; const aBuffer: RawByteString): RawUtf8; overload;
One-step hash computation of a buffer as lowercase hexadecimal string
function HashFull(aAlgo: THashAlgo; aBuffer: pointer; aLen: integer): RawUtf8; overload;
One-step hash computation of a buffer as lowercase hexadecimal string
function IsCN(const Rdn: RawUtf8): boolean;
Fast case-insensitive check of the 'CN' Relative Distinguished Name identifier
function IsDer(const Rdn: RawUtf8): boolean;
Fast case-insensitive check of the 'DER' fake RDNidentifier
function IsPem(const pem: RawUtf8): boolean;
Quickly check the begin/end of a single-instance PEM text
- do not validate the internal Base64 encoding, just the trailer/ending lines
- expects at least a single-instance PEM, with ----BEGIN and -----END markers
function IsPemEncrypted(const pem: TCertPem): boolean;
Quickcly check if a PEM text is likely to be encrypted
- search for a PEM format, with ENCRYPTED keyword
- won't decode the Base64 encoded binary, so may return some false negative
function NextPem(var P: PUtf8Char; Kind: PPemKind = nil): TCertPem;
Parse a multi-PEM text input and return the next PEM content
- search and identify any PEM_BEGIN/PEM_END markers
- optionally returning the recognized TPemKind (maybe pemUnspecified)
- see also NextPemToDer()
function NextPemToDer(var P: PUtf8Char; Kind: PPemKind = nil): TCertDer;
Parse a multi-PEM text input and return the next PEM content as binary DER
- search and identify any PEM_BEGIN/PEM_END markers
- optionally returning the recognized TPemKind (maybe pemUnspecified)
function OidToCka(const oid, oid2: RawUtf8): TCryptKeyAlgo;
Raw function to recognize the OID(s) of a public key ASN1_SEQ definition
function ParsedToText(const c: TX509Parsed): RawUtf8;
Return some multi-line text of the main TX509Parsed fields
- in a layout similar to X509_print() OpenSSL formatting
- is used by its own TX509Parsed.PeerInfo field
function PemToCertAndPrivKey(const MultiPartPem: RawUtf8; out Cert, PrivKey: RawByteString): boolean;
Extract pemCertificate and a private key concatenated in a PEM text file
function PemToDer(const pem: TCertPem; const kind: PPemKind = nil): TCertDer;
Convert a single-instance PEM text file into a binary DER
- if the supplied buffer doesn't start with '-----BEGIN .... -----' trailer, will expect the input to be plain DER binary and directly return it
function PrivateKeyDecrypt(const Input, Salt: RawByteString; const PrivatePassword: SpiUtf8; AfSplitRounds: integer = 31; Pbkdf2Rounds: integer = 1000): RawByteString;
Uncipher some binary into a raw private key buffer
- encryption uses safe PBKDF2 HMAC-SHA256 AES-CTR-128 and AF-32 algorithms
- as used by pemSynopseEccEncryptedPrivateKey format and EccPrivateKeyDecrypt() or TCryptPrivateKey.Load and TCryptCertX509.Load
function PrivateKeyEncrypt(const Input, Salt: RawByteString; const PrivatePassword: SpiUtf8; AfSplitRounds: integer = 31; Pbkdf2Rounds: integer = 1000): RawByteString;
Cipher any private key buffer into safe binary
- encryption uses safe PBKDF2 HMAC-SHA256 AES-CTR-128 and AF-32 algorithms
- as used by pemSynopseEccEncryptedPrivateKey format and EccPrivateKeyEncrypt() or TCryptPrivateKey.Save and TCryptCertX509.Save
function Rnd(const name: RawUtf8 = 'rnd-default'): TCryptRandom;
Main resolver of the randomness generators
- the shared TCryptRandom of this algorithm is returned: caller should NOT free it
- e.g. Rnd.GetBytes(100) to get 100 random bytes from 'rnd-default' engine
- call Rnd('rnd-entropy').Get() to gather OS entropy, optionally as 'rnd-entropysys', 'rnd-entropysysblocking', 'rnd-entropyuser'
- alternative generators are 'rnd-aes' (same as 'rnd-default'), 'rnd-lecuyer' (fast on small content) and 'rnd-system'/'rnd-systemblocking' (mapping FillSystemRandom)
function SeqToEccPrivKey(cka: TCryptKeyAlgo; const seq: RawByteString; rfcpub: PRawByteString = nil): RawByteString;
Raw function to decode a PKCS#8 PrivateKeyInfo into its raw binary
- e.g. as generated by OpenSSL
- is also able to decode RFC 5915 Elliptic Curve key pair alternate format, and its optional public key field
function SeqToEccPubKey(cka: TCryptKeyAlgo; const seq: RawByteString): RawByteString;
Raw function to decode a specific PKCS#8 PublicKeyInfo into its raw binary
- e.g. as generated by OpenSSL or X509PubKeyToDer()
- behaves like X509PubKeyFromDer() but checking for one expected ECC algorithm
function SetSignatureSecurityRaw(algo: TCryptAsymAlgo; const rawsignature: RawUtf8): RawByteString;
Encode a raw digital signature into ASN.1/DER
- incoming comes e.g. from base-64 decoded JSON Web Token/Signature (JWT/JWS)
- output is compatible e.g. with ICryptCert.Verify or ICryptPublicKey.Verify
- ECC are encoded from their raw xy coordinates concatenation into ASN1_SEQ
function Sign(key: pointer; keylen: PtrInt; const name: RawUtf8): ICryptHash; overload;
Main factory of the signer instances as returned by Signer()
- in respect to Hash(), expects a key/salt to be supplied for the HMAC signing
- if not nil, caller should call Update then Final
function Sign(const name, secret, salt: RawUtf8; rounds: integer): ICryptHash; overload;
Main factory of the signer instances, with PBKDF2 secret derivation
- if not nil, caller should call Update then Final
function Sign(const paramsjson: RawUtf8; const defaultsalt: RawUtf8 = SIGNER_DEFAULT_SALT): ICryptHash; overload;
Main factory of a signer instance from strong PBKDF2 derivation
- paramsjson contains a TSynSignerParams serialized as JSON object
- returns the number of bytes computed in returned key memory
function Signer(const name: RawUtf8): TCryptSigner;
Main resolver of the registered signers
- in respect to Hasher(), will require a secret for safe digital signature
- the shared TCryptSigner of this algorithm is returned: caller should NOT free it
- if not nil, you could call New or Full/FullFile methods
- this unit supports 'hmac-sha1','hmac-sha256','hmac-sha384','hmac-sha512', and 'sha3-224','sha3-256','sha3-384','sha3-512','sha3-s128','sha3-s256'
function Store(const name: RawUtf8): ICryptStore;
Main factory of Certificates Store engines as returned by StoreAlgo()
function StoreAlgo(const name: RawUtf8): TCryptStoreAlgo;
Main resolver for Certificates Store engines
- mormot.crypt.ecc.pas defines 'syn-store' or 'syn-store-nocache' for our TEccCertificateChain proprietary format (safe and efficient)
- mormot.crypt.openssl.pas will define 'x509-store'
- the shared TCryptStoreAlgo of this algorithm is returned: caller should NOT free it
procedure StuffExeCertificate(const MainFile, NewFile: TFileName; const Stuff: RawUtf8; UseInternalCertificate: boolean = false);
Create a NewFile executable from adding some text to MainFile digital signature
- up to 60KB of text will be stuffed within a dummy certificate inside the existing digital signature, so you don't need to sign the executable again
- FileAppend() method of mormot.core.zip has been disallowed in latest Windows versions, so this method is the right way for adding some custom information at runtime to an already-signed Windows executable
- raise EStuffExe if MainFile has no supported signature, is already stuffed, or the stuffed data is too big
- this function does not require mormot.crypt.openssl but may use it if available to generate a genuine dummy certificate - if UseInternalCertificate is true, or OpenSSL is not available, it will use a fixed constant certificate
- use FindStuffExeCertificate() to retrieve the stuffed text
procedure SymmetricEncrypt(key: cardinal; var data: RawByteString);
Simple symmetric obfuscation scheme using a 32-bit key
- used e.g. by TSynPersistentWithPassword and mormot.db.proxy to obfuscate password or content - so it is not a real encryption
- fast, but not cryptographically secure, since naively xor data bytes with crc32ctab[]: consider using mormot.crypt.core proven algorithms instead
function TextToHashAlgo(const Text: RawUtf8; out Algo: THashAlgo): boolean;
Recognize a THashAlgo from a text, e.g. 'SHA1' or 'SHA3_256'
function ToText(a: TCryptAsymAlgo): PShortString; overload;
CuCA cuEncipherOnly cuCrlSign cuKeyCertSign cuKeyAgreement cuDataEncipherment cuKeyEncipherment cuNonRepudiation cuDigitalSignature cuDecipherOnly cuTlsServer cuTlsClient cuEmail cuCodeSign cuOcspSign cuTimestamp
function WinX509Parse(const Cert: RawByteString; out Info: TX509Parsed): boolean;
The raw mormot.lib.sspi parser - published for testing
function X509PubKeyBits(const SubjectPublicKey: RawByteString; PubText: PRawUtf8 = nil): integer;
Return the number of bits of a X.509 certificate SubjectPublicKey ASN1_BITSTR
- will recognize RSA ASN1_SEQ and ECC uncompressed keys as stored in X.509
- returns typically 2048 for RSA, or 256 for ecc256r1
- can format the key as its hexa members for ParsedToText(TX509Parsed)
function X509PubKeyFromDer(const PkcsDer: RawByteString): RawByteString;
Compute the raw binary as stored in X.509 certificate from a ASN.1 public key
- i.e. extract the ASN1_BITSTR raw section as encoded by X509PubKeyToDer()
- will return the raw public key with no algorithm check whatsoever - consider calling SeqToEccPubKey() to parse for an expected ECC algorithm
function X509PubKeyToDer(Algorithm: TCryptKeyAlgo; const SubjectPublicKey: RawByteString): RawByteString;
Compute the public key ASN.1 from a raw binary as stored in X.509 certificate
- see e.g. "A.1.1. RSA Public Key Syntax" of RFC 8017
CreateDummyCertificate: function(const Stuff, CertName: RawUtf8; Marker: cardinal): RawByteString;
Low-level function used by StuffExeCertificate()
- properly implemented by mormot.crypt.openssl.pas, but this unit has a stand-alone version using a pre-generated fixed certificate
- warning: the Marker should have no 0 byte within
CryptAlgoDefault: TCryptAsymAlgo = caaES256;
The prefered/default algorithm to be used wth X.509 certificates
- caaES256 (aka prime256v1 or NISTP-256) seems the new default (faster and with 128-bit of security), even if RSA-2048 (i.e. caaRS256) may still be used for compatiblity with legacy systems (but much slower signing and generation, with only 112-bit of security)
- used e.g. by 'x509-store' or 'x509-pki' for its DefaultCertAlgo method
CryptAsym: array[TCryptAsymAlgo] of TCryptAsym;
Direct access to the internal TCryptAsym factories
- may be nil if mormot.crypt.ecc.pas or mormot.crypt.rsa.pas units were not included
- you may use rather CryptAsymOpenSsl[] if OpenSSL is available
CryptAsymOpenSsl: array[TCryptAsymAlgo] of TCryptAsym;
Direct access to the mormot.crypt.openssl.pas TCryptAsym factories
- may be nil if this unit was not included or if OpenSSL is not available
- call RegisterOpenSsl once to initialize this lookup table
CryptCert: array[TCryptAsymAlgo] of TCryptCertAlgo;
Direct access to best known X.509 ICryptCert factories
- may map to CryptCertX509[] if only mormot.crypt.x509.pas is included
- but more standard CryptCertOpenSsl[] will be stored here if available
CryptCertOpenSsl: array[TCryptAsymAlgo] of TCryptCertAlgo;
Direct access to the mormot.crypt.openssl.pas ICryptCert factories
- may be nil if this unit was not included or if OpenSSL is not available
- to return a ICryptCert instance using OpenSSL RSA 2048 key, use e.g.
CryptCertOpenSsl[caaRS256].New
- call RegisterOpenSsl once to initialize this lookup table
CryptCertSyn: TCryptCertAlgo;
Direct access to the mormot.crypt.ecc.pas 'syn-ecc' algorithm
- may be nil if this unit was not included
CryptCertX509: array[TCryptAsymAlgo] of TCryptCertAlgo;
Direct access to the mormot.crypt.x509.pas ICryptCert factories
- may be nil if this unit was not included
- to get a new ICryptCert using OpenSSL RSA 2048 key over SHA-256, use e.g.
CryptCertX509[caaRS256].New
CryptPrivateKey: array[TCryptKeyAlgo] of TCryptPrivateKeyClass;
RSA/ECC private key factory
- implemented e.g. by mormot.crypt.ecc with TCryptPrivateKeyEcc, mormot.crypt.rsa with TCryptPrivateKeyRsa or mormot.crypt.opensssl with with TCryptPrivateKeyOpenSsl
- use as such:
var key: ICryptPrivateKey; ... key := CryptPrivateKey[ckaEcc].Create; if key.Load(...) then ...
CryptPublicKey: array[TCryptKeyAlgo] of TCryptPublicKeyClass;
RSA/ECC public key factory
- implemented e.g. by mormot.crypt.ecc with TCryptPublicKeyEcc, mormot.crypt.rsa with TCryptPublicKeyRsa or mormot.crypt.opensssl with with TCryptPublicKeyOpenSsl
- use as such:
var key: ICryptPublicKey; ... key := CryptPublicKey[ckaEcc].Create; if key.Load(...) then ...
CryptStoreOpenSsl: TCryptStoreAlgo;
Direct access to the mormot.crypt.openssl.pas 'x509-store' algorithm
- may be nil if this unit was not included or if OpenSSL is not available
- is currently nil because TCryptStoreOpenSsl is not stable yet
- call RegisterOpenSsl once to initialize this lookup table
CryptStoreSyn: TCryptStoreAlgo;
Direct access to the mormot.crypt.ecc.pas 'syn-store' algorithm
- may be nil if this unit was not included
CryptStoreSynNoCache: TCryptStoreAlgo;
Direct access to the mormot.crypt.ecc.pas 'syn-store-nocache' algorithm
- may be nil if this unit was not included
CryptStoreX509: TCryptStoreAlgo;
Direct access to the mormot.crypt.x509.pas ICryptStore factory
X509Parse: function(const Cert: RawByteString; out Info: TX509Parsed): boolean;
High-level function to decode X.509 Certificate main properties
- properly implemented by mormot.crypt.openssl or mormot.crypt.x509, but this unit will register our mormot.lib.sspi parser as failover on Windows