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 →