Skip to content

Checksum Verifier — Swift source

Drag and drop a file to compute its MD5, SHA-1, SHA-256, and SHA-512 checksums. Paste an expected hash to verify integrity - detect tampered or corrupted downloads instantly. Runs entirely in your browser.

This is the Swift implementation — the same logic the interactive tool runs, in a shareable, citable form.

// checksum-verifier — MD5 / SHA-1 / SHA-256 / SHA-512 checksums + verification.
//
// Language: Swift 5.9+ (Foundation + CryptoKit)
// Ported from src/lib/checksum-verifier.ts
// display source — part of CosmoDev's polyglot tool pages
//
// The TS reference implements MD5 from scratch (RFC 1321) because the Web
// Crypto API does not expose MD5. CryptoKit DOES ship MD5 — under the
// `Insecure` namespace, marking it as integrity-only — so this port uses it
// directly. SHA-1 (also `Insecure`) and SHA-256/SHA-512 are CryptoKit native.

import Foundation
import CryptoKit

// MARK: - Types

struct ChecksumResult {
    let md5: String
    let sha1: String
    let sha256: String
    let sha512: String
}

enum HashAlgorithm: String, CaseIterable {
    case md5
    case sha1
    case sha256
    case sha512

    /// Hex length of the digest this algorithm produces.
    var hexLength: Int {
        switch self {
        case .md5: return 32
        case .sha1: return 40
        case .sha256: return 64
        case .sha512: return 128
        }
    }
}

// MARK: - Digest helpers

func toHex(_ bytes: Data) -> String {
    bytes.map { String(format: "%02x", $0) }.joined()
}

/// Synchronous one-shot MD5 of a buffer, as lowercase hex.
/// (MD5 is only for integrity checks - not security.)
func md5Hex(_ data: Data) -> String {
    toHex(Data(Insecure.MD5.hash(data: data)))
}

/// Digest a buffer and return lowercase hex.
func shaHex(algorithm: HashAlgorithm, data: Data) -> String {
    switch algorithm {
    case .md5: return md5Hex(data)
    case .sha1: return toHex(Data(Insecure.SHA1.hash(data: data)))
    case .sha256: return toHex(Data(SHA256.hash(data: data)))
    case .sha512: return toHex(Data(SHA512.hash(data: data)))
    }
}

/// Compute all four checksums of a buffer.
func computeChecksums(_ data: Data) -> ChecksumResult {
    ChecksumResult(
        md5: md5Hex(data),
        sha1: shaHex(algorithm: .sha1, data: data),
        sha256: shaHex(algorithm: .sha256, data: data),
        sha512: shaHex(algorithm: .sha512, data: data)
    )
}

// MARK: - Verification helpers

/// Normalize a pasted hash: drop whitespace and `:` grouping, lowercase.
func normalizeHash(_ hash: String) -> String {
    String(hash.filter { !$0.isWhitespace && $0 != ":" }).lowercased()
}

/// Detect the algorithm from the hex length: 32=MD5, 40=SHA-1, 64=SHA-256, 128=SHA-512.
func detectHashAlgorithm(_ hash: String) -> HashAlgorithm? {
    let h = normalizeHash(hash)
    guard !h.isEmpty, h.allSatisfy({ $0.isASCII && $0.isHexDigit }) else { return nil }
    return HashAlgorithm.allCases.first { $0.hexLength == h.count }
}

/**
 * Compare an expected hash against a computed result. Returns nil when the
 * expected string is not a recognizable hex hash of a supported length.
 */
func verifyChecksum(expected: String, result: ChecksumResult) -> (algorithm: HashAlgorithm, match: Bool)? {
    guard let algorithm = detectHashAlgorithm(expected) else { return nil }
    let computed: String
    switch algorithm {
    case .md5: computed = result.md5
    case .sha1: computed = result.sha1
    case .sha256: computed = result.sha256
    case .sha512: computed = result.sha512
    }
    return (algorithm, normalizeHash(expected) == computed)
}

Also available in 8 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →