Complete guide for migrating from MD5, SHA-1, SHA-256, and other hash functions
| Algorithm | Output Size | Security Level | Performance | Status | Migration Priority |
|---|---|---|---|---|---|
| MD5 | 128 bits | โ Broken | Very Fast | Deprecated | Critical |
| SHA-1 | 160 bits | โ ๏ธ Weak | Fast | Phasing Out | High |
| SHA-224 | 224 bits | โ Strong | Good | Recommended | Target |
| SHA-256 | 256 bits | โ Strong | Good | Recommended | Optional |
# Python - MD5
import hashlib
def hash_password(password):
return hashlib.md5(password.encode()).hexdigest()
def verify_file(filepath):
with open(filepath, 'rb') as f:
return hashlib.md5(f.read()).hexdigest()
# Usage
hash = hash_password("secret") # 32 chars
# Python - SHA-224
import hashlib
def hash_password(password):
# Note: Use bcrypt/scrypt for passwords!
return hashlib.sha224(password.encode()).hexdigest()
def verify_file(filepath):
with open(filepath, 'rb') as f:
return hashlib.sha224(f.read()).hexdigest()
# Usage
hash = hash_password("secret") # 56 chars
// JavaScript - MD5
const crypto = require('crypto');
function hashData(data) {
return crypto
.createHash('md5')
.update(data)
.digest('hex');
}
// Browser (with library)
const hash = md5(data);
// JavaScript - SHA-224
const crypto = require('crypto');
function hashData(data) {
return crypto
.createHash('sha224')
.update(data)
.digest('hex');
}
// Browser WebCrypto
async function sha224(data) {
const buffer = await crypto.subtle.digest(
'SHA-224',
new TextEncoder().encode(data)
);
return Array.from(new Uint8Array(buffer))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
ALTER TABLE files ADD COLUMN sha224_hash VARCHAR(56);
ALTER TABLE files DROP COLUMN md5_hash;
# Git uses SHA-1 by default, but SHA-256 support is available
# For SHA-224 in custom applications:
# Before: SHA-1 for commit verification
git_hash=$(echo -n "$content" | sha1sum | cut -d' ' -f1)
# After: SHA-224 for commit verification
git_hash=$(echo -n "$content" | sha224sum | cut -d' ' -f1)
# Python migration for Git-like systems
import hashlib
class Repository:
def __init__(self, hash_algo='sha224'):
self.hash_algo = hash_algo
def hash_object(self, content):
if self.hash_algo == 'sha1':
# Legacy support
return hashlib.sha1(content).hexdigest()
elif self.hash_algo == 'sha224':
return hashlib.sha224(content).hexdigest()
def verify_object(self, content, hash_value):
computed = self.hash_object(content)
return computed == hash_value
| Component | SHA-1 Usage | SHA-224 Migration | Timeline |
|---|---|---|---|
| SSL/TLS Certificates | Signature Algorithm | Update to SHA-224 or SHA-256 | Immediate |
| Code Signing | Binary signatures | Re-sign with SHA-224 | Next release |
| Document Signing | PDF signatures | Update signing algorithm | Gradual |
| API Tokens | HMAC-SHA1 | Migrate to HMAC-SHA224 | With versioning |
// TypeScript - Handling different hash lengths
interface HashConfig {
algorithm: 'sha224' | 'sha256';
encoding: 'hex' | 'base64';
}
class HashMigration {
private config: HashConfig;
constructor(config: HashConfig) {
this.config = config;
}
getHashLength(): number {
const lengths = {
sha224: { hex: 56, base64: 38 },
sha256: { hex: 64, base64: 44 }
};
return lengths[this.config.algorithm][this.config.encoding];
}
async computeHash(data: string): Promise {
const encoder = new TextEncoder();
const dataBuffer = encoder.encode(data);
const hashBuffer = await crypto.subtle.digest(
this.config.algorithm.toUpperCase().replace('SHA', 'SHA-'),
dataBuffer
);
if (this.config.encoding === 'hex') {
return Array.from(new Uint8Array(hashBuffer))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
} else {
return btoa(String.fromCharCode(...new Uint8Array(hashBuffer)));
}
}
validateHash(hash: string): boolean {
const expectedLength = this.getHashLength();
return hash.length === expectedLength;
}
}
-- SQL Migration Script
-- Step 1: Add SHA-224 column with appropriate size
ALTER TABLE documents
ADD COLUMN hash_sha224 CHAR(56);
-- Step 2: Create index for new column
CREATE INDEX idx_hash_sha224 ON documents(hash_sha224);
-- Step 3: Batch update existing records
UPDATE documents
SET hash_sha224 = compute_sha224(content)
WHERE hash_sha224 IS NULL
LIMIT 1000;
-- Step 4: Add constraint after migration
ALTER TABLE documents
ALTER COLUMN hash_sha224 SET NOT NULL;
-- Step 5: Update application queries
-- Before: WHERE hash_sha256 = ?
-- After: WHERE hash_sha224 = ?
| Database | SHA-224 Function | Example Usage | Notes |
|---|---|---|---|
| PostgreSQL | digest(data, 'sha224') | SELECT digest('test', 'sha224') |
Requires pgcrypto extension |
| MySQL 8.0+ | SHA2(str, 224) | SELECT SHA2('test', 224) |
Native support |
| MongoDB | Custom function | Use application layer | Compute before insert |
| SQLite | Extension required | Load crypto extension | Or compute in app |
// Test vectors for SHA-224
const testVectors = [
{
input: "",
expected: "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"
},
{
input: "abc",
expected: "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"
},
{
input: "The quick brown fox jumps over the lazy dog",
expected: "730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525"
}
];
async function validateImplementation() {
console.log('๐งช Running SHA-224 implementation tests...\n');
for (const vector of testVectors) {
const result = await sha224(vector.input);
const passed = result === vector.expected;
console.log(`Input: "${vector.input}"`);
console.log(`Expected: ${vector.expected}`);
console.log(`Got: ${result}`);
console.log(`Result: ${passed ? 'โ
PASS' : 'โ FAIL'}\n`);
if (!passed) {
throw new Error('Implementation validation failed');
}
}
console.log('All tests passed! โ
');
}
class HashService:
def __init__(self, config):
self.config = config
self.use_sha224 = config.get('feature_flags', {}).get('use_sha224', False)
self.dual_write = config.get('feature_flags', {}).get('dual_write', True)
def compute_hash(self, data):
"""Compute hash with feature flag control"""
if self.use_sha224:
primary_hash = hashlib.sha224(data.encode()).hexdigest()
if self.dual_write:
# Also compute legacy hash for comparison
legacy_hash = self._compute_legacy_hash(data)
self._log_hash_comparison(primary_hash, legacy_hash)
return primary_hash
else:
return self._compute_legacy_hash(data)
def _compute_legacy_hash(self, data):
"""Compute using previous algorithm (MD5/SHA1)"""
return hashlib.md5(data.encode()).hexdigest()
def _log_hash_comparison(self, new_hash, old_hash):
"""Log for monitoring during migration"""
logger.info(f"Hash computed - SHA224: {new_hash[:16]}..., Legacy: {old_hash[:16]}...")
def rollback(self):
"""Emergency rollback procedure"""
self.use_sha224 = False
self.dual_write = False
logger.warning("ROLLBACK: Reverted to legacy hashing algorithm")
#!/bin/bash
# SHA-224 Migration Helper Script
echo "๐ SHA-224 Migration Helper"
echo "=========================="
# Function to convert file hashes
migrate_file_hashes() {
local dir=$1
echo "Processing files in $dir..."
find "$dir" -type f | while read -r file; do
old_hash=$(md5sum "$file" | cut -d' ' -f1)
new_hash=$(sha224sum "$file" | cut -d' ' -f1)
echo "$file,$old_hash,$new_hash" >> migration_log.csv
done
echo "โ
Migration log saved to migration_log.csv"
}
# Function to test implementation
test_sha224() {
echo -n "abc" | sha224sum | grep -q "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"
if [ $? -eq 0 ]; then
echo "โ
SHA-224 implementation test passed"
else
echo "โ SHA-224 implementation test failed"
exit 1
fi
}
# Main menu
PS3='Select migration task: '
options=("Test SHA-224" "Migrate Directory" "Generate Report" "Exit")
select opt in "${options[@]}"
do
case $opt in
"Test SHA-224")
test_sha224
;;
"Migrate Directory")
read -p "Enter directory path: " dir
migrate_file_hashes "$dir"
;;
"Generate Report")
echo "Generating migration report..."
wc -l migration_log.csv
;;
"Exit")
break
;;
*) echo "Invalid option";;
esac
done