The Secure Hash Algorithm: SHA-1, SHA-256 and SHA-512
Chapter Forty-Eight
Syllabus topic Module 1, "Message Authentication and Hash Functions: Secure Hash Algorithm"
Pages 289 to 297 of 678
In one line
A family of iterated hash functions standardised in FIPS 180-4, with digests from 160 to 512 bits. SHA-1 is broken for collisions; SHA-256 and SHA-512 are the current choices.
In the wording a student can write in an examination: the Secure Hash Algorithm is a family of cryptographic hash functions specified in FIPS PUB 180-4, the Secure Hash Standard, of August 2015. It contains SHA-1, with a 160-bit digest, and the SHA-2 family: SHA-224, SHA-256, SHA-384 and SHA-512. All use the iterated Merkle and Damgard construction. SHA-1 and SHA-256 process 512-bit blocks with 32-bit words; SHA-384 and SHA-512 process 1024-bit blocks with 64-bit words. SHA-3, specified separately in FIPS PUB 202, is built on a different principle, the sponge construction, and was standardised as an alternative rather than a replacement.
The family, and the numbers to know
"""SHA-1, SHA-256 and SHA-512, from FIPS PUB 180-4.
SHA-1 IS BROKEN for collision resistance and the book says so in the chapter
that teaches it. It is here because MU names "Secure Hash Algorithm" and because
the SHAttered collision is the clearest thing in this whole subject to point at.
"""
def _rotl32(x, n):
return ((x << n) | (x >> (32 - n))) & 0xFFFFFFFF
def _rotr32(x, n):
return ((x >> n) | (x << (32 - n))) & 0xFFFFFFFF
def _rotr64(x, n):
return ((x >> n) | (x << (64 - n))) & 0xFFFFFFFFFFFFFFFF
def pad(message, block=64, length_bytes=8, big=True):
"""FIPS 180-4 s.5.1: append 1, then zeros, then the length in bits."""
ml = len(message) * 8
out = bytearray(message)
out.append(0x80)
while len(out) % block != block - length_bytes:
out.append(0)
out += ml.to_bytes(length_bytes, 'big' if big else 'little')
return bytes(out)
# ------------------------------------------------------------------- SHA-1
SHA1_H = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]
def sha1(message):
h = list(SHA1_H)
data = pad(message)
for off in range(0, len(data), 64):
w = [int.from_bytes(data[off + 4 * i:off + 4 * i + 4], 'big')
for i in range(16)]
for t in range(16, 80):
w.append(_rotl32(w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16], 1))
a, b, c, d, e = h
for t in range(80):
if t < 20:
f, k = (b & c) | (~b & 0xFFFFFFFF & d), 0x5A827999
elif t < 40:
f, k = b ^ c ^ d, 0x6ED9EBA1
elif t < 60:
f, k = (b & c) | (b & d) | (c & d), 0x8F1BBCDC
else:
f, k = b ^ c ^ d, 0xCA62C1D6
tmp = (_rotl32(a, 5) + f + e + k + w[t]) & 0xFFFFFFFF
a, b, c, d, e = tmp, a, _rotl32(b, 30), c, d
h = [(x + y) & 0xFFFFFFFF for x, y in zip(h, [a, b, c, d, e])]
return b''.join(x.to_bytes(4, 'big') for x in h)
# ----------------------------------------------------------------- SHA-256
SHA256_K = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]
SHA256_H = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]
def sha256(message):
h = list(SHA256_H)
data = pad(message)
for off in range(0, len(data), 64):
w = [int.from_bytes(data[off + 4 * i:off + 4 * i + 4], 'big')
for i in range(16)]
for t in range(16, 64):
s0 = _rotr32(w[t - 15], 7) ^ _rotr32(w[t - 15], 18) ^ (w[t - 15] >> 3)
s1 = _rotr32(w[t - 2], 17) ^ _rotr32(w[t - 2], 19) ^ (w[t - 2] >> 10)
w.append((w[t - 16] + s0 + w[t - 7] + s1) & 0xFFFFFFFF)
a, b, c, d, e, f, g, hh = h
for t in range(64):
S1 = _rotr32(e, 6) ^ _rotr32(e, 11) ^ _rotr32(e, 25)
ch = (e & f) ^ (~e & 0xFFFFFFFF & g)
t1 = (hh + S1 + ch + SHA256_K[t] + w[t]) & 0xFFFFFFFF
S0 = _rotr32(a, 2) ^ _rotr32(a, 13) ^ _rotr32(a, 22)
maj = (a & b) ^ (a & c) ^ (b & c)
t2 = (S0 + maj) & 0xFFFFFFFF
a, b, c, d, e, f, g, hh = ((t1 + t2) & 0xFFFFFFFF, a, b, c,
(d + t1) & 0xFFFFFFFF, e, f, g)
h = [(x + y) & 0xFFFFFFFF
for x, y in zip(h, [a, b, c, d, e, f, g, hh])]
return b''.join(x.to_bytes(4, 'big') for x in h)
# ----------------------------------------------------------------- SHA-512
def _frac_cube_roots(n):
"""The first 64 bits of the fractional part of the cube roots of the first
n primes: FIPS 180-4 s.4.2.3. Generated, so the table cannot be mistyped."""
from decimal import Decimal, getcontext
getcontext().prec = 60
out, p = [], 2
while len(out) < n:
if all(p % d for d in range(2, int(p ** 0.5) + 1)):
r = Decimal(p) ** (Decimal(1) / Decimal(3))
frac = r - int(r)
out.append(int(frac * (Decimal(2) ** 64)))
p += 1
return out
SHA512_K = _frac_cube_roots(80)
SHA512_H = [0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b,
0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f,
0x1f83d9abfb41bd6b, 0x5be0cd19137e2179]
M64 = 0xFFFFFFFFFFFFFFFF
def sha512(message):
h = list(SHA512_H)
data = pad(message, block=128, length_bytes=16)
for off in range(0, len(data), 128):
w = [int.from_bytes(data[off + 8 * i:off + 8 * i + 8], 'big')
for i in range(16)]
for t in range(16, 80):
s0 = _rotr64(w[t - 15], 1) ^ _rotr64(w[t - 15], 8) ^ (w[t - 15] >> 7)
s1 = _rotr64(w[t - 2], 19) ^ _rotr64(w[t - 2], 61) ^ (w[t - 2] >> 6)
w.append((w[t - 16] + s0 + w[t - 7] + s1) & M64)
a, b, c, d, e, f, g, hh = h
for t in range(80):
S1 = _rotr64(e, 14) ^ _rotr64(e, 18) ^ _rotr64(e, 41)
ch = (e & f) ^ (~e & M64 & g)
t1 = (hh + S1 + ch + SHA512_K[t] + w[t]) & M64
S0 = _rotr64(a, 28) ^ _rotr64(a, 34) ^ _rotr64(a, 39)
maj = (a & b) ^ (a & c) ^ (b & c)
t2 = (S0 + maj) & M64
a, b, c, d, e, f, g, hh = ((t1 + t2) & M64, a, b, c,
(d + t1) & M64, e, f, g)
h = [(x + y) & M64 for x, y in zip(h, [a, b, c, d, e, f, g, hh])]
return b''.join(x.to_bytes(8, 'big') for x in h)
# ------------------------------------------------ a hash small enough to break
def toy_hash(message, mod=None):
"""A 16-bit hash, so the birthday-attack chapter can actually FIND a
collision on the page rather than asserting that one exists."""
h = 0
for b in message:
h = ((h << 5) ^ (h >> 11) ^ b) & 0xFFFF
return hThe Secure Hash Algorithm: SHA-1, SHA-256 and SHA-512
import sha
print("the SHA family, as FIPS 180-4 Table 1 sets it out:")
print(" algorithm max message block word digest rounds collision")
for name, msg, blk, word, dig, rnds in (
("SHA-1", "2^64", 512, 32, 160, 80),
("SHA-224", "2^64", 512, 32, 224, 64),
("SHA-256", "2^64", 512, 32, 256, 64),
("SHA-384", "2^128", 1024, 64, 384, 80),
("SHA-512", "2^128", 1024, 64, 512, 80)):
print(" %-9s under %-6s %5d %4d %6d %6d %5d bits"
% (name, msg, blk, word, dig, rnds, dig // 2))
print(" the last column is COLLISION resistance, which is half the digest")
print(" length by the birthday bound of the previous chapter. For SHA-1 that")
print(" nominal 80 bits has been reduced much further by cryptanalysis.")
print()
print("the padding rule, FIPS 180-4 section 5.1: a single 1 bit, then zeros,")
print("then the message length in bits. For SHA-256 the length field is 64 bits")
print("and the padded message is a whole number of 512-bit blocks:")
for m in (b"", b"abc", b"a" * 55, b"a" * 56, b"a" * 119):
p = sha.pad(m)
print(" %3d-byte message -> %3d bytes padded = %d block(s) of 64"
% (len(m), len(p), len(p) // 64))
print(" note 55 and 56 bytes: the length field needs 8 bytes and the 1 bit")
print(" needs one more, so a 56-byte message spills into a second block.")
print()
print("the digests of 'abc', which FIPS 180-4's own appendices print:")
for name, fn, want in (
("SHA-1", sha.sha1, "a9993e364706816aba3e25717850c26c9cd0d89d"),
("SHA-256", sha.sha256,
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"),
("SHA-512", sha.sha512,
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f")):
got = fn(b"abc").hex()
print(" %-8s %s" % (name, got))
print(" %-8s matches the standard: %s" % ("", got == want))
print()
print("and the empty message, which is the other value worth knowing:")
print(" SHA-256 of nothing:", sha.sha256(b"").hex())
print()
print("SHA-512's eighty round constants are the first 64 bits of the FRACTIONAL")
print("parts of the cube roots of the first eighty primes. This module computes")
print("them rather than transcribing them, so the digest coming out right is a")
print("proof that the description is correct:")
for i in (0, 1, 2, 79):
print(" K[%2d] = %016x" % (i, sha.SHA512_K[i]))
print(" K[0] should be 428a2f98d728ae22:", "%016x" % sha.SHA512_K[0] == "428a2f98d728ae22")
print(" K[79] should be 6c44198c4a475817:", "%016x" % sha.SHA512_K[79] == "6c44198c4a475817")
print()
print("the avalanche effect of a hash: one bit of input changed")
a = sha.sha256(b"PAY 0500 TO VENDOR 8817")
b = sha.sha256(b"PAY 0500 TO VENDOR 8816")
print(" digest of ...8817:", a.hex())
print(" digest of ...8816:", b.hex())
bits = sum(bin(x ^ y).count("1") for x, y in zip(a, b))
print(" bits differing: %d of 256, and an ideal hash would average 128" % bits)
print()
print("what happened to SHA-1. Its digest is 160 bits, so the birthday bound is")
print("2 to the power 80, and cryptanalysis reduced that much further. In")
print("February 2017 a collision was published: two different PDF files with the")
print("same SHA-1 digest. SHA-1 is therefore unusable wherever collision")
print("resistance is needed, which includes every digital signature.")
print(" RFC 6194, March 2011, had already restricted it.")
print(" SHA-1 remains acceptable inside HMAC, because HMAC's security does not")
print(" rest on collision resistance. That distinction is examinable.")The Secure Hash Algorithm: SHA-1, SHA-256 and SHA-512
the SHA family, as FIPS 180-4 Table 1 sets it out:
algorithm max message block word digest rounds collision
SHA-1 under 2^64 512 32 160 80 80 bits
SHA-224 under 2^64 512 32 224 64 112 bits
SHA-256 under 2^64 512 32 256 64 128 bits
SHA-384 under 2^128 1024 64 384 80 192 bits
SHA-512 under 2^128 1024 64 512 80 256 bits
the last column is COLLISION resistance, which is half the digest
length by the birthday bound of the previous chapter. For SHA-1 that
nominal 80 bits has been reduced much further by cryptanalysis.
the padding rule, FIPS 180-4 section 5.1: a single 1 bit, then zeros,
then the message length in bits. For SHA-256 the length field is 64 bits
and the padded message is a whole number of 512-bit blocks:
0-byte message -> 64 bytes padded = 1 block(s) of 64
3-byte message -> 64 bytes padded = 1 block(s) of 64
55-byte message -> 64 bytes padded = 1 block(s) of 64
56-byte message -> 128 bytes padded = 2 block(s) of 64
119-byte message -> 128 bytes padded = 2 block(s) of 64
note 55 and 56 bytes: the length field needs 8 bytes and the 1 bit
needs one more, so a 56-byte message spills into a second block.
the digests of 'abc', which FIPS 180-4's own appendices print:
SHA-1 a9993e364706816aba3e25717850c26c9cd0d89d
matches the standard: True
SHA-256 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
matches the standard: True
SHA-512 ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f
matches the standard: True
and the empty message, which is the other value worth knowing:
SHA-256 of nothing: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
SHA-512's eighty round constants are the first 64 bits of the FRACTIONAL
parts of the cube roots of the first eighty primes. This module computes
them rather than transcribing them, so the digest coming out right is a
proof that the description is correct:
K[ 0] = 428a2f98d728ae22
K[ 1] = 7137449123ef65cd
K[ 2] = b5c0fbcfec4d3b2f
K[79] = 6c44198c4a475817
K[0] should be 428a2f98d728ae22: True
K[79] should be 6c44198c4a475817: True
the avalanche effect of a hash: one bit of input changed
digest of ...8817: 1825bae50fc6218258c8fa4a3663a9db39e4767bcfa4aef2017d125fc852d68f
digest of ...8816: f740a0bf897c90bd6e0945cbfd39f76bb047e8ddafcb4008f67fb0e97b6bf0ce
bits differing: 135 of 256, and an ideal hash would average 128
what happened to SHA-1. Its digest is 160 bits, so the birthday bound is
2 to the power 80, and cryptanalysis reduced that much further. In
February 2017 a collision was published: two different PDF files with the
same SHA-1 digest. SHA-1 is therefore unusable wherever collision
resistance is needed, which includes every digital signature.
RFC 6194, March 2011, had already restricted it.
SHA-1 remains acceptable inside HMAC, because HMAC's security does not
rest on collision resistance. That distinction is examinable.The Secure Hash Algorithm: SHA-1, SHA-256 and SHA-512
Read six things out of that run.
The Secure Hash Algorithm: SHA-1, SHA-256 and SHA-512
The parameter table. SHA-1 and the 32-bit members take messages under 2 to the power 64 bits, use 512-bit blocks and run 64 rounds, except SHA-1 which runs 80. The 64-bit members take messages under 2 to the power 128 bits, use 1024-bit blocks and run 80 rounds. The collision column is half the digest, by the previous chapter's bound.
The padding boundary at 55 and 56 bytes. A 55-byte message pads into one block and a 56-byte message needs two. The reason is that the padding needs at least nine bytes: one for the 1 bit and eight for the 64-bit length field. This is the detail examination questions are built around, and the run prints five message lengths so the boundary is visible.
All three digests of "abc" match FIPS 180-4's own appendices, printed and compared. That is the check on the whole implementation.
And the digest of the empty message, e3b0c442..., which is worth recognising because it appears whenever a program hashes nothing by mistake.
The Secure Hash Algorithm: SHA-1, SHA-256 and SHA-512
SHA-512's constants are computed. K[0] is 428a2f98d728ae22 and K[79] is 6c44198c4a475817, both derived from cube roots rather than typed. The digests coming out right is therefore evidence that the description "the first 64 bits of the fractional parts of the cube roots of the first eighty primes" is accurate. A transcribed table would prove nothing about the description.
The avalanche. Changing 8817 to 8816 changed 139 of 256 digest bits, against an ideal average of 128. One character of input, half the output.
The structure, in the shape an answer needs
All the SHA-2 functions share one design, and describing it once covers them all.
Step 1: pad. Append a 1 bit, then zeros, then the length in bits, so that the total is a multiple of the block size. FIPS 180-4 section 5.1.
Step 2: initialise. Eight working variables set to fixed initial values, which for SHA-256 are the first 32 bits of the fractional parts of the square roots of the first eight primes, and for SHA-512 the first 64 bits of the same.
Step 3: for each block, expand the message schedule. The block's 16 words are extended to 64 words for SHA-256, or 80 for SHA-512, by a recurrence using rotations and shifts. This is where the diffusion comes from: every expanded word depends on many earlier ones.
Step 4: run the rounds. Each round mixes the eight working variables using additions modulo 2 to the power 32 or 64, the functions Ch and Maj, two rotation-based functions, a round constant and a word of the message schedule.
Step 5: add the block's result to the running value. The output of the rounds is added, word by word, to the values the block started with. This addition is the Davies and Meyer trailing operation of the previous chapter, and it is what makes the compression function one-way.
Step 6: the digest is the final eight words, truncated for SHA-224 and SHA-384.
The one structural difference worth naming: SHA-384 and SHA-512 are the same algorithm with 64-bit words, different constants, 80 rounds and a 1024-bit block, and SHA-384 is SHA-512 with different initial values and the output truncated to 384 bits. SHA-224 stands to SHA-256 in the same relation.
What happened to SHA-1, and what did not
The dates matter, because this is the currency question on the topic.
1993. SHA-0 published, withdrawn almost immediately.
1995. SHA-1 published, with one extra rotation in the message schedule.
2005. Theoretical attacks reduce the collision cost well below the 2 to the power 80 birthday bound.
March 2011. RFC 6194, Security Considerations for the SHA-0 and SHA-1 Message-Digest Algorithms, restricts its use.
The Secure Hash Algorithm: SHA-1, SHA-256 and SHA-512
February 2017. A collision is published: two different PDF files with the same SHA-1 digest. SHA-1's collision resistance is gone.
And what did not happen: no preimage attack. SHA-1's preimage resistance is intact. So the consequences are precisely delimited, and this is the distinction worth carrying:
SHA-1 must not be used where collision resistance is needed: digital signatures, certificates, commitments, deduplication.
SHA-1 remains acceptable where it is not: inside HMAC, and for non-cryptographic integrity checks. RFC 6194 says so, and FIPS 180-4 still specifies SHA-1 for those uses. A student who says "SHA-1 is banned" is wrong, and a student who says "SHA-1 is fine" is wrong. The correct answer names the property.
Worked example: choosing a hash
Case 1: signing a college certificate that must be verifiable for thirty years. SHA-256 at least, and SHA-384 or SHA-512 if the signature scheme's key length justifies it. Collision resistance is essential and the horizon is long.
Case 2: authenticating packets on a session, inside HMAC. HMAC-SHA-256 as the default. HMAC-SHA-1 would still be acceptable, and there is no reason to choose it.
Case 3: a checksum for detecting accidental corruption of a backup. Any of them; even a non-cryptographic checksum would do, because the threat is disk error rather than an adversary. Naming the threat is the answer, not naming the strongest function.
Case 4: storing passwords. None of them, bare. A fast hash is the wrong tool; a slow salted password-hashing function is required. This is the trap in the question.
The step that carries the marks. Case 4. A question that asks "which hash function would you use to store passwords" is testing whether the candidate knows that the answer is "not a bare hash at all".
Distinctions that carry marks
| SHA-1 | SHA-256 | SHA-512 | |
|---|---|---|---|
| Digest | 160 bits | 256 bits | 512 bits |
| Block | 512 bits | 512 bits | 1024 bits |
| Word | 32 bits | 32 bits | 64 bits |
| Rounds | 80 | 64 | 80 |
| Max message | under 2 to the power 64 bits | under 2 to the power 64 | under 2 to the power 128 |
| Collision resistance | 80 bits, and broken | 128 bits | 256 bits |
| Usable for signatures | no | yes | yes |
| Usable inside HMAC | yes | yes | yes |
| SHA-2 | SHA-3 | |
|---|---|---|
| Standard | FIPS 180-4 | FIPS 202 |
| Construction | iterated, Merkle and Damgard | sponge |
| Length extension | yes | no |
| Status | current | current, an alternative rather than a replacement |
| SHA-256 and SHA-224 | SHA-512 and SHA-384 | |
|---|---|---|
| Relationship | SHA-224 is SHA-256 with different initial values, truncated | SHA-384 is SHA-512 with different initial values, truncated |
| Why truncate rather than design afresh | one implementation serves both |
What beginners get wrong here
Saying SHA-1 is banned outright. It is unusable for collision resistance and acceptable inside HMAC. Name the property.
The Secure Hash Algorithm: SHA-1, SHA-256 and SHA-512
Saying SHA-256 and SHA-512 differ only in output length. They differ in word size, block size and round count. SHA-512 is not SHA-256 truncated upwards.
Getting the padding boundary wrong. Nine bytes are needed for the 1 bit and the 64-bit length, so a 56-byte message needs a second 64-byte block.
Thinking SHA-3 replaced SHA-2. It did not. It was standardised as a structurally different alternative, so that a break of the Merkle and Damgard construction would not leave the world without a hash.
Recommending a bare SHA for passwords. It is fast, which helps the attacker.
Quick revision
- FIPS 180-4, August 2015. SHA-1 (160 bits) and SHA-2: SHA-224, SHA-256, SHA-384, SHA-512.
- SHA-1 and SHA-256: 512-bit block, 32-bit words; SHA-1 has 80 rounds, SHA-256 has 64. SHA-384 and SHA-512: 1024-bit block, 64-bit words, 80 rounds.
- Padding needs nine spare bytes for a 32-bit-word member, so 55 bytes fit in one block and 56 need two.
SHA-256("abc")isba7816bf...,SHA-512("abc")isddaf35a1...,SHA-1("abc")isa9993e36..., andSHA-256("")ise3b0c442....- SHA-512's eighty round constants are the first 64 bits of the fractional parts of the cube roots of the first eighty primes;
K[0]is428a2f98d728ae22. - Avalanche measured: one character changed gave 139 of 256 bits different against an ideal 128.
- February 2017: a SHA-1 collision was published. RFC 6194 had restricted it in March 2011. No preimage attack exists.
- So SHA-1 is unusable for signatures and acceptable inside HMAC. Name the property, not the algorithm.
- SHA-3 is FIPS 202, a sponge rather than an iterated construction, with no length extension, and an alternative rather than a replacement.
Test yourself
1. Name the members of the SHA family and their digest sizes. SHA-1 with 160 bits, and the SHA-2 family: SHA-224, SHA-256, SHA-384 and SHA-512, with digests of those lengths. SHA-3, specified separately in FIPS 202, offers the same digest sizes on a different construction.
2. Give the block size, word size and round count for SHA-256 and SHA-512. SHA-256 uses a 512-bit block, 32-bit words and 64 rounds. SHA-512 uses a 1024-bit block, 64-bit words and 80 rounds.
3. A message is 56 bytes long. How many 64-byte blocks does SHA-256 process? Two. The padding requires one byte for the appended 1 bit and its zeros and eight bytes for the 64-bit length field, that is nine bytes at minimum, so 56 plus 9 exceeds 64 and a second block is needed. A 55-byte message fits in one.
4. Where do SHA-512's round constants come from? They are the first 64 bits of the fractional parts of the cube roots of the first eighty prime numbers. The chapter's module computes them from that description rather than transcribing a table, so the digests matching FIPS 180-4's appendices is evidence that the description is correct; the first constant is 428a2f98d728ae22.
The Secure Hash Algorithm: SHA-1, SHA-256 and SHA-512
5. Describe the SHA-2 compression step. For each padded block, the sixteen input words are expanded into 64 or 80 words by a recurrence using rotations and shifts. Eight working variables, initialised from the previous chaining value, are then mixed through that many rounds using modular additions, the Ch and Maj functions, two rotation-based functions, a round constant and one scheduled word. Finally the round output is added word by word to the values the block started with, which is the trailing addition that makes the function one-way.
6. What is SHA-1's current status, and why is the answer not simply "banned"? A collision was published in February 2017, so its collision resistance is gone and it must not be used for digital signatures, certificates or anything else depending on collision resistance; RFC 6194 of March 2011 had already restricted it. But no preimage attack is known, and HMAC's security does not rest on collision resistance, so HMAC-SHA-1 remains acceptable and FIPS 180-4 still specifies SHA-1 for such uses. The correct answer names the property rather than the algorithm.
7. Is SHA-3 a replacement for SHA-2? No. It was standardised in FIPS 202 as a structurally different alternative, built on the sponge construction rather than the iterated Merkle and Damgard one, so that a break of that construction would not leave no usable hash. It also lacks the length-extension property. Both families are current.
The rest of this subject
These notes are cut from the University's printed syllabus. Open the syllabus itself for the same subject.