Skip to content

Hash Generator — C# source

Compute SHA-1, SHA-256, SHA-384 and SHA-512 hashes of any text at once, using the browser's native SubtleCrypto. Copy each digest. 100% client-side.

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

// hash — SHA-1 / SHA-256 / SHA-384 / SHA-512 digest of a UTF-8 string.
//
// Language: C# 12 (.NET 8, standard library only)
// Source:   CosmoDev polyglot showcase port of the `hash` tool, ported from
//           src/tools/HashGenerator.tsx (the canonical TypeScript island).
// License:  display source — part of CosmoDev's polyglot tool pages.
//
// Unkeyed SHA digests via System.Security.Cryptography — the vetted,
// constant-time implementations .NET ships on every platform. The static
// HashData entry points (added in .NET 5) compute a one-shot digest without
// the using/Dispose ceremony the older Create() pattern needed, and
// Convert.ToHexString supplies the lowercase hex the TypeScript reference
// produces. No NuGet packages are required.
//
// Behavior mirrors the TypeScript reference: UTF-8 input, lowercase hex
// output, and rejection of unknown algorithm names (ArgumentException — the
// C# standing of the Python port's ValueError). SHA-1 is offered for legacy
// compatibility only; it is not collision-resistant.

using System.Globalization;
using System.Security.Cryptography;
using System.Text;

namespace CosmoDev.Hash;

/// <summary>Pure logic of the CosmoDev `hash` tool.</summary>
public static class HashTool
{
    /// <summary>Canonical algorithm names. The spellings match the TypeScript
    /// union so the same string works across every port.</summary>
    public const string Sha1 = "SHA-1";
    public const string Sha256 = "SHA-256"; // default algorithm
    public const string Sha384 = "SHA-384";
    public const string Sha512 = "SHA-512";

    /// <summary>The algorithm selected when a caller passes an empty name —
    /// the optional-parameter default the TypeScript reference declares.</summary>
    public const string DefaultAlgorithm = Sha256;

    /// <summary>Every supported algorithm, in the order the React island
    /// renders them.</summary>
    public static IReadOnlyList<string> Algorithms { get; } = [Sha1, Sha256, Sha384, Sha512];

    /// <summary>
    /// Compute the named digest of <paramref name="text"/> and return it as
    /// lowercase hex. The text is UTF-8 encoded before hashing, so the result
    /// is correct for arbitrary Unicode (emoji, accents, CJK). An empty
    /// <paramref name="algorithm"/> selects SHA-256; an unknown name throws
    /// <see cref="ArgumentException"/>.
    /// </summary>
    public static string Digest(string text, string? algorithm = null)
    {
        string name = string.IsNullOrEmpty(algorithm) ? DefaultAlgorithm : algorithm;

        // Each arm fixes the implementation type at compile time. The
        // HashData one-shots allocate no hasher state and dispose nothing.
        byte[] digest = name switch
        {
            Sha1 => SHA1.HashData(Encoding.UTF8.GetBytes(text)),
            Sha256 => SHA256.HashData(Encoding.UTF8.GetBytes(text)),
            Sha384 => SHA384.HashData(Encoding.UTF8.GetBytes(text)),
            Sha512 => SHA512.HashData(Encoding.UTF8.GetBytes(text)),
            _ => throw new ArgumentException($"Unsupported hash algorithm: {name}", nameof(algorithm)),
        };

        // ToHexString is uppercase; the reference emits lowercase.
        return Convert.ToHexString(digest).ToLowerInvariant();
    }

    /// <summary>
    /// Compute every supported digest of <paramref name="text"/> — the C#
    /// shape of the Record the React island renders. Each hash is computed
    /// independently. The dictionary preserves the canonical algorithm order.
    /// </summary>
    public static IReadOnlyDictionary<string, string> HashAll(string text)
    {
        Dictionary<string, string> all = new(capacity: Algorithms.Count);
        foreach (string algorithm in Algorithms)
        {
            all[algorithm] = Digest(text, algorithm);
        }
        return all;
    }
}

Also available in 13 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 →