AES, Advanced Encryption Standard, is the “new” standard block cipher selected by the NIST among a few other competitors. It has been designed by Vincent Rijmen and Joan Daemen, and initially named Rijndael.
It works for different key sizes: 128, 192 or 256 bits and works over input/outputs of 16 bytes.
On an mathematical point of view, AES performs operations over GF(2^8) - which can be mapped to polynomials of degree 7 with binary coefficients. Some operations are particularly easy to perform, as noted by FIPS 197, such as multiplication by x (to be represented as (02)) which corresponds to a left shift and XOR 1b. Then, multiplication by (03) corresponds to a multiplication by 2 and an addition.
Basically, the algorithm consists in:
The decryption procedure is globally the “same”, but to undo the encryption the rounds must be different. In particular, the MixColumns transformation does not use the same invertible polynomial, and the Sbox of SubBytes is inverted too. This means the decryption must be implemented separetely.
Typical speed reported by LibTomCrypt is 5 cycles per bit, for a full C implementation (no assembly), on an x86 processor.
References:
DES (Data Encryption Standard) is a former block cipher standard. Because its security was at stake, it is gradually being replaced by AES. It was invented by IBM, with codename Lucifer, in 1976, and then selected in 1977 by the NIST. It uses 56 bit keys, and operates over 8 byte blocks.
The keys for DES usually also include 8 parity bits, which are included as the 8th, 16th… and 64th bit of the key. 8 bytes are consequently required to hold the key, although its strength is only that of 56-bit keys.
The algorithm consists in:
The decryption of a DES block follows exactly the same algorithm, but from down to top.
DES's implementation is quite tricky because it operates over bits and not bytes. To compute the key schedule, it is usually acceptable to work using one byte per bit because the key schedule is only computed once. But, for the core of the algorithm (the rounds), this is not possible, and there are several tricks to operate over 32-bit integers as much as possible (for 32-bit platforms !). The following tricks are commonly implemented:
Typical speed reported for DES is 23 cycles / bit for R. Outerbridge's implementation on x86.
DES's security is seriously compromised, mainly because 56-bit keys are too short to offer appropriate security using todays' machines. Currently, we know of:
Since all those results have been published, research on DES has somewhat been abandonned (DES can perhaps be broken even quicker now), the focus being shift on AES. However, some applications still use DES or Triple DES.
Triple DES can be seen as an attempt to secure DES: it performs three loops of DES. Several Triple DES modes exist and are detailed in FIPS 163-3. Mainly, the best known modes are EDE3 and EDE2. The first one performs an Encryption using the 56 first bits of the key, then a Decryption using the next 56 bits and finally and Encryption using the last 56-bits. So the Triple DES key can be seen as a 168-bit key or 3 56-bit DES keys. Obviously, it is important the first and the second key are not identical. For EDE2, only 112-bit keys are used: encryption with K1, decryption with K2 and encryption with K1(=K3).
Other modes exists such as EEE3, where the algorithm is applied 3 times in encryption mode.
References:
RSA is perhaps the most famous crypto algorithm. Contrary to DES or AES, it is not a block cipher but a public-key cipher. It was invented in 1977 by Rivest, Shamir and Adleman.
Its theory relies on modular exponentation and the difficulty to factorize large integers.
The algorithm consists in computing the exponentiation of a message, modulo a modulus.
The modulus is the multiplication of two large primes p and q (or more) and the exponent is chosen such that it is invertible modulo (p-1)(q-1).
So, the public key consists of:
The private key basically consists of:
Note that the modulus can also be computed as the multiplication of more than 2 primes (for example 4). In that case, all four primes must be known and kept secret.
Some algorithms use the Chinese Remainder Theorem (CRT) to compute faster modular exponentiation. Indeed, with CRT, it is possible to compute 2 modular exponentiation over half size primes instead of 1 modular exponentiation (which actually speeds up the process).
In that case, some other parameters are typically kept secret in the private key:
The most popular way to compute modular exponentiations use Montgomery's multiplications. Montgomery published in 1985 a way to compute modular exponentiation using only operations modulo powers of 2 - twice as more efficient. The theory is complex
and involves some pre-computing ®. Other optimizations exist (and can be combined) such as the binary method or sliding windows.
The generation of a key pair is a 'long' process because algorithms to output primes are lengthy.
A common way to generate a key pair is to generate a random number and divide it by the x first hard coded primes (and loop until it's okay) and/or to use better algorithms such as the Miller-Rabin primality test.
This only generates probable primes. Once p and q have been generated, all other factors are easily computed, including the private exponent. The public exponent is usually provided by the caller or fixed.
By definition, RSA will only work over integers small than the modulus (or the integer can be reduced). Consequently, the implementation must make sure prior to RSA computations that the input transforms to an appropriate integer. This is the task of RSA paddings.
PKCS#1 defines 4 paddings: two encryption schemes (RSAES-PKCS1.5 and RSAES-OAEP) and two signatures schemes with appendix (RSASSA-PKCS1.5 and RSASSA-PSS). PKCS#1 does not define signature schemes with message recovery.
The PKCS1.5 padding is the easiest to implement (but the least secure). For signatures, it consists in a leading 0×01 0×00, followed by a padding string of 0xff (at least 8), a 0×00 and the DER encoding of the Digest Information structure containing the digest algorithm and the digest of the message to sign.
For encryption, it is 0×00 0×02, followed by a padding string of random bytes, and finished by the message. The insertion of a random string ensures that the output of the encryption of two identical cleartexts produces different ciphertexts.
RSASSA-PSS was invented by Mihir Bellare and Phillip Rogaway and added to PKCS#1 in 1996.
It is possible to prove that, with PSS, the difficulty of forging signatures is directly related to the difficulty of inverting RSA.
Internally, the padding uses a hash function, a salt (random numbers) and a mask generation function (MGF - usually based on a hash)
RSAES-OAEP also is a late addition to PKCS#1, but its security isn't currently proved, although it is assumed it is better than PKCS1.5.
It starts with a leading 0×00 (which actually ensures the encoded message is smaller than the modulus), and uses
an optional label (a string), mask generation function and seed.
There are several RSA key formats. The so-called PKCS1 key format is for public keys:
RSAPublicKey ::= SEQUENCE { modulus INTEGER, -- n publicExponent INTEGER -- e }
X.509 also defines a public key format, used by several software such as OpenSSL:
SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, publicKey BIT STRING }
where, for RSA, the bit string actually corresponds to the encoding of PKCS#1 RSAPublicKey.
PKCS#8 also defines a key format for private keys (not restricted to RSA):
PrivateKeyInfo ::= SEQUENCE { version Version, privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, privateKey PrivateKey, attributes [0] IMPLICIT Attributes OPTIONAL
The OID for RSA is 1.2.840.113549.1.1.1.
References:
Diffie-Hellman is another public-key algorithm, commonly used to establish a secret between two different entities.
It has been invented by Diffie and Hellman (!) in 1976.
Its mathematical background relates to Galois Fields over prime numbers, i.e groups where a given prime (p) is used as a modulus over all operations.
Both parties share parameters which are:
Additionally, the private key is a secret integer (x). If a subprime is used, x is smaller than q. Otherwise smaller than p.
The public key is an integer y computed as y = g^x mod p.
There are two different standards for DH: X9.42 and PKCS#3. The former uses a subprime, whereas the latter does not. Also, standards specify different conditions on sizes for primes or other parameters.
DSA is very similar to DH except it is designed for signatures, whereas DH is for secret establishments.
X9.42 defines a very simple key format for DH:
DiffieHellmanPublicNumber ::= INTEGER
and domain parameters:
DomainParameters ::= SEQUENCE { p INTEGER, -- odd prime p= jq +1 g INTEGER, -- generator, g^q = 1 mod p q INTEGER, -- prime factor of p-1 j INTEGER, -- cofactor j>=2 validationParams ValidationParms OPTIONAL ValidationParms ::= SEQUENCE { seed BIT STRING -- seed for prime generation pGenCounter INTEGER -- parameter verification }
PKCS#3 defines another format for domain parameters:
DHParameter ::= SEQUENCE { prime INTEGER, -- p base INTEGER, -- g privateValueLength INTEGER OPTIONAL }
X.509 re-uses the SubjectPublicKeyInfo format but the BIT STRING of the public key is the integer Y
and the algorithm OID is 1.2.840.10046.2.1
Once a shared secret has been computed (Z), this shared secret must be derived into an appropriate key.
Several derivation algorithms exists although none seems either famous nor really standard: see in PKCS#3 or X9.42.
References
The core of DSA is the same as DH's, but the parametrization is different because DSA is used for signatures.
Actually, DSA is the NIST's standard for signatures.
DSA uses a subprime q.
The signature process is:
Note the signature consists of two parts, and the first part does not use the input.
Key formats for DSA are defined in RFC 2459:
DSAPublicKey ::= INTEGER -- public key, Y
and for OpenSSL:
DSAPrivateKey ::= SEQUENCE { version INTEGER, p INTEGER, q INTEGER, g INTEGER, y INTEGER, x INTEGER }
The signature format is defined in RFC 2459:
Dss-Parms ::= SEQUENCE { p INTEGER, q INTEGER, g Dss-Sig-Value ::= SEQUENCE { r INTEGER, s INTEGER }
References
==== ECDH ====
The ECDH algorithm translates to elliptic curves to finding a scalar
number k such that P=kG, where P is a known point of the curve, and G its generator or
base (a point too).
Elliptic curves are defined over GF(p) (finite fields of integers modulo p, whose characteristic is 1)
or over GF(2^m) (finite fields of m degree polynoms, where characterists is 2)
Over GF(p), an elliptic curve is y²=x^3 +ax+b mod p.
Over GF(2^m), it is y²+xy=x^3+ax²+b
When, for instance, a curve is defined over GF(p), this means that the coordinates x and y of a point of the curve are integers in GF(p).
Also, the order of a curve is the number of points of the curve + the point at infinity.
This is an important security parameter of the algorithm and it is typically big.
The order of a point is the smaller integer such that nP = infinity.
The public key is point Q : Q=d.G
The private key (d) is an integer between 1 and the order of the curve.
See P1363, X9.63, SEC1
I like this crypto library much, unfortunately, it looks like it won't be maintained any longer. You can download it here.