Hash Generator — Java 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 Java 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: Java 17 (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 java.security.MessageDigest — the JDK's vetted
// provider set (typically backed by OpenSSL through the SunCryptoAPI native
// patches). All four names are standard JCA algorithm strings, so no external
// libraries are needed. Hex encoding uses Character.forDigit — no formatter
// and no third-party Hex class.
//
// Behavior mirrors the TypeScript reference: UTF-8 input, lowercase hex
// output, and rejection of unknown algorithm names. MessageDigest signals an
// unknown name with the checked NoSuchAlgorithmException; the port translates
// that into IllegalArgumentException — the Java standing of the ValueError the
// Python port raises — because from this API's viewpoint a bad name is a
// caller bug, not a recoverable environment failure. SHA-1 is offered for
// legacy compatibility only; it is not collision-resistant.
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/** Pure logic of the CosmoDev {@code hash} tool. */
public final class HashTool {
/** Canonical algorithm names. The spellings match the TypeScript union so
* the same string works across every port. */
public static final String SHA1 = "SHA-1";
public static final String SHA256 = "SHA-256"; // default algorithm
public static final String SHA384 = "SHA-384";
public static final String SHA512 = "SHA-512";
/** The algorithm selected when a caller passes null or "" — the
* optional-parameter default the TypeScript reference declares. */
public static final String DEFAULT_ALGORITHM = SHA256;
/** Every supported algorithm, in the order the React island renders them. */
public static final List<String> ALGORITHMS = List.of(SHA1, SHA256, SHA384, SHA512);
private HashTool() {
// Static utility — no instances.
}
/**
* Computes the named digest of {@code text} and returns it as lowercase
* hex.
*
* <p>The text is UTF-8 encoded before hashing, so the result is correct
* for arbitrary Unicode (emoji, accents, CJK). A null or empty
* {@code algorithm} selects SHA-256. An unknown name throws
* {@link IllegalArgumentException}.
*/
public static String digest(String text, String algorithm) {
String name = (algorithm == null || algorithm.isEmpty()) ? DEFAULT_ALGORITHM : algorithm;
// The supported set is fixed by the tool. Checking it here — before
// getInstance — rejects unknown names with IllegalArgumentException
// (the Python port's ValueError) and stops the JCA from accepting
// digests the tool does not offer: "MD5" passes the provider lookup
// but is outside this API's contract.
if (!ALGORITHMS.contains(name)) {
throw new IllegalArgumentException("Unsupported hash algorithm: " + name);
}
MessageDigest md;
try {
// A fresh instance per call: MessageDigest is stateful, and
// reusing one across digests would need reset() bookkeeping.
md = MessageDigest.getInstance(name);
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException("Unsupported hash algorithm: " + name, e);
}
byte[] hash = md.digest(text.getBytes(StandardCharsets.UTF_8));
// Two hex digits per byte, lowercase — Character.forDigit already
// yields lowercase for bases 16 and below.
StringBuilder hex = new StringBuilder(hash.length * 2);
for (byte b : hash) {
hex.append(Character.forDigit((b >> 4) & 0xf, 16));
hex.append(Character.forDigit(b & 0xf, 16));
}
return hex.toString();
}
/**
* Computes every supported digest of {@code text} — the Java shape of the
* Record the React island renders. Each hash is computed independently.
* The LinkedHashMap preserves the canonical algorithm order.
*/
public static Map<String, String> hashAll(String text) {
Map<String, String> all = new LinkedHashMap<>();
for (String algorithm : ALGORITHMS) {
all.put(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 →