Vad är en Hash-funktion?

En hash-funktion är en matematisk algoritm som tar input av valfri storlek och producerar en fix-längd output (hash). Det är en “one-way function” - lätt att beräkna framåt, men praktiskt omöjligt att reversera.

Grundläggande egenskaper

1. Deterministisk Samma input ger alltid samma output:

"hello" → 5d41402abc4b2a76b9719d911017c592
"hello" → 5d41402abc4b2a76b9719d911017c592  // Alltid samma

2. Fix längd Oavsett input-storlek, samma output-längd:

MD5("hi")     → 49f68a5c8493ec2c0bf489821c21fc3b  (32 hex chars)
MD5("hello")  → 5d41402abc4b2a76b9719d911017c592  (32 hex chars)
MD5("very long text...") → ... (32 hex chars)

3. Avalanche Effect Minimal förändring i input ger total förändring i output:

MD5("hello")  → 5d41402abc4b2a76b9719d911017c592
MD5("hallo")  → 4d186321c1a7f0f354b297e8914ab240  // Helt annorlunda!

4. Snabbt att beräkna Hash-funktioner är designade för att vara snabba.

Hash-algoritmer

MD5 (Message Digest 5)

Output: 128 bits (32 hex tecken)

MD5("password") → 5f4dcc3b5aa765d61d8327deb882cf99

Skapad: 1991 av Ronald Rivest

Status:BRUTEN - Använd INTE för säkerhet

Varför bruten?

  • Collision attacks möjliga sedan 2004
  • Kan generera två olika inputs med samma hash
  • Kan crackas på minuter med modern hårdvara

När kan MD5 fortfarande användas?

// ✅ OK: Non-security checksums
const fileChecksum = md5(fileContent);

// ✅ OK: Cache keys
const cacheKey = md5(url + params);

// ❌ ALDRIG: Lösenord eller säkerhetsrelaterat
const passwordHash = md5(password);  // FARLIGT!

SHA-1 (Secure Hash Algorithm 1)

Output: 160 bits (40 hex tecken)

SHA1("password") → 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8

Skapad: 1995 av NSA

Status:DEPRECATED - Fasa ut

Varför deprecated?

  • Teoretiska collision attacks 2005
  • Praktiska collisions demonstrerade 2017 (SHAttered attack)
  • Git använder fortfarande SHA-1 men migrerar till SHA-256

Användning idag:

// ⚠️ Legacy system - fasa ut
if (isLegacySystem) {
  hash = sha1(data);  // Planera migration till SHA-256
}

// ❌ Nya system - använd INTE
const newHash = sha1(password);  // Använd SHA-256+ istället

SHA-256 (SHA-2 family)

Output: 256 bits (64 hex tecken)

SHA256("password") → 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

Skapad: 2001 av NSA

Status:SÄKER - Rekommenderad

Fördelar:

  • Inga kända praktiska attacks
  • Används i Bitcoin och blockchain
  • NIST standard
  • Balans mellan säkerhet och prestanda

Användning:

// ✅ File integrity
const fileHash = sha256(fileContent);

// ✅ Digital signatures
const signature = sign(sha256(message), privateKey);

// ✅ Blockchain
const blockHash = sha256(sha256(blockHeader));  // Bitcoin double-SHA256

// ⚠️ Lösenord - använd bcrypt/argon2 istället
const passwordHash = sha256(password);  // OK men bcrypt är bättre

SHA-512 (SHA-2 family)

Output: 512 bits (128 hex tecken)

SHA512("password") → b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86

Skapad: 2001 av NSA

Status:SÄKER - Extra stark

Fördelar:

  • Starkare säkerhet än SHA-256
  • Snabbare på 64-bit system
  • Större hash = mindre risk för collisions

Nackdelar:

  • Dubbelt så lång output
  • Långsammare på 32-bit system
  • Ofta overkill för de flesta use cases

När använda SHA-512:

// ✅ Extra känslig data
const topSecretHash = sha512(sensitiveData);

// ✅ Long-term arkivering
const archiveHash = sha512(document);

// ✅ HMAC för tokens
const token = hmacSha512(data, secretKey);

