Purpose: Framework Core Cryptographic Process using OpenSSL
- 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.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.crypt.core | Framework Core Cryptographic Process (Hashing and Cypher) | |
mormot.crypt.ecc | Framework Core High-Level Public-Key Elliptic-Curve Cryptography | |
mormot.crypt.ecc256r1 | Framework Core Public-Key Cryptography with secp256r1/NISTP-256 ECC Curves | |
mormot.crypt.jwt | Framework Core JSON Web Tokens (JWT) Support | |
mormot.crypt.rsa | Framework Core RSA Support | |
mormot.crypt.secure | Framework Core Authentication and Security Features | |
mormot.lib.openssl11 | Low-level access to the OpenSSL 1.1 / 3.x Library |
Objects | Description | |
---|---|---|
EOpenSslAsymmetric | Exception class raised by the sign/verify classes of this unit | |
EOpenSslCrypto | Exception class raised by the AES classes of this unit | |
EOpenSslHash | Exception class raised by the hashing classes of this unit | |
TAesAbstractOsl | Handle AES cypher/uncypher with chaining with OpenSSL 1.1 | |
TAesCbcOsl | OpenSSL AES cypher/uncypher with Cipher-block chaining (CBC) | |
TAesCfbOsl | OpenSSL AES cypher/uncypher with Cipher feedback (CFB) | |
TAesCtrOsl | OpenSSL AES cypher/uncypher with 128-bit Counter mode (CTR) | |
TAesEcbOsl | OpenSSL AES cypher/uncypher without chaining (ECB) | |
TAesGcmOsl | OpenSSL AES-GCM cypher/uncypher | |
TAesOfbOsl | OpenSSL AES cypher/uncypher with Output feedback (OFB) | |
TAesOsl | Reusable wrapper around OpenSSL Cipher process | |
TAesPrngOsl | TAesPrng-compatible class using OpenSSL 1.1 | |
TCryptCertCacheOpenSsl | Maintain a cache of OpenSSL X.509 ICryptCert instances, from their DER/binary | |
TCryptPrivateKeyOpenSsl | Store an OpenSSL private key in ICryptPrivateKey format | |
TCryptPublicKeyOpenSsl | Store an OpenSSL public key in ICryptPublicKey format | |
TEcc256r1VerifyOsl | OpenSSL verification of a ECDSA signature using ECC secp256r1 cryptography | |
TJwtAbstractOsl | Abstract parent for OpenSSL JWT algorithms - never use this plain class! | |
TJwtEddsaOsl | Implements 'EdDSA' Ed25519 algorithm using OpenSSL | |
TJwtEs256KOsl | Implements 'ES256K' secp256k1 ECC algorithm using OpenSSL | |
TJwtEs256Osl | Implements 'ES256' secp256r1 ECC algorithm over SHA-256 using OpenSSL | |
TJwtEs384Osl | Implements 'ES384' secp384r1 ECC algorithm over SHA-384 using OpenSSL | |
TJwtEs512Osl | Implements 'ES512' ecp521r1 ECC algorithm over SHA-512 using OpenSSL | |
TJwtOpenSsl | Abstract parent for OpenSSL JWT algorithms - never use this plain class! | |
TJwtPs256Osl | Implements 'PS256' RSA-PSS algorithm over SHA-256 using OpenSSL | |
TJwtPs384Osl | Implements 'PS384' RSA-PSS algorithm over SHA-384 using OpenSSL | |
TJwtPs512Osl | Implements 'PS512' RSA-PSS algorithm over SHA-512 using OpenSSL | |
TJwtRs256Osl | Implements 'RS256' RSA algorithm over SHA-256 using OpenSSL | |
TJwtRs384Osl | Implements 'RS384' RSA algorithm over SHA-384 using OpenSSL | |
TJwtRs512Osl | Implements 'RS512' RSA algorithm over SHA-512 using OpenSSL | |
TOpenSslDigestAbstract | Abstract parent multi-algorithm hashing/HMAC wrapper for OpenSSL | |
TOpenSslHash | Convenient multi-algorithm wrapper for OpenSSL Hash algorithms | |
TOpenSslHmac | Convenient multi-algorithm wrapper for OpenSSL HMAC algorithms |
EOpenSslCrypto = class(EOpenSsl)
Exception class raised by the AES
classes of this unit
TAesPrngOsl = class(TAesPrngAbstract)
TAesPrng
-compatible class using OpenSSL 1.1
- we abbreviate OpenSsl as Osl in class names for brevity
- may be used instead of TAesPrng
if a "proven" generator is required - you could override MainAesPrng
global variable
- but mormot.crypt.core TAesPrng
is faster, especially for small output, and use a similar and proven 256-bit AES
-CTR source of randomness:
OpenSSL Random32 in 288.71ms i.e. 346,363/s, aver. 2us, 1.3 MB/s mORMot Random32 in 3.95ms i.e. 25,303,643/s, aver. 0us, 96.5 MB/s OpenSSL FillRandom in 240us, 397.3 MB/s mORMot FillRandom in 46us, 2 GB/s
constructor Create; override;
Initialize the CSPRNG using OpenSSL 1.1
- if the library is not available, will raise an Exception
class function IsAvailable: boolean; override;
Wrapper around function OpenSslIsAvailable
class function Main: TAesPrngAbstract; override;
Returns the single system-wide instance of TAesPrngOsl
- if you need to generate some random content, just call the TAesPrngOsl.Main.FillRandom() overloaded methods, or directly TAesPrngOsl.Fill() class methods
procedure FillRandom(Buffer: pointer; Len: PtrInt); override;
Fill a binary buffer with some pseudorandom data
- this method is thread-safe
- is just a wrapper around RAND_bytes
() API call
TAesOsl = object(TObject)
Reusable wrapper around OpenSSL Cipher
process
Ctx: array[boolean] of PEVP_CIPHER_CTX;
Computed from TAesAbstractOsl.AlgoName
procedure Init(aOwner: TAesAbstract; aCipherName: PUtf8Char);
Set and reused in CallEvp()
TAesAbstractOsl = class(TAesAbstract)
Handle AES
cypher/uncypher with chaining with OpenSSL 1.1
- we abbreviate OpenSsl as Osl in class names for brevity
- use any of the inherited implementation, corresponding to the chaining mode required - TAesEcbOsl
, TAesCbcOsl
, TAesCfbOsl
, TAesOfbOsl
and TAesCtrOsl
classes to handle in ECB, CBC, CFB, OFB and CTR mode (including PKCS7-like padding)
- those classes are re-entrant, i.e. that you can call the Encrypt
* or Decrypt
* methods on the same instance several times
destructor Destroy; override;
Release the used instance memory and resources
function Clone: TAesAbstract; override;
Circumvent Delphi bug about const aKey creates a new instance with the very same values
- directly copy the existing OpenSSL context for efficiency
function CloneEncryptDecrypt: TAesAbstract; override;
Compute a class instance similar to this one, for performing the reverse
encryption/decryption process
- will return self to avoid creating two instances
class function IsAvailable: boolean; override;
Wrapper around function OpenSslIsAvailable
- actual cipher
won't be checked until Create() since we need the keysize
procedure Decrypt(BufIn, BufOut: pointer; Count: cardinal); override;
Perform the AES
un-cypher in the corresponding mode
procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); override;
Perform the AES
cypher in the corresponding mode
TAesEcbOsl = class(TAesAbstractOsl)
OpenSSL AES
cypher/uncypher without chaining (ECB)
- this mode is known to be less secure than the others
TAesCbcOsl = class(TAesAbstractOsl)
OpenSSL AES
cypher/uncypher with Cipher
-block chaining (CBC)
TAesCfbOsl = class(TAesAbstractOsl)
OpenSSL AES
cypher/uncypher with Cipher
feedback (CFB)
- our TAesCfb
class is faster than OpenSSL on x86_64:
mormot aes-128-cfb in 6.95ms i.e. 359247/s or 764.5 MB/s mormot aes-256-cfb in 9.40ms i.e. 265816/s or 565.7 MB/s openssl aes-128-cfb in 10.53ms i.e. 237326/s or 505 MB/s openssl aes-256-cfb in 13.18ms i.e. 189652/s or 403.6 MB/s
TAesOfbOsl = class(TAesAbstractOsl)
OpenSSL AES
cypher/uncypher with Output feedback (OFB)
- our TAesOfb
class is faster than OpenSSL on x86_64:
mormot aes-128-ofb in 6.88ms i.e. 363002/s or 772.5 MB/s mormot aes-256-ofb in 9.37ms i.e. 266808/s or 567.8 MB/s openssl aes-128-ofb in 7.82ms i.e. 319693/s or 680.3 MB/s openssl aes-256-ofb in 10.39ms i.e. 240523/s or 511.8 MB/s
TAesCtrOsl = class(TAesAbstractOsl)
OpenSSL AES
cypher/uncypher with 128-bit Counter mode (CTR)
- similar to TAesCtrNist
, not our proprietary TAesCtrAny
with a 64-bit CTR
- our TAesCtrNist
class is faster than OpenSSL on x86_64:
mormot aes-128-ctr in 1.99ms i.e. 1254390/s or 2.6 GB/s mormot aes-256-ctr in 2.64ms i.e. 945179/s or 1.9 GB/s openssl aes-128-ctr in 2.23ms i.e. 1121076/s or 2.3 GB/s openssl aes-256-ctr in 2.80ms i.e. 891901/s or 1.8 GB/s
TAesGcmOsl = class(TAesGcmAbstract)
OpenSSL AES
-GCM cypher/uncypher
- implements AEAD (authenticated-encryption with associated-data) process via MacSetNonce/MacEncrypt or AesGcmAad/AesGcmFinal methods
- OpenSSL is faster than our TAesGcm
class, but not so much:
openssl aes-128-gcm in 2.86ms i.e. 874125/s or 1.8 GB/s openssl aes-256-gcm in 3.43ms i.e. 727590/s or 1.5 GB/s mormot aes-128-gcm in 3.45ms i.e. 722752/s or 1.5 GB/s mormot aes-256-gcm in 4.11ms i.e. 607385/s or 1.2 GB/s
- WARNING: AEAD associated information is currently unsupported by TAesGcmOsl
, due to some obscure OpenSSL padding issue in our code - GMAC will be properly handled by TAesGcmOsl
, but you should use plain TAesGcm
instead if you really need to authenticate some associated information
function AesGcmFinal(var Tag: TAesBlock; TagLen: integer): boolean; override;
AES
-GCM pure alternative to MacEncryptGetTag/MacDecryptCheckTag
- after Encrypt
, fill tag with the GCM value of the data and return true
- after Decrypt
, return true only if the GCM value of the data match tag
function Clone: TAesAbstract; override;
Creates a new instance with the very same values
- by design, our classes will use TAesGcmEngine
stateless context, so this method will just copy the current fields to a new instance, by-passing the key creation step
function CloneEncryptDecrypt: TAesAbstract; override;
Compute a class instance similar to this one, for performing the reverse
encryption/decryption process
- will return self to avoid creating two instances
procedure AesGcmAad(Buf: pointer; Len: integer); override;
AES
-GCM pure alternative to MacSetNonce() - unsupported
- set the IV as usual (only the first 12 bytes will be used for GCM), then optionally append
any AEAD data with this method; warning: you need to call Encrypt
() once before - perhaps as Encrypt
(nil, nil, 0)
- WARNING: AEAD associated information is currently unsupported by TAesGcmOsl
, due to some obscure OpenSSL padding issue in our code - GMAC will be properly handled by TAesGcmOsl
, but you should use plain TAesGcm
instead if you really need to authenticate some associated information
EOpenSslHash = class(EOpenSsl)
Exception class raised by the hashing classes of this unit
TOpenSslDigestAbstract = class(TObject)
Abstract parent multi-algorithm hashing/HMAC
wrapper for OpenSSL
function Digest(Dest: pointer = nil): cardinal; virtual; abstract;
Computes the hash
of all supplied messages
- store
it internally the DigestValue
buffer, or copy it into Dest buffer which is typically a THash256
or THash512
variable
- returns actual DigestValue
/Dest buffer length, i.e. DigestSize
function DigestHex: RawUtf8;
Computes the Hash
/HMAC
of all supplied message as lowercase
hexa chars
class function IsAvailable: boolean;
Wrapper around function OpenSslIsAvailable
procedure Update(Data: pointer; DataLength: integer); overload; virtual; abstract;
Call this method for each continuous message block
- iterate over all message blocks, then call Digest
to retrieve the HMAC
procedure Update(const Data: RawByteString); overload;
Call this method for each continuous message block
property DigestSize: cardinal read fDigestSize;
How many bytes have been stored in DigestValues, after a call to Digest
property DigestValue: THash512Rec read fDigestValue;
Raw access to the final Message Digest
, after a call to the Digest
method
- if HashSize as supplied to Create() is bigger than 64, first bytes will be truncated in this field - you should specify a buffer to Digest
() call
TOpenSslHash = class(TOpenSslDigestAbstract)
Convenient multi-algorithm wrapper for OpenSSL Hash
algorithms
constructor Create(const Algorithm: RawUtf8; HashSize: cardinal = 0);
Initialize the internal hashing structure for a specific algorithm
- Algorithm is one of `openssl list -digest
-algorithms`
- if Algorithm is not specified, EVP_sha256
will be used
- for XOF hash
functions such as 'shake256', the hashSize option can be used to specify the desired output length in bytes
- raise an EOpenSslHash
exception on unknown/unsupported algorithm
destructor Destroy; override;
Release the digest
context
function Digest(Dest: pointer = nil): cardinal; override;
Computes the hash
of all supplied messages
- store
it internally the DigestValue buffer, or copy it into Dest buffer which is typically a THash256
or THash512
variable
- returns actual DigestValue/Dest buffer length, i.e. DigestSize
class function Hash(const Algorithm: RawUtf8; const Data: RawByteString; HashSize: cardinal = 0): RawUtf8;
Compute the message authentication code using `Algorithm` as hash
function
procedure Update(Data: pointer; DataLength: integer); override;
Call this method for each continuous message block
- iterate over all message blocks, then call Digest
to retrieve the Hash
TOpenSslHmac = class(TOpenSslDigestAbstract)
Convenient multi-algorithm wrapper for OpenSSL HMAC
algorithms
constructor Create(const Algorithm: RawUtf8; const Key: RawByteString); overload;
Initialize the internal HMAC
structure for a specific Algorithm and Key
constructor Create(const Algorithm: RawUtf8; Key: pointer; KeyLength: cardinal); overload;
Initialize the internal HMAC
structure for a specific Algorithm and Key
- Algorithm is one of `openssl list -digest
-algorithms`
- if Algorithm is not specified, EVP_sha256
will be used
- Key/KeyLen define the HMAC
associated salt
- raise an EOpenSslHash
exception on unknown/unsupported algorithm
destructor Destroy; override;
Release the digest
context
function Digest(Dest: pointer = nil): cardinal; override;
Computes the HMAC
of all supplied messages
- store
it internally the DigestValue buffer, or copy it into Dest buffer which is typically a THash256
or THash512
variable
- returns actual DigestValue/Dest buffer length, i.e. DigestSize
class function Hmac(const Algorithm: RawUtf8; const Data, Key: RawByteString): RawUtf8; overload;
Compute the HMAC
using `algorithm` as hash
function
class function Hmac(const Algorithm: RawUtf8; const Data: RawByteString; Key: pointer; KeyLength: cardinal): RawUtf8; overload;
Compute the HMAC
using `algorithm` as hash
function
procedure Update(Data: pointer; DataLength: integer); override;
Call this method for each continuous message block
- iterate over all message blocks, then call Digest
to retrieve the Hash
EOpenSslAsymmetric = class(EOpenSsl)
Exception class raised by the sign
/verify classes of this unit
TEcc256r1VerifyOsl = class(TEcc256r1VerifyAbstract)
OpenSSL verification of a ECDSA signature using ECC secp256r1 cryptography
- assigned to TEcc256r1Verify
global meta-class at startup
constructor Create(const pub: TEccPublicKey); override;
Initialize the verifier with a given ECC compressed public key
destructor Destroy; override;
Finalize this instance
function Verify(const hash: TEccHash; const sign: TEccSignature): boolean; override;
Validate a signature against a hash
using ECC
TJwtOpenSsl = class(TJwtAsym)
Abstract parent for OpenSSL JWT algorithms - never use this plain class!
constructor Create(const aJwtAlgorithm, aHashAlgorithm: RawUtf8; aGenEvpType, aGenBitsOrCurve: integer; const aPrivateKey, aPublicKey: RawByteString; const aPrivateKeyPassword, aPublicKeyPassword: SpiUtf8; aClaims: TJwtClaims; const aAudience: array of RawUtf8; aExpirationMinutes: integer = 0; aIDIdentifier: TSynUniqueIdentifierProcess = 0; aIDObfuscationKey: RawUtf8 = ''; aIDObfuscationKeyNewKdf: integer = 0); reintroduce;
Initialize the JWT processing instance using any supported OpenSSL algorithm
destructor Destroy; override;
Finalize the instance
class function IsAvailable: boolean; virtual;
Wrapper around OpenSslIsAvailable
() function
property AsymAlgo: TCryptAsymAlgo read fAsymAlgo;
The asymmetric algorithm, as defined by inherted classes
property HashAlgorithm: RawUtf8 read fHashAlgorithm;
The OpenSSL hash
algorithm, as supplied to the constructor
TJwtAbstractOsl = class(TJwtOpenSsl)
Abstract parent for OpenSSL JWT algorithms - never use this plain class!
- inherited classes implement all official algorithms from https://jwt.io
- we abbreviate OpenSsl as Osl in class names for brevity
- some numbers from our regresssion tests on Linux x86_64 for JWT validation:
100 RS256 in 2.03ms i.e. 47.8K/s, aver. 20us 100 RS384 in 1.99ms i.e. 48.9K/s, aver. 19us 100 RS512 in 1.99ms i.e. 48.9K/s, aver. 19us 100 PS256 in 2.30ms i.e. 42.3K/s, aver. 23us 100 PS384 in 2.26ms i.e. 43.1K/s, aver. 22us 100 PS512 in 2.75ms i.e. 35.4K/s, aver. 27us 100 ES256 in 8.64ms i.e. 11.3K/s, aver. 86us 100 ES384 in 81.43ms i.e. 1.1K/s, aver. 814us 100 ES512 in 59.81ms i.e. 1.6K/s, aver. 598us 100 ES256K in 40.43ms i.e. 2.4K/s, aver. 404us 100 EdDSA in 11.55ms i.e. 8.4K/s, aver. 115us
constructor Create( const aPrivateKey, aPublicKey: RawByteString; const aPrivateKeyPassword, aPublicKeyPassword: SpiUtf8; aClaims: TJwtClaims; const aAudience: array of RawUtf8; aExpirationMinutes: integer = 0; aIDIdentifier: TSynUniqueIdentifierProcess = 0; aIDObfuscationKey: RawUtf8 = ''; aIDObfuscationKeyNewKdf: integer = 0); reintroduce;
Initialize the JWT processing instance calling SetAlgorithms abstract method
- the supplied key(s) could be in PEM or raw DER binary format
- the supplied set of claims are expected to be defined in the JWT payload
- aAudience are the allowed values for the jrcAudience claim
- aExpirationMinutes is the deprecation time for the jrcExpirationTime claim
- aIDIdentifier and aIDObfuscationKey/aIDObfuscationKeyNewKdf are passed to a TSynUniqueIdentifierGenerator
instance used for jrcJwtID claim
class function IsAvailable: boolean; override;
Wrapper around OpenSslSupports
() function
class procedure GenerateBinaryKeys(out PrivateKey, PublicKey: RawByteString);
Generate a private/public keys pair for this algorithm in raw DER format
- the new key will have RSA_DEFAULT_GENERATION_BITS
, i.e. 2048-bit
class procedure GenerateKeys(out PrivateKey, PublicKey: RawUtf8);
Generate a private/public keys pair for this algorithm in PEM text
format
- the new key will have RSA_DEFAULT_GENERATION_BITS
, i.e. 2048-bit
TJwtEs256Osl = class(TJwtAbstractOsl)
Implements 'ES256' secp256r1 ECC algorithm over SHA-256 using OpenSSL
- note that our TJwtEs256
class is slightly faster on Linux x86_64:
TJwtEs256 pascal: 100 ES256 in 33.57ms i.e. 2.9K/s, aver. 335us TJwtEs256 OpenSSL: 100 ES256 in 6.90ms i.e. 14.1K/s, aver. 69us TJwtEs256Osl: 100 ES256 in 8.64ms i.e. 11.3K/s, aver. 86us
TJwtEs384Osl = class(TJwtAbstractOsl)
Implements 'ES384' secp384r1 ECC algorithm over SHA-384 using OpenSSL
TJwtEs512Osl = class(TJwtAbstractOsl)
Implements 'ES512' ecp521r1 ECC algorithm over SHA-512 using OpenSSL
TJwtEs256KOsl = class(TJwtAbstractOsl)
Implements 'ES256K' secp256k1 ECC algorithm using OpenSSL
TJwtRs256Osl = class(TJwtAbstractOsl)
Implements 'RS256' RSA algorithm over SHA-256 using OpenSSL
TJwtRs384Osl = class(TJwtAbstractOsl)
Implements 'RS384' RSA algorithm over SHA-384 using OpenSSL
TJwtRs512Osl = class(TJwtAbstractOsl)
Implements 'RS512' RSA algorithm over SHA-512 using OpenSSL
TJwtPs256Osl = class(TJwtAbstractOsl)
Implements 'PS256' RSA-PSS algorithm over SHA-256 using OpenSSL
TJwtPs384Osl = class(TJwtAbstractOsl)
Implements 'PS384' RSA-PSS algorithm over SHA-384 using OpenSSL
TJwtPs512Osl = class(TJwtAbstractOsl)
Implements 'PS512' RSA-PSS algorithm over SHA-512 using OpenSSL
TJwtEddsaOsl = class(TJwtAbstractOsl)
Implements 'EdDSA' Ed25519 algorithm using OpenSSL
TCryptPublicKeyOpenSsl = class(TCryptPublicKey)
Store
an OpenSSL public key in ICryptPublicKey
format
- set to mormot.crypt.secure CryptPublicKey
[] factories by RegisterOpenSsl
TCryptPrivateKeyOpenSsl = class(TCryptPrivateKey)
Store
an OpenSSL private key in ICryptPrivateKey
format
- set to mormot.crypt.secure CryptPrivateKey
[] factories by RegisterOpenSsl
TCryptCertCacheOpenSsl = class(TCryptCertCache)
Maintain a cache of OpenSSL X.509 ICryptCert
instances, from their DER/binary
- defined here so that you could use OpenSSL for your certificates process
TJwtAbstractOslClass = class of TJwtAbstractOsl;
Meta-class of all OpenSSL JWT algorithms
CAA_BITSORCURVE: array[TCryptAsymAlgo] of integer = ( NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, NID_secp256k1, RSA_DEFAULT_GENERATION_BITS, RSA_DEFAULT_GENERATION_BITS, RSA_DEFAULT_GENERATION_BITS, RSA_DEFAULT_GENERATION_BITS, RSA_DEFAULT_GENERATION_BITS, RSA_DEFAULT_GENERATION_BITS, 0);
CaaES256 caaES384 caaES512 caaES256K caaRS256 caaRS384 caaRS512 caaPS256 caaPS384 caaPS512 caaEdDSA
Functions or procedures | Description | |
---|---|---|
ecc_make_key_osl | Mormot.crypt.ecc256r1 compatible function for asymmetric key generation | |
ecdh_shared_secret_osl | Mormot.crypt.ecc256r1 compatible function for ECDH shared secret computation | |
ecdsa_sign_osl | Mormot.crypt.ecc256r1 compatible function for asymmetric key signature | |
ecdsa_verify_osl | Mormot.crypt.ecc256r1 compatible function for asymmetric key verification | |
OpenSslGenerateBinaryKeys | Generate a public/private pair of keys in raw DER binary format | |
OpenSslGenerateKeys | Generate a public/private pair of keys in PEM text format | |
OpenSslGenerateKeys | Generate a public/private pair of keys in raw OpenSSL format | |
OpenSslGetMd | Retrieve a low-level PEVP_MD digest from mORMot TCryptAsymAlgo enum | |
OpenSslGetMd | Retrieve a low-level PEVP_MD digest from mORMot THashAlgo enum | |
OpenSslGetMdByName | Retrieve a low-level PEVP_MD digest from its algorithm name | |
OpenSslLoad | Compute a new ICryptCert OpenSSL instance from DER or PEM input | |
OpenSslSign | Asymmetric digital signature of some Message using a given PrivateKey | |
OpenSslSupports | Check if a TCryptAsymAlgo of public/private pair of keys is supported | |
OpenSslSupports | Check if an OpenSSL given type of public/private pair of keys is supported | |
OpenSslVerify | Asymmetric digital verification of some Message using a given PublicKey | |
OpenSslX509Parse | High-level function to decode X.509 certificate main properties using OpenSSL | |
RegisterOpenSsl | Call once at program startup to use OpenSSL when its performance matters | |
X509Algo | Guess the asymmetric algorithm of this OpenSSL X.509 certificate |
function ecc_make_key_osl(out PublicKey: TEccPublicKey; out PrivateKey: TEccPrivateKey): boolean;
Mormot.crypt.ecc256r1 compatible function for asymmetric key generation
- this OpenSSL-powered function will replace our slower mormot.crypt.ecc256r1
OpenSSL: 300 Ecc256r1MakeKey in 7.75ms i.e. 38,664/s, aver. 25us mORMot: 300 Ecc256r1MakeKey in 255ms i.e. 1,176/s, aver. 850us
- directly access OpenSSL prime256v1, so faster than OpenSslGenerateKeys
()
function ecdh_shared_secret_osl(const PublicKey: TEccPublicKey; const PrivateKey: TEccPrivateKey; out Secret: TEccSecretKey): boolean;
Mormot.crypt.ecc256r1 compatible function for ECDH shared secret computation
- this OpenSSL-powered function will replace our slower pascal/c code
OpenSSL: 598 Ecc256r1SharedSecret in 67.98ms i.e. 8,796/s, aver. 113us mORMot: 598 Ecc256r1SharedSecret in 537.95ms i.e. 1,111/s, aver. 899us
function ecdsa_sign_osl(const PrivateKey: TEccPrivateKey; const Hash: TEccHash; out Signature: TEccSignature): boolean;
Mormot.crypt.ecc256r1 compatible function for asymmetric key signature
- this OpenSSL-powered function will replace our slower pascal/c code
OpenSSL: 300 Ecc256r1Sign in 11.66ms i.e. 25,711/s, aver. 38us mORMot: 300 Ecc256r1Sign in 262.72ms i.e. 1,141/s, aver. 875us
- directly access OpenSSL prime256v1, so faster than OpenSslSign
()
function ecdsa_verify_osl(const PublicKey: TEccPublicKey; const Hash: TEccHash; const Signature: TEccSignature): boolean;
Mormot.crypt.ecc256r1 compatible function for asymmetric key verification
- this OpenSSL-powered function will replace our slower pascal/c code
OpenSSL: 300 Ecc256r1Verify in 41.32ms i.e. 7,260/s, aver. 137us mORMot: 300 Ecc256r1Verify in 319.32ms i.e. 939/s, aver. 1.06ms
- directly access OpenSSL prime256v1, so faster than OpenSslVerify
()
procedure OpenSslGenerateBinaryKeys(EvpType, BitsOrCurve: integer; out PrivateKey, PublicKey: RawByteString; const PrivateKeyPassWord: SpiUtf8 = '');
Generate a public/private pair of keys in raw DER binary format
- if EvpType is EVP_PKEY_DSA
, EVP_PKEY_DH
or EVP_PKEY_RSA
or EVP_PKEY_RSA_PSS
, BitsOrCurve is the number of bits of the key
- if EvpType is EVP_PKEY_EC
, BitsOrCurve is the Elliptic curve NID (e.g. NID_X9_62_prime256v1
)
- if EvpType is EVP_PKEY_ED25519
, BitsOrCurve is ignored
function OpenSslGenerateKeys(EvpType, BitsOrCurve: integer): PEVP_PKEY; overload;
Generate a public/private pair of keys in raw OpenSSL format
- if EvpType is EVP_PKEY_DSA
, EVP_PKEY_DH
or EVP_PKEY_RSA
or EVP_PKEY_RSA_PSS
, BitsOrCurve is the number of bits of the key
- if EvpType is EVP_PKEY_EC
, BitsOrCurve is the curve NID (e.g. NID_X9_62_prime256v1
)
- if EvpType is EVP_PKEY_ED25519
, BitsOrCurve is ignored
- caller should result.Free once done with the private key returned instance
procedure OpenSslGenerateKeys(EvpType, BitsOrCurve: integer; out PrivateKey, PublicKey: RawUtf8; const PrivateKeyPassWord: SpiUtf8 = ''); overload;
Generate a public/private pair of keys in PEM text
format
- if EvpType is EVP_PKEY_DSA
, EVP_PKEY_DH
or EVP_PKEY_RSA
or EVP_PKEY_RSA_PSS
, BitsOrCurve is the number of bits of the key
- if EvpType is EVP_PKEY_EC
, BitsOrCurve is the Elliptic curve NID (e.g. NID_X9_62_prime256v1
)
- if EvpType is EVP_PKEY_ED25519
, BitsOrCurve is ignored
function OpenSslGetMd(Algorithm: THashAlgo): PEVP_MD; overload;
Retrieve a low-level PEVP_MD
digest
from mORMot THashAlgo
enum
- returns nil if not found, e.g. if OpenSsl is not available
function OpenSslGetMd(Algorithm: TCryptAsymAlgo): PEVP_MD; overload;
Retrieve a low-level PEVP_MD
digest
from mORMot TCryptAsymAlgo
enum
- returns nil if not found, e.g. if OpenSsl is not available
function OpenSslGetMdByName(const Algorithm: RawUtf8; const Caller: shortstring): PEVP_MD; overload;
Retrieve a low-level PEVP_MD
digest
from its algorithm name
- raise an EOpenSslHash
if this algorithm is not found
function OpenSslLoad(const Cert: RawByteString): ICryptCert;
Compute a new ICryptCert
OpenSSL instance from DER or PEM input
- returns nil if the input is not correct or not supported
- returns non-nil TCryptCertOpenSsl instance from function LoadCertificate
()
- will guess the proper TCryptCertAlgoOpenSsl to use for the ICryptCert
- called e.g. by TCryptCertCacheOpenSsl
function OpenSslSign(const Algorithm: RawUtf8; Message, PrivateKey: pointer; MessageLen, PrivateKeyLen: integer; out Signature: RawByteString; const PrivateKeyPassword: SpiUtf8 = ''): cardinal;
Asymmetric digital signature of some Message using a given PrivateKey
- if Algorithm is '', EVP_sha256
will be used as message Digest
- if Algorithm is 'null
', no Digest
is done before signature - which is mandatory e.g. for ed25519 which uses internally SHA-512
- returns 0 on error, or the result Signature size in bytes
function OpenSslSupports(EvpType: integer): boolean; overload;
Check if an OpenSSL given type of public/private pair of keys is supported
- some older OpenSSL versions do not support e.g. EVP_PKEY_ED25519
function OpenSslSupports(Algo: TCryptAsymAlgo): boolean; overload;
Check if a TCryptAsymAlgo
of public/private pair of keys is supported
function OpenSslVerify(const Algorithm: RawUtf8; const PublicKeyPassword: SpiUtf8; Message, PublicKey, Signature: pointer; MessageLen, PublicKeyLen, SignatureLen: integer; const Engine: RawUtf8 = ''): boolean;
Asymmetric digital verification of some Message using a given PublicKey
- if Algorithm is '', EVP_sha256
will be used as message Digest
- if Algorithm is 'null
', no Digest
is done before signature - which is mandatory e.g. for ed25519 which uses internally SHA-512
- returns false on error, or true if the Message has been authenticated
function OpenSslX509Parse(const Cert: RawByteString; out Info: TX509Parsed): boolean;
High-level function to decode X.509 certificate main properties using OpenSSL
- assigned to mormot.core.secure X509Parse
() redirection by RegisterOpenSsl
procedure RegisterOpenSsl;
Call once at program startup to use OpenSSL when its performance matters
- to be typically called after function OpenSslInitialize
() by your project
- redirects TAesGcmFast (and TAesCtrFast on i386) globals to OpenSSL
- redirects raw mormot.crypt.ecc256r1 functions to use OpenSSL which is much faster than our stand-alone pure pascal version
- register OpenSSL for our Asym
() and Cert
() high-level factory, and also for CryptPublicKey
[] and CryptPrivateKey
[]
- RegisterX509
from mormot.crypt.x509.pas can be called after this procedure, to register TCryptCertAlgoX509 with ckaEcc384, ckaEcc512 and ckaEdDSA
function X509Algo(x: PX509): TCryptAsymAlgo;
Guess the asymmetric algorithm of this OpenSSL X.509 certificate
- returns nil if x is nil
- raise an EOpenSslCert if x has an unsupported algorithm
- warning: caaES256K can not be distinguished from caaES256
- is defined here because TCryptAsymAlgo
is from mormot.crypt.secure.pas which does not fit in the low-level mormot.lib.openssl.pas unit