designates my notes. / designates important.
The first half of the book, the cryptography was interesting and why I read the book. The latter half, network protocols and such was old-hat for me. That said, I would strongly recommend this book to anyone interested in either cryptography or network security.
Ample, but not detailed, mathematical foundations are provided, allowing anyone without the prerequisite math skills to understand the entire book, provided you are willing to roll up your mental sleeves. The elliptical parts are quite difficult, but the rest is infinitely approachable by a novice.
It also covers the various forms ciphers can take, block, stream, etc. Random and pseudo random number generators are discussed. Public and private key systems are elaborated.
There are TONS of illustrations to help you visualize the algorithms and communication routines. There are also many examples, starting from the most basic shift ciphers all the way to DES, AES, and RSA. Hashing is also covered in great detail with the aforementioned illustrations and examples.
Enough detail is given that you can easily implement the algorithms in a programming language of your choosing. I built a number of python based toy examples for things like the euclidean algorithm, the Miller-Rabin prime test, and an RSA implementation among other things. I would strongly suggest anyone interested in learning cryptography to implement as many of the algorithms as you can, from scratch. The amount you learn doing this far exceeds what you would get simply trying to absorb the book.
It really is a well rounded book.
Here are links to the python programs I wrote, but be warned these are not debugged and more of proof of concepts to facilitate understanding. Do not use them for anything more than learning.
Read all of the classic papers cited in the Recommended Reading section for this chapter, available at the Author Web site at WilliamStallings.com/Cryptography. The papers are available at box.com/Crypto7e.
Dorothy Sayers’s Have His Carcase (fiction)
if a|1, then a = +-1
if a|b and b|a, then a = +-b
any b != 0 divides 0
if a|b and b|c, then a|c
If b|g and b|h, then b|(mg + nh) for arbitrary integers m and n.
To see this last point, note that
If b|g, then g is of the form g = b * g1 for some integer g1.
If b|h, then h is of the form h = b * h1 for some integer h1 .
So
mg + nh = mbg1 + nbh1 = b * (mg1 + nh1)
and therefore b divides mg + nh.
np.floor(-11/7)
np.remainder(-11, 7)
gcd(a, b) = max[k, such that k|a and k|b]
8 and 15 are relatively prime because the positive divisors of 8 are 1, 2, 4, and 8, and the positive divisors of 15 are 1, 3, 5, and 15. So 1 is the only integer on both lists.
import numpy as np
def gcd(a, b):
#q = np.floor(a/b)
r = np.remainder(a, b)
#print q, r
if r > 0:
return gcd(b, r)
else:
return b
def gcd_2(a, b):
if b == 0:
return a
else:
return gcd(b, np.remainder(a, b))
if __name__ == "__main__":
print gcd(1160718174, 316258250) #1078
print gcd_2(1160718174, 316258250) #1078
>>> np.mod == np.remainder
True
Define the set Z_n as the set of nonnegative integers less than n: Z n = {0, 1, …, (n - 1)}
def mgcd(a, b):
if b == 0:
return a
else:
return mgcd(b, np.mod(a, b))
if __name__ == "__main__":
print mgcd(1160718174, 316258250) #1078
All encryption algorithms are based on two general principles: substitution, in which each element in the plaintext (bit, letter, group of bits or letters) is mapped into another element, and transposition, in which elements in the plaintext are rearranged.
If both sender and receiver use the same key, the system is referred to as symmetric, single-key, secret-key, or conventional encryption. If the sender and receiver use different keys, the system is referred to as asymmetric, two-key, or public-key encryption.
With the exception of a scheme known as the one-time pad (described later in this chapter), there is no encryption algorithm that is unconditionally secure. Therefore, all that the users of an encryption algorithm can strive for is an algorithm that meets one or both of the following criteria:
An encryption scheme is said to be computationally secure if either of the foregoing two criteria are met.
random key that is as long as the message, so that the key need not be repeated. In addition, the key is to be used to encrypt and decrypt a single message, and then is discarded. [one-time pad]
a one-time pad, is unbreakable.
Funny, saying this literally on the next page after warning against such claims.
Block size: Larger block sizes mean greater security (all other things being equal) but reduced encryption/decryption speed for a given algorithm. The greater security is achieved by greater diffusion. Traditionally, a block size of 64 bits has been considered a reasonable tradeoff and was nearly universal in block cipher design. However, the new AES uses a 128-bit block size.
Key size: Larger key size means greater security but may decrease encryption/ decryption speed. The greater security is achieved by greater resistance to brute-force attacks and greater confusion. Key sizes of 64 bits or less are now widely considered to be inadequate, and 128 bits has become a common size.
Number of rounds: The essence of the Feistel cipher is that a single round offers inadequate security but that multiple rounds offer increasing security. A typical size is 16 rounds.
Subkey generation algorithm: Greater complexity in this algorithm should lead to greater difficulty of cryptanalysis.
Round function F: Again, greater complexity generally means greater resistance to cryptanalysis.
(A1) Closure: If a and b belong to G, then a # b is also in G.
(A2) Associative: a # (b # c) = (a # b) # c for all a, b, c in G.
(A3) Identity element: There is an element e in G such that a # e = e # a = a
for all a in G.
(A4) Inverse element: For each a in G, there is an element a′ in G such that a
# a′ = a′ # a = e.
In essence, a ring is a set of elements in which we can do addition, subtraction [a - b = a + ( -b)], and multiplication without leaving the set.
With respect to addition and multiplication, the set of all n-square matrices over the real numbers is a ring.
1 + 1 = 1 - 1 = 0
1 + 0 = 1 - 0 = 1
0 + 1 = 0 - 1 = 1
an encryption round has the structure SubBytes, ShiftRows, MixColumns, AddRoundKey. The standard decryption round has the structure InvShiftRows, InvSubBytes, AddRoundKey, InvMixColumns. Thus, the first two stages of the decryption round need to be interchanged, and the second two stages of the decryption round need to be interchanged.
InvShiftRows[InvSubBytes(Si)] = InvSubBytes[InvShiftRows(S_i)]
InvMixColumns(Si ^ w_j) = [InvMixColumns(S_i)] ^ [InvMixColumns(wj)]
In conclusion, because of the chaining mechanism of CBC (cipher block chaining), it is an appropriate mode for encrypting messages of length greater than b bits.
In addition to its use to achieve confidentiality, the CBC mode can be used for authentication. This use is described in Chapter 12.
For AES, DES, or any block cipher, encryption is performed on a block of b bits. In the case of DES, b = 64 and in the case of AES, b = 128. However, it is possible to convert a block cipher into a stream cipher, using one of the three modes to be discussed in this and the next two sections: cipher feedback (CFB) mode, output feedback (OFB) mode, and counter (CTR) mode. A stream cipher eliminates the need to pad a message to be an integral number of blocks. It also can operate in real time.
One advantage of the OFB (output feedback) method is that bit errors in transmission do not propagate. For example, if a bit error occurs in C1, only the recovered value of P1 is affected
The disadvantage of OFB is that it is more vulnerable to a message stream modification attack than is CFB. Consider that complementing a bit in the ciphertext complements the corresponding bit in the recovered plaintext. Thus, controlled changes to the recovered plaintext can be made. This may make it possible for an opponent, by making the necessary changes to the checksum portion of the message as well as to the data portion, to alter the ciphertext in such a way that it is not detected by an error-correcting code.
One distinction from the stream ciphers we discuss in Chapter 8 is that OFB encrypts plaintext a full block at a time, where typically a block is 64 or 128 bits. Many stream ciphers encrypt one byte at a time.
Preprocessing: The execution of the underlying encryption algorithm does not depend on input of the plaintext or ciphertext. Therefore, if sufficient memory is available and security is maintained, preprocessing can be used to prepare the output of the encryption boxes that feed into the XOR functions, as in Figure 7.7. When the plaintext or ciphertext input is presented, then the only computation is a series of XORs. Such a strategy greatly enhances throughput.
Provable security: It can be shown that CTR is at least as secure as the other modes discussed in this chapter.
Format-preserving encryption (FPE) refers to any encryption technique that takes a plaintext in a given format and produces a ciphertext in the same format. For example, credit cards consist of 16 decimal digits.
FPE facilitates the retrofitting of encryption technology to legacy applications, where a conventional encryption mode might not be feasible because it would disrupt data fields/pathways.
m the modulus m > 0
a the multiplier 0 < a < m
c the increment 0 <= c < m
X_0 the starting value, or seed 0 <= X_0 < m
X_n + 1 = (aX_n) mod (2^31 - 1)
Z = E(PU_b, E(PR_a,X))
X = D(PU_a, D(PR_b,Z))
Another form of attack is to find some way to compute the private key given the public key. To date, it has not been mathematically proven that this form of attack is infeasible for a particular public-key algorithm. Thus, any given algorithm, including the widely used RSA algorithm, is suspect. The history of cryptanalysis shows that a problem that seems insoluble from one perspective can be found to have a solution if looked at in an entirely different way.
Finally, there is a form of attack that is peculiar to public-key systems. This is, in essence, a probable-message attack. Suppose, for example, that a message were to be sent that consisted solely of a 56-bit DES key. An adversary could encrypt all possible 56-bit DES keys using the public key and could discover the encrypted key by matching the transmitted ciphertext. Thus, no matter how large the key size of the public-key scheme, the attack is reduced to a brute-force attack on a 56-bit key. This attack can be thwarted by appending some random bits to such simple messages.
p, q, two prime numbers (private, chosen)
n = pq (public, calculated)
e, with gcd(f(n), e) = 1; 1 6 e 6 f(n) (public, chosen)
d K e -1 (mod f(n)) (private, calculated)
1. Select two prime numbers, p = 17 and q = 11.
2. Calculate n = pq = 17 * 11 = 187.
3. Calculate f(n) = (p - 1)(q - 1) = 16 * 10 = 160.
4. Select e such that e is relatively prime to f(n) = 160 and less than f(n);
we choose e = 7.
5. Determine d such that de K 1 (mod 160) and d 6 160. The correct value is
d = 23, because 23 * 7 = 161 = (1 * 160) + 1; d can be calculated using
the extended Euclid’s algorithm (Chapter 2).
The resulting keys are public key PU = {7, 187} and private key PR = {23, 187}.
The example shows the use of these keys for a plaintext input of M = 88. For encryption, we need to calculate C = 887 mod 187. Exploiting the properties of modular arithmetic, we can do this as follows.
88^7 mod 187 = [(88^4 mod 187) * (88^2 mod 187) * (88^1 mod 187)] mod 187
88^1 mod 187 = 88
88^2 mod 187 = 7744 mod 187 = 77
88^4 mod 187 = 59,969,536 mod 187 = 132
88^7 mod 187 = (88 * 77 * 132) mod 187 = 894,432 mod 187 = 11
11^23 mod 187 = [(11^1 mod 187) * (11^2 mod 187) * (11^4 mod 187)
* (11^8 mod 187) * (11^8 mod 187)] mod 187
11^1 mod 187 = 11
11^2 mod 187 = 121
11^4 mod 187 = 14,641 mod 187 = 55
11^8 mod 187 = 214,358,881 mod 187 = 33
11^23 mod 187 = (11 * 121 * 55 * 33 * 33) mod 187 = 79,720,245 mod 187 = 88
y^2 + axy + by = x^3 + cx^2 + dx + e
P = O.
With the preceding list of rules, it can be shown that the set E(a, b) is an abelian group.
(a) a data object that maps to a pre-specified hash result (the one-way property) or (b) two data objects that map to the same hash result (the collision-free property).
Typically, the input is padded out to an integer multiple of some fixed length (e.g., 1024 bits), and the padding includes the value of the length of the original mes- sage in bits.
Typically, it is preferable to tie the authentication directly to the plaintext, so the method of Figure 12.4b is used.
Finally, note that the MAC does not provide a digital signature, because both sender and receiver share the same key.
1. Mary may forge a different message and claim that it came from John. Mary
would simply have to create a message and append an authentication code using
the key that John and Mary share.
2. John can deny sending the message. Because it is possible for Mary to forge
a message, there is no way to prove that John did in fact send the message.
1. A generates a public/private key pair {PUa, PR a} and transmits a message to
B consisting of PUa and an identifier of A, ID A.
2. B generates a secret key, K s, and transmits it to A, which is encrypted
with A’s public key.
3. A computes D(PR a, E(PUa, K s)) to recover the secret key. Because only A
can decrypt the message, only A and B will know the identity of K s.
4. A discards PUa and PR a and B discards PUa. A and B can now securely
communicate using conventional encryption and the session key Ks. At the
completion of the exchange, both A and B discard K s. Despite its simplicity,
this is an attractive protocol.
1. A -> B: ID_A || N_a
2. B -> KDC: ID_B || N_b || E(K_b, [ID_A || N_a || T_b])
3. KDC -> A: E(K_a, [ID_B || N_a || K_s || T_b]) || E(K_b, [ID_A || K_s || T_b]) || N_b
4. A -> B: E(K_b, [ID_A || K_s || T_b]) || E(K_s, N_b)
|| = concatenate
KDC = Key Distribution Center
N = Nonce
K = Key
T = Timestamp
ID = Identifier
Whereas X.509 certificates are trusted if there is a valid PKIX chain to a trusted root, an OpenPGP public key is trusted if it is signed by another OpenPGP public key that is trusted by the recipient. This is called the Web-of-Trust.
OpenPGP does not include the sender’s public key with each message, so it is necessary for recipients of OpenPGP messages to sepa- rately obtain the sender’s public key in order to verify the message.
DANE is a protocol to allow X.509 certificates, commonly used for Transport Layer Security (TLS), to be bound to DNS names using DNSSEC. It is proposed in RFC 6698 as a way to authenticate TLS client and server entities without a certificate authority (CA).
The rationale for DANE is the vulnerability of the use of CAs in a global PKI system. Every browser developer and operating system supplier maintains a list of CA root certificates as trust anchors. These are called the software’s root certifi- cates and are stored in its root certificate store. The PKIX procedure allows a cer- tificate recipient to trace a certificate back to the root. So long as the root certificate remains trustworthy, and the authentication concludes successfully, the client can proceed with the connection.
However, if any of the hundreds of CAs operating on the Internet is compro- mised, the effects can be widespread. The attacker can obtain the CA’s private key, get issued certificates under a false name, or introduce new bogus root certificates into a root certificate store. There is no limitation of scope for the global PKI and a compromise of a single CA damages the integrity of the entire PKI system. In addition, some CAs have engaged in poor security practices.