Introduction to the SHA-224 Algorithm
SHA-224 is a member of the SHA-2 family of cryptographic hash functions, standardized by the National Institute of Standards and Technology (NIST) in FIPS PUB 180-4. The "224" in its name refers to the output size: a 224-bit (28-byte) hash value, typically represented as a 56-character hexadecimal string.
SHA-224 is essentially a truncated version of SHA-256, using different initial hash values but the same internal structure and operations. It was designed to provide a security level appropriate for 112-bit symmetric encryption schemes while offering better performance than longer hashes in constrained environments.
SHA-224 Algorithm Key Properties
- Output Size: 224 bits (28 bytes)
- Internal State Size: 256 bits (same as SHA-256)
- Block Size: 512 bits (64 bytes)
- Word Size: 32 bits
- Number of Rounds: 64
- Operations: Bitwise operations (AND, OR, XOR, NOT), modular addition, rotations
- Endianness: Big-endian
- Security Level: 112 bits (against collision attacks)
Relationship to SHA-256
SHA-224 and SHA-256 are closely related algorithms with the following key differences:
Feature | SHA-224 | SHA-256 |
---|---|---|
Output Size | 224 bits (28 bytes) | 256 bits (32 bytes) |
Initial Hash Values | Different set of constants | Standard SHA-256 constants |
Output Processing | Uses only first 7 words of state | Uses all 8 words of state |
Internal Structure | Identical to SHA-256 | Identical to SHA-224 |
Compression Function | Same as SHA-256 | Same as SHA-224 |
Constants (K values) | Same as SHA-256 | Same as SHA-224 |
Message Schedule | Same as SHA-256 | Same as SHA-224 |
In essence, SHA-224 is SHA-256 with different initialization values and with the final hash value truncated to 224 bits (the first 7 words of the 8-word state). The internal processing is identical, which allows implementations to easily support both hash functions with minimal additional code.
SHA-224 Algorithm Components
Initial Hash Values (H0)
SHA-224 uses the following 8 initial hash values (32-bit words), which are different from those used in SHA-256:
const H0 = [
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
];
Round Constants (K)
SHA-224 uses the same 64 constant 32-bit words as SHA-256. These constants represent the first 32 bits of the fractional parts of the cube roots of the first 64 prime numbers:
const 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
];
Core Functions
SHA-224 relies on six logical functions, each operating on 32-bit words:
// Bitwise rotation right
function ROTR(x, n) {
return (x >>> n) | (x << (32 - n));
}
// Ch function: choose bits from y or z based on x
function Ch(x, y, z) {
return (x & y) ^ (~x & z);
}
// Maj function: majority function (most common bit wins)
function Maj(x, y, z) {
return (x & y) ^ (x & z) ^ (y & z);
}
// Sigma 0 function
function Σ0(x) {
return ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22);
}
// Sigma 1 function
function Σ1(x) {
return ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25);
}
// Lowercase sigma 0 function (for message schedule)
function σ0(x) {
return ROTR(x, 7) ^ ROTR(x, 18) ^ (x >>> 3);
}
// Lowercase sigma 1 function (for message schedule)
function σ1(x) {
return ROTR(x, 17) ^ ROTR(x, 19) ^ (x >>> 10);
}
SHA-224 Algorithm Step-by-Step
1. Preprocessing
- Padding the message: Append a single "1" bit, followed by zeros, and then the message length as a 64-bit value to make the total length a multiple of 512 bits (64 bytes).
- Initialize hash values: Set the initial hash state H(0) to the eight 32-bit values specified for SHA-224.
2. Message Processing (for each 512-bit block)
- Create message schedule (W): Break the block into 16 32-bit words (W0 to W15), then extend to create 64 words using the formula:
Wt = σ1(Wt-2) + Wt-7 + σ0(Wt-15) + Wt-16for t = 16 to 63.
- Initialize working variables: Set a, b, c, d, e, f, g, h to the current hash values H(i-1).
- Compression function: For t = 0 to 63:
T1 = h + Σ1(e) + Ch(e, f, g) + Kt + Wt
T2 = Σ0(a) + Maj(a, b, c)
h = g
g = f
f = e
e = d + T1
d = c
c = b
b = a
a = T1 + T2 - Update hash values: After processing each block, update the hash values:
H(i)0 = a + H(i-1)0
H(i)1 = b + H(i-1)1
H(i)2 = c + H(i-1)2
H(i)3 = d + H(i-1)3
H(i)4 = e + H(i-1)4
H(i)5 = f + H(i-1)5
H(i)6 = g + H(i-1)6
H(i)7 = h + H(i-1)7
3. Output
The final hash value is the concatenation of H0 through H6 (the first 7 words of the final state), producing a 224-bit output. Unlike SHA-256, which uses all 8 words, SHA-224 discards the final word to produce a 224-bit output.

