Skip to article frontmatterSkip to article content

Scope

A super-brief introduction to some other cryptographic techniques that you might encounter in the wild

Typically private/public key cryptography is strong but expensive, so we also need symmetric key cryptography for efficiency; a common pattern is to use strong cryptography to establish a shared secret, and then use symmetric key cryptography for the actual data exchange

in this part we’ll cover


Diffie-Hellman Key Exchange

a method for two parties to establish a shared secret over an insecure channel
typically used to agree on a symmetric key for further communication

based on simpler math:

  • choose a large prime pp and a base gg for everyone to see

  • then Alice and Bob choose their own private keys aa and bb

  • they both compute the same value:
    (ga)b=(gb)a=gabmodp(g^a)^b = (g^b)^a = g^{ab} \mod p

usage:

  • agree on a shared (symmetric) secret key,
    e.g. once the TLS handshake is done


symmetric key cryptography - AES

As mentioned above, public key cryptography is expensive, so we also need symmetric key cryptography for efficiency

With a symmetric key, as the name suggests, the same key is used by both ends (Alice and Bob) to encrypt and decrypt messages

In this respect the most common algorithm is AES (Advanced Encryption Standard)
See the gory details here in wikipedia


SHA - Secure Hash Algorithm(s)

Hash functions: why ?

Usages

for example: imagine: you want to spot all the duplicated files in a large directory tree - like, in all your computer
and the drive contains 1 million files; how would you go about doing that ?


a menagerie of hash functions

SHA1 and SHA2 were designed by the NSA and for that reason are often considered, ahem, suspicious... esp. after the Snowden revelations


SHA-2 (early 2000’s)

but the general idea is as follows:

I must say that implementing any of these algorithms in a low-level language could be a very good coding exercise, even if possibly tedious at times 😉


an example in Python code

In [1]: import hashlib

In [2]: # SHA-256 outputs 256 bits i.e. 64 hexa digits
   ...: hashlib.sha256(b"Pour tester la fonction de hachage SHA-256").hexdigest()
Out[2]: '99e7bfb9a23b5c8df17bc938120279585cf0de126aa84a7b7130ba2be67404ec'

In [3]: # regardless of the input size, be it small...
   ...: hashlib.sha256(b"tout petit").hexdigest()
Out[3]: '110af6c99fcf455de0db64a28c633d0b0e5341073c6ff3dfc73d9349703a595e'

In [4]: # or very large
   ...: hashlib.sha256(b"tres grand" * 1000).hexdigest()
Out[4]: '7a4b3b4472bc8edbba508efb0c458e7aa174b13ba5554004b801ce2d7780b7bb'

In [5]: # with almost the same input, we get .. something completely different
   ...: #                ↓ the only change is P becomes p
   ...: hashlib.sha256(b"pour tester la fonction de hachage SHA-256").hexdigest()
Out[5]: 'f02c78cd3b6a88379f5d0ace98539f3ceab86b59948248426de7ffdfe9777782'


In [6]: # SHA-1 yields shorter outputs, 160 bits only, i.e. 40 hexa digits
   ...: hashlib.sha1(b"Pour tester la fonction de hachage SHA-1").hexdigest()
Out[6]: '8d80362c01520158006bf2beef38d5ae08489570'