The OpenSource mORMot framework has a strong set of cryptography features. It offers symmetric cryptography with hashing and encryption, together with asymmetric cryptography via private/public key pairs. Its optimized pascal and assembly engines can be embedded into your executable, but you could also call an external OpenSSL library if needed. This session will present mormot.crypt.* units, and apply them to some use cases, from low-level algorithms to high-level JWT or file encryption and signing.
6. mORMot 2 Cryptography
• Disclaimer
This is a PRACTICAL description
› not a PhD dissertation
› includes biases and reductions
› cryptography is a serious matter
7. mORMot 2 Cryptography
• Disclaimer
Cryptography is error prone
› the golden rule is
to not reinvent the wheel
› https://security.stackexchange.com
8. mORMot 2 Cryptography
• Disclaimer
Practical goals of this session
Hashes / Encryption / Asymmetric ???
Find in your way in mORMot source
Understand the mORMot tests output
9. mORMot 2 Cryptography
• Worth saying
Test Vectors and regression/performance tests supplied
32-bit performance is lower (less optimized)
Old non-AES-NI CPUs will fallback to pascal/asm version
AARCH64 has its own static .o HW optimized code
Oldest Delphi lack of all needed asm opcodes
10. mORMot 2 Cryptography
• Why mORMot ?
Used on production since years
Audited internally by at least one 1B$ company
Can switch to OpenSSL if needed/required
11. mORMot 2 Cryptography
• Why not mORMot 1 ?
mORMot 2 is a deep rewrite
Maintainability
Performance
New features (1.18 as a bug-fix branch)
12. mORMot 2 Cryptography
• mORMot 2 Maintainability
Units names and size
mormot.crypt.core.pas mormot.crypt.jwt.pas
mormot.crypt.ecc.pas mormot.crypt.ecc256r1.pas
mormot.crypt.openssl.pas mormot.crypt.secure.pas
13. mORMot 2 Cryptography
• mORMot 2 Maintainability
Units names and size
mormot.crypt.core.pas
mormot.crypt.core.asmx64.inc
mormot.crypt.core.asmx86.inc
14. mORMot 2 Cryptography
• mORMot 2 Maintainability
Units names and size
mormot.crypt.openssl.pas
mormot.lib.openssl11.pas
15. mORMot 2 Cryptography
• mORMot 2 Maintainability
Units names and size
src/crypt/mormot.crypt.*
src/lib/mormot.lib.*
…
16. mORMot 2 Cryptography
• mORMot 2 Maintainability
Units names and size
src/crypt/mormot.crypt.*
src/lib/mormot.lib.*
src/core/mormot.core.*
…
17. mORMot 2 Cryptography
• mORMot 2 Performance
mormot.crypt.core.asmx64.inc
rewritten since 1.18
aes-ctr now faster than OpenSSL
AARCH64 HW acceleration
aes sha2 crc32c
18. mORMot 2 Cryptography
• mORMot 2 Performance
mormot.crypt.openssl.pas
OpenSSL 1.1 can be used (not 1.0)
if available (dynamic/delayed loading on Win + POSIX)
if faster
for other algorithms (RSA)
for regulatory purposes
24. mORMot 2 Hashes
• Cryptographic Hashes
Practical definition:
Proven Algorithm
which has no known collision
(content can’t be forged to get the same hash)
25. mORMot 2 Hashes
• Cryptographic Hashes
sha2 256-bit
32-bit oriented algorithm – still safe and fast
26. mORMot 2 Hashes
• Cryptographic Hashes
sha512 384/512-bit
64-bit oriented algorithm – used on TLS
28. mORMot 2 Hashes
• Cryptographic Hashes
Some Algorithms require a salt and cascaded run
when used for digital signature
e.g. HMAC-SHA256 HMAC-SHA512
Some Algorithms don’t need a double run
e.g. SHA-3
29. mORMot 2 Hashes
• Cryptographic Hashes
When derivating a hash from a password/secret
Single hashing ease brute force with dictionaries
Rainbow tables do exist
30. mORMot 2 Hashes
• Cryptographic Hashes
When derivating a hash from a password/secret
Single hashing ease brute force with dictionaries
Rainbow tables do exist
Use dedicated PBKDF functions with huge rounds count
e.g. Pbkdf2HmacSha256()
Consider a client-side challenge
(server computes a hash and let the client iterate to find a match)
32. mORMot 2 Hashes
• Non-Cryptographic Hashes
Collisions have been disclosed
on some Cryptographic Hashes
e.g. MD5 SHA1
But still slow to compute (<<1GB/s)
Not useful in practice, but for retro compatibility
33. mORMot 2 Hashes
• Non-Cryptographic Hashes
32-bit general purpose hashes
Have (a lot of) known collisions
Are much faster (up to 20GB/s with HW opcodes)
Are not used for authentication or fingerprint
but e.g. for a hash table (modulo table size)
or to detect transmission errors
35. mORMot 2 Hashes
• Non-Cryptographic Hashes
BJ = Bob Jenkins as used by Delphi RTL (slow)
crc32 = as used in zip gzip (some HW)
crc32c = HW opcodes in Intel/AMD/ARM
xxhash32 … (and a lot of friends) = “fast” SW algorithms
aesni32 = default mORMot 2 hasher
36. mORMot 2 Hashes
• Non-Cryptographic Hashes
aesni32 = default mORMot 2 hasher
Hardware Accelerated on Intel/AMD (aes-ni)
Randomly seeded to avoid hash flooding
Small number of collisions (AES permutations)
Proven – used in golang RTL since years
Fallback to crc32c or xxhash32 on old CPUs
37. mORMot 2 Hashes
Some numbers on Intel Core i5 7300U
aes-ni pclmulqdq sse4.2 avx avx2
38. mORMot 2 Hashes
2500 crc32c in 225us i.e. 10.5M/s or 23 GB/s
2500 xxhash32 in 833us i.e. 2.8M/s or 6.2 GB/s
2500 crc32 in 343us i.e. 6.9M/s or 15.1 GB/s
2500 adler32 in 240us i.e. 9.9M/s or 21.6 GB/s
2500 hash32 in 447us i.e. 5.3M/s or 11.6 GB/s
2500 aesnihash in 221us i.e. 10.7M/s or 23.5 GB/s
2500 md5 in 8.29ms i.e. 294.2K/s or 641.1 MB/s
2500 sha1 in 13.75ms i.e. 177.4K/s or 386.7 MB/s
2500 hmacsha1 in 15.03ms i.e. 162.3K/s or 353.8 MB/s
2500 sha256 in 17.06ms i.e. 143.1K/s or 311.8 MB/s
2500 hmacsha256 in 18.60ms i.e. 131.2K/s or 285.9 MB/s
2500 sha384 in 11.48ms i.e. 212.5K/s or 463.2 MB/s
2500 hmacsha384 in 13.62ms i.e. 179.1K/s or 390.4 MB/s
2500 sha512 in 11.52ms i.e. 211.8K/s or 461.7 MB/s
2500 hmacsha512 in 13.62ms i.e. 179.1K/s or 390.4 MB/s
2500 sha3_256 in 26.24ms i.e. 93K/s or 202.7 MB/s
2500 sha3_512 in 47.86ms i.e. 51K/s or 111.1 MB/s
41. mORMot 2 Hashes
• Non-Cryptographic Hashes
Base Functions
Direct Low-Level records
High Level Multi-Algorithm Hasher
42. mORMot 2 Hashes
• Non-Cryptographic Hashes
Base Functions
in mormot.core.base.pas
mormot.lib.z.pas
e.g. crc32c() aesnihash() xxhash32()
DefaultHasher()
crc32()
43. mORMot 2 Hashes
• Non-Cryptographic Hashes
Base Functions
in mormot.core.base.pas
crc64c() crc128c() crc256c()
aesnihash64/128/256()
DefaultHasher64/128/256()
crcblock() = 4 x crc32c() for 128-bit checksums
44. mORMot 2 Hashes
• Non-Cryptographic Hashes
Direct Low-Level records
in mormot.crypt.core.pas
e.g. TMD5.Init/Update/Final + MD5()
TSha256.Init/Update/Final + Sha256()
THmacSha256.Init/Update/Final …
45. mORMot 2 Hashes
• Non-Cryptographic Hashes
Direct Low-Level records
why record and not class ?
less likely to leak memory
single purpose (easier to audit)
direct copy for thread-safe pre-computed reuse
46. mORMot 2 Hashes
• Non-Cryptographic Hashes
High Level Multi-Algorithm Hasher
in mormot.crypt.secure.pas
TSignAlgo = (saSha1,
saSha256,saSha384,saSha512,
saSha3224,saSha3256,saSha3384,saSha3512,
saSha3S128,saSha3S256);
47. mORMot 2 Hashes
• Non-Cryptographic Hashes
High Level Multi-Algorithm Hasher
in mormot.crypt.secure.pas
TSynSigner.Init/Update/Final/Pbkdf2
TSynHasher.Init/Update/Final
TStreamRedirect* classes
HashFile() (single or multi-algo)
52. mORMot 2 Encryption
• Advanced Encryption Standard (AES)
16-byte = 128-bit block cipher = TAesBlock
Always 128-bit blocks, even on 192/256-bit keys
AES requires padding for the last bytes
e.g. PKCS7
(encrypted output is bigger than plain data)
54. mORMot 2 Encryption
• Advanced Encryption Standard (AES)
Requires a Chaining Mode – never use ECB
(source: Wikipedia Block Cipher Mode of Operation)
55. mORMot 2 Encryption
• Advanced Encryption Standard (AES)
Requires a Chaining Mode
Any chaining mode will need an IV
(Initialization Vector)
May be computed from context
or supplied with the data (e.g. as trailer)
57. mORMot 2 Encryption
• Advanced Encryption Standard (AES)
GCM = Galois/Counter Mode
AHEAD = Encrypt and Authenticate
128-bit digital signature with PCLMULQDQ HW acceleration
Parallelizable (96-bit CTR)
58. mORMot 2 Encryption
• Advanced Encryption Standard (AES)
mormot.crypt.core.pas
Direct low-level records – not to be used in practice
TAes record
= low-level AES/AES-NI ECB process
TAesGcmEngine record
= low-level AES/AES-NI GCM process
59. mORMot 2 Encryption
• Advanced Encryption Standard (AES)
mormot.crypt.core.pas
High-Level Classes
TAesAbstract parent class
with EncryptPkcs7/DecryptPkcs7() for cipher algos
MacEncrypt/MacAndCrypt() for AHEAD algos
TAesEcb TAesCbc TAesCfb TAesOfb
TAesCtr TAesGcm standard/NIST modes
TAesCfc TAesOfc TAesCtc 128-bit 4 x crc32c AHEAD
62. mORMot 2 Encryption
• Advanced Encryption Standard (AES)
mormot.crypt.core.pas
TAesAbstract inherited classes
var
/// the fastest AES implementation classes available on the system, per mode
// - mormot.crypt.openssl may register its own classes, e.g. TAesGcmOsl
TAesFast: array[TAesMode] of TAesAbstractClass = (
TAesEcb, TAesCbc, TAesCfb, TAesOfb, TAesC64, TAesCtr,
TAesCfc, TAesOfc, TAesCtc, TAesGcm);
myaes := TAesFast[mCtr]. CreateFromPbkdf2('pwd', 'salt', 1000);
64. mORMot 2 Encryption
2500 mormot aes-128-cfb in 4.59ms i.e. 531.7K/s or 1.1 GB/s
2500 mormot aes-128-ofb in 4.53ms i.e. 538.9K/s or 1.1 GB/s
2500 mormot aes-128-c64 in 6.19ms i.e. 393.8K/s or 858.2 MB/s
2500 mormot aes-128-ctr in 1.36ms i.e. 1.7M/s or 3.8 GB/s
2500 mormot aes-128-cfc in 4.75ms i.e. 513.1K/s or 1 GB/s
2500 mormot aes-128-ofc in 5.20ms i.e. 468.8K/s or 1 GB/s
2500 mormot aes-128-ctc in 1.67ms i.e. 1.4M/s or 3.1 GB/s
2500 mormot aes-128-gcm in 2.28ms i.e. 1M/s or 2.2 GB/s
2500 mormot aes-256-cfb in 6.15ms i.e. 396.8K/s or 864.8 MB/s
2500 mormot aes-256-ofb in 6.14ms i.e. 397.6K/s or 866.5 MB/s
2500 mormot aes-256-c64 in 7.80ms i.e. 312.6K/s or 681.3 MB/s
2500 mormot aes-256-ctr in 1.76ms i.e. 1.3M/s or 2.9 GB/s
2500 mormot aes-256-cfc in 6.36ms i.e. 383.7K/s or 836.3 MB/s
2500 mormot aes-256-ofc in 6.80ms i.e. 358.8K/s or 782 MB/s
2500 mormot aes-256-ctc in 2.10ms i.e. 1.1M/s or 2.4 GB/s
2500 mormot aes-256-gcm in 2.72ms i.e. 896.9K/s or 1.9 GB/s
2500 shake128 in 27.40ms i.e. 89.1K/s or 194.1 MB/s
2500 shake256 in 26.71ms i.e. 91.3K/s or 199.1 MB/s
65. mORMot 2 Encryption
2500 openssl aes-128-cfb in 6.99ms i.e. 348.8K/s or 760.1 MB/s
2500 openssl aes-128-ofb in 5.21ms i.e. 468.5K/s or 1 GB/s
2500 openssl aes-128-ctr in 1.51ms i.e. 1.5M/s or 3.4 GB/s
2500 openssl aes-128-gcm in 1.88ms i.e. 1.2M/s or 2.7 GB/s
2500 openssl aes-256-cfb in 8.73ms i.e. 279.6K/s or 609.4 MB/s
2500 openssl aes-256-ofb in 6.81ms i.e. 358.2K/s or 780.7 MB/s
2500 openssl aes-256-ctr in 1.91ms i.e. 1.2M/s or 2.7 GB/s
2500 openssl aes-256-gcm in 2.28ms i.e. 1M/s or 2.2 GB/s
71. mORMot 2 Asymmetric Crypto
• Private/Public Keys
Public Keys can be published and shared
as files or in a common PKI storage
Private Keys should be encrypted
with a strong password
never released
always stored in a safe place (even a real safe)
72. mORMot 2 Asymmetric Crypto
• Certificates and Public Key Infrastructure (PKI)
73. mORMot 2 Asymmetric Crypto
• Certificates and Public Key Infrastructure (PKI)
Public Keys can be signed in chain
Each public Key could be within a certificate
(about issuer, domain, expiration, parents…)
Certificate chains should be easily transmitted
(e.g. as base-64 encoded files)
74. mORMot 2 Asymmetric Crypto
• Certificates and Public Key Infrastructure (PKI)
mORMot features its own simple PKI
Focused on state-of-the-art ECC 256
Public certificates are stored in JSON files
Small in size, but complete and easy to work with
With a private/public key files management tool
You can use OpenSSL standard PKI instead
78. mORMot 2 Asymmetric Crypto
• RSA and ECC
RSA – Rivest-Shamir-Adleman
challenge based on integer computation
ECC – Elliptic Curve Cryptography
compute a reverse point on curve
79. mORMot 2 Asymmetric Crypto
• RSA and ECC (for 128-bit security level)
key bits gen sign verify shared
RSA 3072+ 12 1K 29K -
ECC 256 60K 38K 17K 13K
OpenSSL Numbers - in operations per second
› in practice (e.g. TLS) ECC is the way to go
80. mORMot 2 Asymmetric Crypto
• mormot.crypt.ecc.pas
mormot.crypt.ecc256r1.pas
mormot.crypt.openssl.pas
Ecc256r1MakeKey(out pub, out priv)
Ecc256r1Sign(priv, hash, out sign)
Ecc256r1Verify(pub, hash, sign)
Ecc256r1SharedSecret(pub, priv, out secret)
82. mORMot 2 Asymmetric Crypto
Some numbers on Intel Core i5 7300U
aes-ni pclmulqdq sse4.2 avx avx2
83. mORMot 2 Asymmetric Crypto
mORMot
300 Ecc256r1MakeKey in 76.59ms i.e. 3.8K/s, aver. 255us
300 Ecc256r1Sign in 79.21ms i.e. 3.7K/s, aver. 264us
300 Ecc256r1Verify in 95.70ms i.e. 3K/s, aver. 319us
598 Ecc256r1SharedSecret in 158.93ms i.e. 3.6K/s, aver. 265us
OpenSSL
300 Ecc256r1MakeKey in 5.09ms i.e. 57.5K/s, aver. 16us
300 Ecc256r1Sign in 7.97ms i.e. 36.7K/s, aver. 26us
300 Ecc256r1Verify in 28.66ms i.e. 10.2K/s, aver. 95us
598 Ecc256r1SharedSecret in 44.75ms i.e. 13K/s, aver. 74us
84. mORMot 2 Asymmetric Crypto
mORMot OpenSSL
MakeKey 3.8K/s 57.5K/s
Sign 3.7K/s 36.7K/s
Verify 3K/s 10.2K/s
SharedSecret 3.6K/s 13K/s
Linux X86_64 FPC
(note: mORMot 1.18 numbers were < 1K/s
with external .o/.obj compiled with gcc)
86. mORMot 2 Practical JWT
• JSON Web Token (JWT)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3O
DkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.S
flKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
(transmitted e.g. as HTTPS “Authenticate: Bearer” header)
87. mORMot 2 Practical JWT
• JSON Web Token (JWT)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3O
DkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.S
flKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
(transmitted e.g. as HTTPS “Authenticate: Bearer” header)
88. mORMot 2 Practical JWT
• JSON Web Token (JWT)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3O
DkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.S
flKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
{"alg": "HS256","typ": "JWT"} .{"sub":"1234567890","name":
"John Doe","iat":1516239022}.SflKxwRJSMeKKF2QT4fwpMeJf3
6POk6yJV_adQssw5c
The 3rd part is the HMAC-SHA256 of the header and payload.
91. mORMot 2 Practical JWT
• JSON Web Token (JWT)
mormot.crypt.jwt.pas
TJwtAbstract.Compute()
TJwtAbstract.Verify()
with payload processing as JSON/TDocVariant
and TJwtES256 for ‘ES256’ (native or OpenSSL) ECC signature
92. mORMot 2 Practical JWT
Some numbers on Intel Core i5 7300U
aes-ni pclmulqdq sse4.2 avx avx2
93. mORMot 2 Practical JWT
1000 HS256 in 1.37ms i.e. 710.2K/s, aver. 1.37us
1000 HS384 in 1.44ms i.e. 673.9K/s, aver. 1.44us
1000 HS512 in 1.43ms i.e. 679.1K/s, aver. 1.43us
1000 S3224 in 1.22ms i.e. 797.8K/s, aver. 1.22us
1000 S3256 in 1.23ms i.e. 793.3K/s, aver. 1.23us
1000 S3384 in 1.23ms i.e. 792K/s, aver. 1.23us
1000 S3512 in 1.25ms i.e. 776.2K/s, aver. 1.25us
1000 S3S128 in 1.40ms i.e. 693K/s, aver. 1.40us
1000 S3S256 in 1.32ms i.e. 739.2K/s, aver. 1.32us
100 ES256 in 6.95ms i.e. 14K/s, aver. 69us
mORMot engine
94. mORMot 2 Practical JWT
100 RS256 in 3.57ms i.e. 27.3K/s, aver. 35us
100 RS384 in 3.57ms i.e. 27.3K/s, aver. 35us
100 RS512 in 3.58ms i.e. 27.2K/s, aver. 35us
100 PS256 in 3.78ms i.e. 25.8K/s, aver. 37us
100 PS384 in 3.71ms i.e. 26.3K/s, aver. 37us
100 PS512 in 3.67ms i.e. 26.5K/s, aver. 36us
100 ES256 in 9.38ms i.e. 10.4K/s, aver. 93us
100 ES384 in 81.22ms i.e. 1.2K/s, aver. 812us
100 ES512 in 61.65ms i.e. 1.5K/s, aver. 616us
100 ES256K in 43.32ms i.e. 2.2K/s, aver. 433us
100 EdDSA in 11.80ms i.e. 8.2K/s, aver. 118us
OpenSSL engine