Figure 1: SHA-224 algorithm processing flow, showing the compression function and state transformation.
Complete SHA-224 Implementation
Below is a complete implementation of the SHA-224 algorithm in JavaScript. This implementation is designed for clarity and educational purposes rather than optimized performance:
/**
* SHA-224 implementation in JavaScript
* Based on the Secure Hash Standard (SHS) - FIPS PUB 180-4
*/
function sha224(input) {
// Initial hash values (SHA-224 specific)
const H = [
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
];
// SHA-256 round constants
const 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
];
// Convert string to bytes
function stringToBytes(str) {
const encoder = new TextEncoder();
return encoder.encode(str);
}
// Right rotate a 32-bit number
function ROTR(x, n) {
return ((x >>> n) | (x << (32 - n))) >>> 0;
}
// Logical functions
function Ch(x, y, z) {
return ((x & y) ^ ((~x) & z)) >>> 0;
}
function Maj(x, y, z) {
return ((x & y) ^ (x & z) ^ (y & z)) >>> 0;
}
function Sigma0(x) {
return (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) >>> 0;
}
function Sigma1(x) {
return (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) >>> 0;
}
function sigma0(x) {
return (ROTR(x, 7) ^ ROTR(x, 18) ^ (x >>> 3)) >>> 0;
}
function sigma1(x) {
return (ROTR(x, 17) ^ ROTR(x, 19) ^ (x >>> 10)) >>> 0;
}
// Process the message
function process() {
// Convert input to bytes and add padding
let bytes = (typeof input === 'string') ? stringToBytes(input) : input;
const originalLength = bytes.length * 8;
// Step 1: Padding the message
// Append the bit '1' to the message
bytes = [...bytes, 0x80];
// Append padding zeros
while ((bytes.length % 64) !== 56) {
bytes.push(0);
}
// Append the length as a 64-bit big-endian integer
const lengthBytes = new Array(8).fill(0);
for (let i = 0; i < 8; i++) {
lengthBytes[7 - i] = (originalLength >>> (i * 8)) & 0xff;
}
bytes = bytes.concat(lengthBytes);
// Step 2: Process each 64-byte chunk
for (let i = 0; i < bytes.length; i += 64) {
// Create the message schedule array (W)
const W = new Array(64);
// Copy chunk into first 16 words of W
for (let j = 0; j < 16; j++) {
W[j] = (bytes[i + j * 4] << 24) |
(bytes[i + j * 4 + 1] << 16) |
(bytes[i + j * 4 + 2] << 8) |
(bytes[i + j * 4 + 3]);
}
// Extend the first 16 words into remaining 48 words of W
for (let j = 16; j < 64; j++) {
W[j] = (sigma1(W[j - 2]) + W[j - 7] + sigma0(W[j - 15]) + W[j - 16]) >>> 0;
}
// Initialize working variables with current hash value
let [a, b, c, d, e, f, g, h] = H;
// Compression function main loop
for (let j = 0; j < 64; j++) {
const T1 = (h + Sigma1(e) + Ch(e, f, g) + K[j] + W[j]) >>> 0;
const T2 = (Sigma0(a) + Maj(a, b, c)) >>> 0;
h = g;
g = f;
f = e;
e = (d + T1) >>> 0;
d = c;
c = b;
b = a;
a = (T1 + T2) >>> 0;
}
// Add compressed chunk to current hash value
H[0] = (H[0] + a) >>> 0;
H[1] = (H[1] + b) >>> 0;
H[2] = (H[2] + c) >>> 0;
H[3] = (H[3] + d) >>> 0;
H[4] = (H[4] + e) >>> 0;
H[5] = (H[5] + f) >>> 0;
H[6] = (H[6] + g) >>> 0;
H[7] = (H[7] + h) >>> 0;
}
// Step 3: Produce the final hash (for SHA-224, only use first 7 words)
let result = '';
for (let i = 0; i < 7; i++) {
result += H[i].toString(16).padStart(8, '0');
}
return result;
}
return process();
}
// Example usage
const text = "Hello, world!";
const hash = sha224(text);
console.log(`SHA-224("${text}") = ${hash}`);
// Ensure the standalone SHA224 function is available for testing
if (typeof window !== 'undefined') {
window.sha224 = sha224;
}
This implementation follows the algorithm as specified in FIPS PUB 180-4 and produces a 224-bit (28-byte) hash output represented as a 56-character hexadecimal string.
Standard Test Vectors
To verify an implementation of SHA-224, you can use these standard test vectors from NIST:
Input | SHA-224 Hash Output (224 bits / 28 bytes) |
---|---|
"" (empty string) |
d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f |
abc |
23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7 |
abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq |
75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525 |
One million repetitions of a |
20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67 |
Verification Tool
You can verify your SHA-224 implementation against these test vectors using our SHA-224 Calculator.
Performance Considerations
When implementing SHA-224, several optimizations can improve performance:
Word-Level Parallelism
The algorithm operates on 32-bit words and can benefit from processors with 32-bit or wider data paths.
Unrolled Loops
Unrolling the main loop (partially or fully) can reduce branch prediction penalties and improve performance.
Message Schedule Optimization
Calculating the message schedule incrementally can reduce memory usage and improve cache locality.
SIMD Instructions
Modern CPUs with SIMD (Single Instruction, Multiple Data) can process multiple words in parallel.
Hardware Acceleration
Many modern processors include dedicated instructions or cryptographic acceleration for SHA-2 family functions.
Endianness Handling
Optimizing byte swapping operations for the target architecture can improve performance.
For more detailed performance optimizations, see our SHA-224 Performance Guide.
Algorithm Security
SHA-224 offers 112 bits of security against collision attacks, which means finding two different inputs that produce the same hash would require approximately 2112 operations. This security level is specifically designed to match symmetric encryption schemes with 112-bit keys.
Security Properties
- Preimage Resistance: Given a hash h, it's computationally infeasible to find any input m such that hash(m) = h. For SHA-224, this requires approximately 2224 operations.
- Second Preimage Resistance: Given an input m1, it's computationally infeasible to find another input m2 (≠ m1) such that hash(m1) = hash(m2). For SHA-224, this requires approximately 2224 operations.
- Collision Resistance: It's computationally infeasible to find any two different inputs m1 and m2 such that hash(m1) = hash(m2). For SHA-224, this requires approximately 2112 operations due to the birthday paradox.
Known Attacks
As of 2025, there are no known practical attacks against SHA-224 that significantly reduce its security below the theoretical levels described above. The best-known attacks on the SHA-2 family involve reduced-round versions or theoretical constructions that don't threaten real-world security.
Security Recommendations
While SHA-224 remains secure for most applications, consider the following:
- For long-term security (beyond 2030), consider stronger alternatives like SHA-256 or SHA-3 family functions
- For password hashing, always use specialized algorithms like Argon2, bcrypt, or PBKDF2 rather than plain SHA-224
- For digital signatures, ensure you're using appropriate key sizes that match SHA-224's security level (112 bits)
For a more detailed security analysis, visit our SHA-224 Security Analysis page.
Advanced Algorithm Topics
Length Extension Attacks
Like other Merkle–Damgård construction hash functions, SHA-224 is vulnerable to length extension attacks. This means if you know H(message1), you can calculate H(message1 || padding || message2) without knowing the original message1. This property has security implications for certain uses like simple keyed hashing schemes.
To prevent length extension attacks, use constructions like HMAC-SHA224 rather than simple concatenation schemes like H(key || message).
Entropy and Output Distribution
SHA-224 exhibits excellent avalanche effect properties, where a small change in the input (even a single bit) results in a completely different hash output with approximately half the bits changed. The output distribution is uniform across the 224-bit space for any reasonable input distribution.
State Recovery
Unlike SHA-256, where the full internal state is exposed in the output, SHA-224 truncates the final state by omitting the last 32-bit word. This provides a small additional security margin against certain types of analytical attacks that attempt to recover the internal state.
Implementation in Constrained Environments
SHA-224 is particularly well-suited for memory-constrained environments like embedded systems and IoT devices. For specific optimization techniques tailored to these environments, see our SHA-224 for Embedded Systems guide.