// ❌ När storlek spelar roll (URLs, databaser)
const shortHash = sha256(data);  // Bättre val

SHA-3 (Keccak)

Output: Variabel (224, 256, 384, 512 bits)

Skapad: 2015 (NIST competition vinnare)

Status:SÄKER - Ny standard

Skillnader från SHA-2:

  • Helt annan intern struktur (sponge construction)
  • Inte baserad på Merkle-Damgård
  • Teoretiskt mer motståndskraftig mot vissa attacks

Användning:

// ✅ När SHA-2 inte är tillräckligt
const futureProofHash = sha3_256(data);

// ✅ Ethereum använder Keccak256
const ethereumHash = keccak256(data);

Varför inte mer populär?

  • SHA-256 är fortfarande säker
  • SHA-3 är långsammare i många implementationer
  • Mindre ecosystem support

Jämförelse

AlgorithmOutput SizeSpeedSecurityUse Case
MD5128 bit⚡⚡⚡ Snabbast❌ BrutenChecksums (non-security)
SHA-1160 bit⚡⚡ Snabb⚠️ DeprecatedLegacy, Git
SHA-256256 bit⚡ Medium✅ SäkerRekommenderad standard
SHA-512512 bit⚡ Medium✅ Mycket säkerExtra säkerhet
SHA-3Variabel🐌 Långsammare✅ FramtidssäkerNya system

Praktiska exempel

1. File Integrity Check

// Ladda ner fil och verifiera integritet
async function downloadAndVerify(url, expectedHash) {
  const response = await fetch(url);
  const buffer = await response.arrayBuffer();
  
  const hash = await crypto.subtle.digest('SHA-256', buffer);
  const hashHex = Array.from(new Uint8Array(hash))
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
  
  if (hashHex !== expectedHash) {
    throw new Error('File integrity check failed!');
  }
  
  return buffer;
}

// Användning
await downloadAndVerify(
  'https://example.com/file.zip',
  'abc123...'  // SHA-256 hash från källan
);

2. Git Commit Hash

# Git använder SHA-1 (migrerar till SHA-256)
git log --oneline
# a1b2c3d Fix bug in login
# e4f5g6h Add new feature

# Commit hash är SHA-1 av:
# - Tree hash
# - Parent commit hash
# - Author info
# - Commit message
# - Timestamp

3. Bitcoin Mining

// Bitcoin mining = hitta hash som börjar med nollor
function mine(blockHeader, difficulty) {
  let nonce = 0;
  const target = '0'.repeat(difficulty);
  
  while (true) {
    const hash = sha256(sha256(blockHeader + nonce));
    
    if (hash.startsWith(target)) {
      return { nonce, hash };
    }
    
    nonce++;
  }
}

// Hitta hash som börjar med 4 nollor
const result = mine("Block data...", 4);
// { nonce: 182394, hash: "0000abc123..." }

4. Password Verification (DÅLIG METOD)

// ❌ ANVÄND ALDRIG SHA för lösenord direkt!
function badPasswordHash(password) {
  return sha256(password);
}

// Problem:
// 1. För snabbt - 1 miljard försök per sekund
// 2. Rainbow tables
// 3. Ingen salt

// ✅ Använd istället bcrypt/argon2
import bcrypt from 'bcrypt';

async function goodPasswordHash(password) {
  const salt = await bcrypt.genSalt(12);
  return await bcrypt.hash(password, salt);
}

5. Cache Keys

// ✅ Bra användning av SHA-256 för cache
function getCacheKey(url, params) {
  const data = JSON.stringify({ url, params });
  return sha256(data);
}

const cacheKey = getCacheKey(
  '/api/users',
  { page: 1, limit: 10 }
);
// "a1b2c3d4..."

cache.get(cacheKey);

Hash vs Encryption

HashEncryption
One-wayTwo-way
Fix output sizeVariabel output
SnabbLångsammare
DeterministiskAnvänder keys
Integrity checkConfidentiality

Hash:

const hash = sha256("secret");
// "2bb80..." 
// Kan INTE återfås till "secret"

Encryption:

const encrypted = encrypt("secret", key);
// "x7j9k..."
const decrypted = decrypt(encrypted, key);
// "secret"  ✅ Kan dekrypteras

HMAC (Hash-based Message Authentication Code)

Kombinerar hash med en secret key:

function hmac(message, secretKey) {
  const hash1 = sha256((secretKey ^ opad) + sha256((secretKey ^ ipad) + message));
  return hash1;
}

// Verifierar både integritet OCH autenticitet
const signature = hmac("message", "secret-key");

Användning:

  • JWT tokens
  • API signatures (AWS, etc.)
  • Webhook verification
// Verifiera webhook från GitHub
const signature = req.headers['x-hub-signature-256'];
const payload = req.body;
const secret = process.env.WEBHOOK_SECRET;

const expectedSignature = 'sha256=' + 
  crypto.createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');

if (signature !== expectedSignature) {
  throw new Error('Invalid signature');
}

Rainbow Tables & Salt

Problem:

// Samma lösenord = samma hash
sha256("password123") → "ef92b..."
sha256("password123") → "ef92b..."  // Samma!

// Rainbow table: förberäknade hashar
// "password123" → "ef92b..."
// "123456"      → "8d969..."
// ...millions more...

Lösning: Salt

// Lägg till random data innan hash
const salt = generateRandomBytes(16);
const hash = sha256(password + salt);

// Spara både salt och hash
db.save({
  salt: salt,
  hash: hash
});

// Nu är samma lösenord olika hash
sha256("password123" + "abc") → "123..."
sha256("password123" + "xyz") → "789..."  // Olika!

Därför: Använd bcrypt som gör detta automatiskt!

Välja rätt algoritm

För File Integrity

SHA-256  // Bästa balansen
SHA-512  // Extra paranoid
MD5      // Bara för non-security

För Lösenord

✅ bcrypt    // Rekommenderad
✅ argon2    // Modernare, starkare
✅ scrypt    // Också bra
SHA-256   // För snabbt, ingen salt management
MD5       // ALDRIG!

För Digital Signatures

SHA-256  // Standard
SHA-512  // Extra säkerhet
SHA-3    // Framtidssäker

För Git/Blockchain

SHA-256  // Bitcoin, modern Git
⚠️ SHA-1   // Legacy Git (migrerar)

För Cache Keys

SHA-256  // Bra balans
MD5      // OK för cache
SHA-1    // OK för cache

Performance

Benchmark (1 miljard operationer):

MD5:     ~2 sekunder   ⚡⚡⚡
SHA-1:   ~3 sekunder   ⚡⚡
SHA-256: ~4 sekunder   ⚡
SHA-512: ~3 sekunder   ⚡ (på 64-bit)
SHA-3:   ~6 sekunder   🐌

För de flesta applikationer spelar hastigheten ingen roll!

Security Best Practices

1. Använd rätt verktyg

// ❌ Fel verktyg
const passwordHash = md5(password);

// ✅ Rätt verktyg
const passwordHash = await bcrypt.hash(password, 12);

2. Håll dig uppdaterad

// ⚠️ Fasas ut
if (usingLegacySHA1) {
  planMigrationToSHA256();
}

3. Kombinera med salt

// ❌ Utan salt
const hash = sha256(password);

// ✅ Med salt
const salt = crypto.randomBytes(16);
const hash = sha256(password + salt);

4. Iterera för lösenord

// ❌ En iteration
const hash = sha256(password);

// ✅ Många iterationer (bcrypt gör detta)
let hash = password;
for (let i = 0; i < 10000; i++) {
  hash = sha256(hash);
}

Verktyg

Testa olika hash-algoritmer:

Slutsats

För nya projekt:

  • SHA-256 - Standard för file integrity, signatures
  • bcrypt/argon2 - ALLTID för lösenord
  • HMAC-SHA256 - För authentication tokens

Undvik:

  • MD5 - Endast non-security use cases
  • SHA-1 - Fasas ut, planera migration
  • SHA-256 för lösenord - Använd bcrypt istället

Kom ihåg: Hash ≠ Encryption ≠ Encoding

Välj rätt verktyg för jobbet!