<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Web-Crypto | Toolbox Guides &amp; Articles</title><link>https://blog.toolbox.vishnudigital.com/tags/web-crypto/</link><atom:link href="https://blog.toolbox.vishnudigital.com/tags/web-crypto/index.xml" rel="self" type="application/rss+xml"/><description>Web-Crypto</description><generator>HugoBlox Kit (https://hugoblox.com)</generator><language>en-us</language><lastBuildDate>Sun, 06 Sep 2026 00:00:00 +0000</lastBuildDate><image><url>https://blog.toolbox.vishnudigital.com/media/icon.svg</url><title>Web-Crypto</title><link>https://blog.toolbox.vishnudigital.com/tags/web-crypto/</link></image><item><title>RSA vs ECC Keypairs: Key Sizes, PEM Formats, and Choosing a Curve in 2026</title><link>https://blog.toolbox.vishnudigital.com/rsa-vs-ecc-keypair-generation-pem-guide/</link><pubDate>Sun, 06 Sep 2026 00:00:00 +0000</pubDate><guid>https://blog.toolbox.vishnudigital.com/rsa-vs-ecc-keypair-generation-pem-guide/</guid><description>
&lt;aside class="comic-bubble not-prose my-8 p-6 rounded-2xl border-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#fdfbf7] dark:bg-[#28201a] shadow-[4px_4px_0px_#2c221a] dark:shadow-[4px_4px_0px_#14100d]" aria-label="AEO Quick Answer &amp; Specification Dossier"&gt;
&lt;div class="flex items-center justify-between gap-3 mb-3"&gt;
&lt;div class="flex items-center gap-2"&gt;
&lt;span class="comic-stamp bg-amber-600 text-white px-2.5 py-0.5 rounded text-[11px] font-black tracking-wider"&gt;QUICK ANSWER&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold text-[#2c221a]/70 dark:text-[#ede6db]/70"&gt;RFC SPECIFICATION SUMMARY&lt;/span&gt;
&lt;/div&gt;
&lt;span class="hidden sm:inline-flex items-center gap-1.5 text-[11px] font-bold font-mono px-2 py-0.5 rounded border border-emerald-700 dark:border-emerald-500 bg-emerald-100 dark:bg-emerald-950 text-emerald-900 dark:text-emerald-200"&gt;
&lt;span class="inline-block w-1.5 h-1.5 rounded-full bg-emerald-600 dark:bg-emerald-400"&gt;&lt;/span&gt; 100% Client-Side
&lt;/span&gt;
&lt;/div&gt;
&lt;p class="text-base sm:text-lg text-[#2c221a] dark:text-[#ede6db] leading-relaxed font-semibold mb-4"&gt;
RSA and ECC are both asymmetric keypair systems, but they buy security differently. RSA-2048 gives about 112 bits of security strength and RSA-3072 about 128 bits, while NIST P-256 reaches the same 128 bits with a 256-bit key, producing far smaller keys and faster signing. Private keys are normally exported as PKCS#8 PEM (BEGIN PRIVATE KEY) and public keys as SPKI PEM (BEGIN PUBLIC KEY), both being Base64-wrapped DER. Choose ECDSA P-256 for new signing work, RSA-2048 or RSA-3072 where legacy interoperability is required, and keep the algorithm configurable for post-quantum migration.
&lt;/p&gt;
&lt;div class="flex flex-wrap gap-2 text-xs font-mono font-bold mt-4 pt-3 border-t border-[#ded4c3] dark:border-[#3b332c]"&gt;
&lt;span class="px-2.5 py-1 rounded bg-[#ede6db] dark:bg-[#382e26] text-[#2c221a] dark:text-[#ede6db] border border-[#ded4c3] dark:border-[#4a3e35]"&gt;Difficulty: Advanced&lt;/span&gt;
&lt;span class="px-2.5 py-1 rounded bg-[#ede6db] dark:bg-[#382e26] text-[#2c221a] dark:text-[#ede6db] border border-[#ded4c3] dark:border-[#4a3e35]"&gt;Time: 8 Mins&lt;/span&gt;
&lt;span class="px-2.5 py-1 rounded bg-[#ede6db] dark:bg-[#382e26] text-[#2c221a] dark:text-[#ede6db] border border-[#ded4c3] dark:border-[#4a3e35]"&gt;Privacy: 100% Client-Side RAM&lt;/span&gt;
&lt;span class="px-2.5 py-1 rounded bg-[#ede6db] dark:bg-[#382e26] text-[#2c221a] dark:text-[#ede6db] border border-[#ded4c3] dark:border-[#4a3e35]"&gt;Standard: RFC 8017 / RFC 5280 / FIPS 186-5&lt;/span&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;div class="tool-embed-container comic-panel not-prose my-10 rounded-2xl border-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#fdfbf7] dark:bg-[#28201a] shadow-[4px_4px_0px_#2c221a] dark:shadow-[4px_4px_0px_#14100d] overflow-hidden" id="embed-rsa-keys-1788851897578670000-box" role="region" aria-label="Interactive Tool Workbench"&gt;
&lt;div class="comic-halftone p-4 sm:p-5 border-b-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#f5efe4] dark:bg-[#211a14] flex flex-wrap items-center justify-between gap-3"&gt;
&lt;div class="flex items-center gap-2.5 flex-wrap min-w-0"&gt;
&lt;span class="comic-stamp bg-amber-600 text-white px-2.5 py-0.5 rounded text-[10px] font-black tracking-wider uppercase"&gt;
Interactive Workbench
&lt;/span&gt;
&lt;span class="inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full text-[10px] font-mono font-bold bg-emerald-100 text-emerald-800 dark:bg-emerald-950/60 dark:text-emerald-300 border border-emerald-300 dark:border-emerald-800 shrink-0"&gt;
&lt;span class="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-pulse"&gt;&lt;/span&gt;
&lt;span&gt;LIVE&lt;/span&gt;
&lt;/span&gt;
&lt;h3 class="text-base sm:text-lg font-extrabold text-[#2c221a] dark:text-[#ede6db] tracking-tight truncate m-0"&gt;
RSA vs ECC Keypairs: Key Sizes, PEM Formats, and Choosing a Curve in 2026
&lt;/h3&gt;
&lt;/div&gt;
&lt;div class="flex items-center gap-2 shrink-0"&gt;
&lt;a href="https://toolbox.vishnudigital.com/rsa-keys" target="_blank" rel="noopener noreferrer" class="comic-btn-secondary !py-1 !px-3 !text-xs font-mono font-bold flex items-center gap-1.5 shadow-[2px_2px_0px_#2c221a] dark:shadow-[2px_2px_0px_#14100d] hover:translate-x-[-1px] hover:translate-y-[-1px] transition-all" title="Open full utility in new window"&gt;
&lt;span&gt;Open Fullscreen ↗&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="relative w-full overflow-hidden bg-[#fdfbf7] dark:bg-[#1a1410]" style="min-height: 420px;"&gt;
&lt;div id="embed-rsa-keys-1788851897578670000-skeleton" class="absolute inset-0 flex flex-col items-center justify-center p-8 bg-[#fdfbf7] dark:bg-[#1e1814] z-10 transition-opacity duration-300"&gt;
&lt;div class="flex items-center gap-3 p-4 rounded-xl border-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#f5efe4] dark:bg-[#28201a] shadow-[2px_2px_0px_#2c221a] dark:shadow-[2px_2px_0px_#14100d] max-w-sm w-full"&gt;
&lt;div class="w-8 h-8 rounded-lg bg-amber-500/20 flex items-center justify-center shrink-0"&gt;
&lt;svg class="w-5 h-5 text-amber-600 animate-spin" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"&gt;
&lt;circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor"&gt;&lt;/circle&gt;
&lt;path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;div class="min-w-0 flex-1"&gt;
&lt;div class="text-xs font-bold text-[#2c221a] dark:text-[#ede6db] truncate"&gt;Initializing Workbench...&lt;/div&gt;
&lt;div class="text-[10px] font-mono text-[#2c221a]/60 dark:text-[#ede6db]/60"&gt;100% Client-Side RAM Sandbox&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;iframe
id="embed-rsa-keys-1788851897578670000-frame"
data-base-src="https://toolbox.vishnudigital.com/rsa-keys?embed=true"
src="about:blank"
title="RSA vs ECC Keypairs: Key Sizes, PEM Formats, and Choosing a Curve in 2026 – Free Online Utility"
class="w-full border-0 block opacity-0 transition-opacity duration-300"
style="height: 620px; min-height: 420px;"
loading="lazy"
allow="clipboard-read; clipboard-write; web-share"
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-downloads"&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;div class="p-3 sm:px-5 border-t border-[#ded4c3] dark:border-[#3b332c] bg-[#f5efe4]/80 dark:bg-[#211a14]/80 flex flex-wrap items-center justify-between gap-3 text-xs font-mono"&gt;
&lt;div class="flex items-center gap-2 text-[#2c221a]/70 dark:text-[#ede6db]/70"&gt;
&lt;span class="text-emerald-600 dark:text-emerald-400 font-bold"&gt;🔒 Private Execution:&lt;/span&gt;
&lt;span class="hidden sm:inline"&gt;Computations run in local browser memory. Zero server uploads.&lt;/span&gt;
&lt;span class="sm:hidden"&gt;Zero server uploads.&lt;/span&gt;
&lt;/div&gt;
&lt;div class="flex items-center gap-1.5 shrink-0"&gt;
&lt;a href="https://toolbox.vishnudigital.com/rsa-keys" target="_blank" rel="noopener noreferrer" class="font-bold text-amber-700 dark:text-amber-400 hover:text-amber-800 dark:hover:text-amber-300 hover:underline"&gt;
Launch Fullscreen →
&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;script&gt;
(function() {
const containerId = "embed-rsa-keys-1788851897578670000";
const frame = document.getElementById(containerId + "-frame");
const skeleton = document.getElementById(containerId + "-skeleton");
if (!frame) return;
function getCurrentTheme() {
return document.documentElement.classList.contains("dark") ? "dark" : "light";
}
function resolveSrc() {
const baseSrc = frame.getAttribute("data-base-src");
if (!baseSrc) return "";
const theme = getCurrentTheme();
return baseSrc + (baseSrc.includes("?") ? "&amp;" : "?") + "theme=" + theme;
}
function loadIframe() {
if (frame.getAttribute("src") !== "about:blank") return;
const fullSrc = resolveSrc();
frame.src = fullSrc;
frame.onload = function() {
if (skeleton) {
skeleton.classList.add("opacity-0");
setTimeout(function() { skeleton.style.display = "none"; }, 300);
}
frame.classList.remove("opacity-0");
frame.classList.add("opacity-100");
syncThemeToIframe();
};
}
function syncThemeToIframe() {
if (!frame || !frame.contentWindow) return;
try {
frame.contentWindow.postMessage({
type: "TOOLBOX_THEME_CHANGE",
theme: getCurrentTheme()
}, "*");
} catch(e) {}
}
if ("IntersectionObserver" in window) {
const observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
loadIframe();
observer.disconnect();
}
});
}, { rootMargin: "250px" });
observer.observe(frame);
} else {
loadIframe();
}
window.addEventListener("message", function(event) {
if (
event.data &amp;&amp;
typeof event.data === "object" &amp;&amp;
event.data.type === "TOOLBOX_RESIZE" &amp;&amp;
event.data.height
) {
if (event.source === frame.contentWindow) {
const measured = Math.max(event.data.height + 20, 420);
frame.style.height = measured + "px";
}
}
});
const themeObserver = new MutationObserver(function(mutations) {
mutations.forEach(function(m) {
if (m.attributeName === "class") {
syncThemeToIframe();
}
});
});
themeObserver.observe(document.documentElement, { attributes: true });
document.querySelectorAll(".theme-toggle").forEach(function(btn) {
btn.addEventListener("click", function() {
setTimeout(syncThemeToIframe, 50);
});
});
})();
&lt;/script&gt;
&lt;div class="tool-hero-cta not-prose my-10 p-6 sm:p-7 rounded-2xl border-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#fdfbf7] dark:bg-[#28201a] shadow-[4px_4px_0px_#2c221a] dark:shadow-[4px_4px_0px_#14100d] flex flex-col md:flex-row items-start md:items-center justify-between gap-6 transition-all" role="complementary" aria-label="Interactive Companion Tool"&gt;
&lt;div class="space-y-2 max-w-xl"&gt;
&lt;div class="flex items-center gap-2"&gt;
&lt;span class="comic-stamp bg-amber-600 text-white px-2.5 py-0.5 rounded text-[10px] font-black tracking-wider uppercase"&gt;
Free In-Browser Tool
&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold text-stone-500 dark:text-stone-400"&gt;TOOLBOX UTILITY&lt;/span&gt;
&lt;/div&gt;
&lt;h3 class="text-xl font-extrabold text-[#2c221a] dark:text-[#ede6db] tracking-tight m-0"&gt;
RSA &amp;amp; ECC Keypair Generator
&lt;/h3&gt;
&lt;p class="text-sm text-stone-600 dark:text-stone-300 leading-relaxed font-medium m-0"&gt;
Generate RSA keypairs in PKCS#8 and SPKI PEM using the browser&amp;#39;s own Web Crypto implementation. Private key material never leaves local memory.
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="shrink-0 w-full md:w-auto"&gt;
&lt;a href="https://toolbox.vishnudigital.com/rsa-keys" class="comic-btn-primary w-full md:w-auto text-center" &gt;
Open Air-Gapped Keypair Generator →
&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="two-ways-to-build-a-trapdoor"&gt;Two Ways to Build a Trapdoor&lt;/h2&gt;
&lt;p&gt;Asymmetric cryptography needs a function that is easy forwards and infeasible backwards. RSA and ECC pick different hard problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RSA&lt;/strong&gt; (RFC 8017) relies on the difficulty of factoring a modulus &lt;code&gt;n = p × q&lt;/code&gt; into its two large primes. Public key: &lt;code&gt;(n, e)&lt;/code&gt;. Private key: &lt;code&gt;(n, d)&lt;/code&gt; plus the CRT parameters that make decryption fast.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ECC&lt;/strong&gt; relies on the elliptic curve discrete logarithm problem: given points &lt;code&gt;G&lt;/code&gt; and &lt;code&gt;Q = kG&lt;/code&gt; on a curve, recover the scalar &lt;code&gt;k&lt;/code&gt;. Public key: the point &lt;code&gt;Q&lt;/code&gt;. Private key: the scalar &lt;code&gt;k&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The consequence is not academic. The best classical attack on RSA — the general number field sieve — runs in sub-exponential time, so RSA key sizes must grow steeply to keep pace with hardware. The best generic attack on a well-chosen curve is Pollard&amp;rsquo;s rho at roughly the square root of the group order, so ECC key sizes grow linearly with security. That single difference explains the entire comparison table below.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What you get from this guide:&lt;/strong&gt; a defensible key-size choice, the ability to read any PEM file you are handed, and a clear view of what post-quantum migration does and does not demand of you today.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="security-strength-the-only-fair-comparison"&gt;Security Strength: The Only Fair Comparison&lt;/h2&gt;
&lt;p&gt;Key length is meaningless across algorithm families. The comparable unit is &lt;strong&gt;security strength in bits&lt;/strong&gt;, expressed as the equivalent symmetric key.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Security strength&lt;/th&gt;
&lt;th&gt;RSA modulus&lt;/th&gt;
&lt;th&gt;Elliptic curve&lt;/th&gt;
&lt;th&gt;Symmetric equivalent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;112 bits&lt;/td&gt;
&lt;td&gt;RSA-2048&lt;/td&gt;
&lt;td&gt;P-224&lt;/td&gt;
&lt;td&gt;3TDEA (legacy)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;128 bits&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;RSA-3072&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;P-256 (secp256r1)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;AES-128&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;192 bits&lt;/td&gt;
&lt;td&gt;RSA-7680&lt;/td&gt;
&lt;td&gt;P-384 (secp384r1)&lt;/td&gt;
&lt;td&gt;AES-192&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;256 bits&lt;/td&gt;
&lt;td&gt;RSA-15360&lt;/td&gt;
&lt;td&gt;P-521 (secp521r1)&lt;/td&gt;
&lt;td&gt;AES-256&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Two practical readings of this table:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;RSA-2048 is the current floor, not a target.&lt;/strong&gt; It sits at 112-bit strength, which NIST&amp;rsquo;s transition guidance schedules for phase-out by 2030 and disallowance by 2035. New long-lived keys should be RSA-3072 or an elliptic curve.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RSA-4096 is not the obvious upgrade.&lt;/strong&gt; It buys roughly 140 bits of strength for four to eight times the signing cost of RSA-3072. P-256 reaches 128 bits with a 32-byte private scalar and signs an order of magnitude faster.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="performance-shape"&gt;Performance shape&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;RSA-2048&lt;/th&gt;
&lt;th&gt;ECDSA P-256&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Key generation&lt;/td&gt;
&lt;td&gt;Slow (prime search)&lt;/td&gt;
&lt;td&gt;Fast (one scalar multiply)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sign / decrypt&lt;/td&gt;
&lt;td&gt;Slow (private exponent)&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verify / encrypt&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Very fast&lt;/strong&gt; (small &lt;code&gt;e = 65537&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Public key size&lt;/td&gt;
&lt;td&gt;~294 bytes (SPKI DER)&lt;/td&gt;
&lt;td&gt;~91 bytes (SPKI DER)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Signature size&lt;/td&gt;
&lt;td&gt;256 bytes&lt;/td&gt;
&lt;td&gt;~64-72 bytes (DER)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;RSA&amp;rsquo;s asymmetry — cheap verification, expensive signing — is why it survived so long in TLS server certificates, where a server signs once per handshake but clients verify constantly. It is also why RSA keygen in a browser can take a visible second at 4096 bits while an ECDSA keypair appears instantly.&lt;/p&gt;
&lt;hr&gt;
&lt;div class="in-article-ad-wrapper not-prose my-8 p-3 sm:p-4 rounded-xl border-2 border-stone-900/40 dark:border-stone-400/40 bg-[#fdfbf7] dark:bg-[#211c18] shadow-[3px_3px_0px_rgba(41,30,20,0.3)] dark:shadow-[3px_3px_0px_rgba(242,237,228,0.2)] overflow-hidden"&gt;
&lt;div class="flex items-center justify-between mb-2 border-b border-stone-200 dark:border-stone-800 pb-1"&gt;
&lt;span class="text-[10px] font-mono font-bold uppercase tracking-widest text-stone-500 dark:text-stone-400"&gt;Advertisement&lt;/span&gt;
&lt;span class="text-[9px] font-mono uppercase px-1.5 py-0.5 rounded bg-amber-100 dark:bg-amber-950 text-amber-800 dark:text-amber-300"&gt;Sponsored&lt;/span&gt;
&lt;/div&gt;
&lt;div class="w-full flex justify-center items-center overflow-hidden min-h-[250px]"&gt;
&lt;ins class="adsbygoogle"
style="display:block; text-align:center; min-height:250px; width:100%;"
data-ad-layout="in-article"
data-ad-format="fluid"
data-ad-client="ca-pub-5474548764059850"
&gt;&lt;/ins&gt;
&lt;script&gt;
(adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id="reading-a-pem-file"&gt;Reading a PEM File&lt;/h2&gt;
&lt;p&gt;A PEM file is Base64-encoded &lt;strong&gt;DER&lt;/strong&gt; (Distinguished Encoding Rules), the canonical binary serialisation of an ASN.1 structure, wrapped in armour lines. The header tells you exactly which structure is inside.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Header line&lt;/th&gt;
&lt;th&gt;Structure&lt;/th&gt;
&lt;th&gt;Contains&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-----BEGIN PUBLIC KEY-----&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;SubjectPublicKeyInfo (RFC 5280)&lt;/td&gt;
&lt;td&gt;Algorithm identifier + public key bits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-----BEGIN PRIVATE KEY-----&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PKCS#8 PrivateKeyInfo (RFC 5958)&lt;/td&gt;
&lt;td&gt;Algorithm identifier + private key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-----BEGIN ENCRYPTED PRIVATE KEY-----&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PKCS#8 EncryptedPrivateKeyInfo&lt;/td&gt;
&lt;td&gt;Passphrase-wrapped private key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-----BEGIN RSA PRIVATE KEY-----&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PKCS#1 RSAPrivateKey (RFC 8017)&lt;/td&gt;
&lt;td&gt;RSA parameters only, &lt;strong&gt;no&lt;/strong&gt; algorithm identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-----BEGIN EC PRIVATE KEY-----&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;SEC1 ECPrivateKey (RFC 5915)&lt;/td&gt;
&lt;td&gt;Curve parameters + scalar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-----BEGIN CERTIFICATE-----&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;X.509 Certificate&lt;/td&gt;
&lt;td&gt;A signed public key — see the
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The modern, algorithm-agnostic pair is &lt;strong&gt;PKCS#8 for private&lt;/strong&gt; and &lt;strong&gt;SPKI for public&lt;/strong&gt;; those are the two formats the Web Crypto API exports. The older PKCS#1 and SEC1 forms are algorithm-specific, which is why tooling has converged on PKCS#8.&lt;/p&gt;
&lt;h3 id="generating-a-keypair-with-web-crypto"&gt;Generating a keypair with Web Crypto&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// RSA-3072 signing keypair, exported as PKCS#8 + SPKI PEM.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;RSASSA-PKCS1-v1_5&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or &amp;#34;RSA-PSS&amp;#34; / &amp;#34;RSA-OAEP&amp;#34; for encryption
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;modulusLength&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3072&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;publicExponent&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mh"&gt;0x01&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x01&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="c1"&gt;// 65537
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;SHA-256&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// extractable
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;sign&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;verify&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toPem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;der&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;b64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;btoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromCharCode&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;der&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sb"&gt;`-----BEGIN &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-----\n&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;b64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/.{1,64}/g&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;\n-----END &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-----`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;privatePem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;toPem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exportKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pkcs8&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;PRIVATE KEY&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publicPem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;toPem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exportKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;spki&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;PUBLIC KEY&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Three details that trip people up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;publicExponent&lt;/code&gt; is 65537&lt;/strong&gt; (&lt;code&gt;0x010001&lt;/code&gt;). It is a Fermat prime with only two set bits, making verification fast; smaller exponents such as 3 have historically enabled padding attacks in badly implemented verifiers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Base64 lines wrap at 64 characters.&lt;/strong&gt; Some strict parsers reject unwrapped single-line PEM.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;extractable: true&lt;/code&gt; is required to export at all.&lt;/strong&gt; Set it to &lt;code&gt;false&lt;/code&gt; for keys that should stay inside the browser&amp;rsquo;s key store.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="the-ssh-format-gap"&gt;The SSH format gap&lt;/h3&gt;
&lt;p&gt;A &lt;code&gt;-----BEGIN PUBLIC KEY-----&lt;/code&gt; block cannot be pasted into &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt;. OpenSSH uses its own wire encoding — an algorithm name, then length-prefixed fields, Base64-encoded onto one line:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SPKI PEM -&amp;gt; OpenSSH public key line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh-keygen -i -m PKCS8 -f public.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PKCS#8 private key -&amp;gt; OpenSSH private key file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh-keygen -p -m RFC4716 -f id_rsa
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Also worth knowing: OpenSSH&amp;rsquo;s recommended key type today is &lt;strong&gt;Ed25519&lt;/strong&gt;, and the Web Crypto &lt;code&gt;generateKey&lt;/code&gt; algorithms for RSA and ECDSA do not produce it. Generate Ed25519 keys with &lt;code&gt;ssh-keygen -t ed25519&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="choosing-an-algorithm-in-2026"&gt;Choosing an Algorithm in 2026&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use case&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;th&gt;Reasoning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;New TLS server certificate&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ECDSA P-256&lt;/strong&gt;, RSA-2048/3072 as fallback&lt;/td&gt;
&lt;td&gt;Smaller handshake; universally supported by browsers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JWT signing&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ES256&lt;/strong&gt; (ECDSA P-256) or &lt;strong&gt;RS256&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ES256 gives shorter tokens; see the
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSH user key&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Ed25519&lt;/strong&gt; via &lt;code&gt;ssh-keygen&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Small, fast, no curve-parameter footguns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Legacy enterprise PKI&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;RSA-3072&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Broadest hardware and appliance support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Encrypting data directly&lt;/td&gt;
&lt;td&gt;Neither — use hybrid&lt;/td&gt;
&lt;td&gt;Encrypt with
, wrap the AES key with RSA-OAEP or ECDH&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="the-rsa-oaep-size-limit-and-why-hybrid-encryption-exists"&gt;The RSA-OAEP Size Limit and Why Hybrid Encryption Exists&lt;/h2&gt;
&lt;p&gt;RSA does not encrypt streams. It encrypts one integer smaller than the modulus. With &lt;strong&gt;OAEP padding&lt;/strong&gt; (RFC 8017) the usable plaintext is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;max plaintext bytes = k - 2 * hLen - 2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;k = modulus size in bytes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hLen = hash output size in bytes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key size&lt;/th&gt;
&lt;th&gt;&lt;code&gt;k&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;OAEP hash&lt;/th&gt;
&lt;th&gt;Maximum plaintext&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2048-bit&lt;/td&gt;
&lt;td&gt;256 bytes&lt;/td&gt;
&lt;td&gt;SHA-1 (20)&lt;/td&gt;
&lt;td&gt;214 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2048-bit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;256 bytes&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SHA-256 (32)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;190 bytes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3072-bit&lt;/td&gt;
&lt;td&gt;384 bytes&lt;/td&gt;
&lt;td&gt;SHA-256 (32)&lt;/td&gt;
&lt;td&gt;318 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;4096-bit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;512 bytes&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SHA-256 (32)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;446 bytes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;190 bytes will not hold a document, a database row, or a session payload — which is why real systems use &lt;strong&gt;hybrid encryption&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Generate a random &lt;strong&gt;AES-256&lt;/strong&gt; content key.&lt;/li&gt;
&lt;li&gt;Encrypt the payload with &lt;strong&gt;AES-256-GCM&lt;/strong&gt; — fast, streaming, authenticated.&lt;/li&gt;
&lt;li&gt;Encrypt only the 32-byte AES key with &lt;strong&gt;RSA-OAEP&lt;/strong&gt; (or derive it with ECDH).&lt;/li&gt;
&lt;li&gt;Ship the wrapped key alongside the ciphertext.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That is the structure inside TLS, JWE, S/MIME, and PGP: the asymmetric half transports a key, the symmetric half does the work. See the
for the symmetric side.&lt;/p&gt;
&lt;h3 id="signature-padding-pss-or-pkcs1-v15"&gt;Signature padding: PSS or PKCS#1 v1.5?&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scheme&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Use when&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RSA-PSS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Recommended (RFC 8017)&lt;/td&gt;
&lt;td&gt;Any new system — randomised padding with a formal security proof&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RSASSA-PKCS1-v1_5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Legacy but ubiquitous&lt;/td&gt;
&lt;td&gt;Interoperating with existing TLS certificates and JWT &lt;code&gt;RS256&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Raw RSA, no padding&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Never&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Textbook RSA is deterministic and trivially malleable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Never encrypt bulk data with RSA.&lt;/strong&gt; RSA-OAEP can encrypt at most a few hundred bytes for a given modulus. The correct pattern is hybrid encryption: generate a random symmetric key, encrypt the payload with AES-GCM, and encrypt only that symmetric key with the recipient&amp;rsquo;s public key.&lt;/p&gt;
&lt;h3 id="where-post-quantum-stands"&gt;Where post-quantum stands&lt;/h3&gt;
&lt;p&gt;NIST finalised three post-quantum standards in August 2024: &lt;strong&gt;FIPS 203 (ML-KEM)&lt;/strong&gt; for key encapsulation, &lt;strong&gt;FIPS 204 (ML-DSA)&lt;/strong&gt; and &lt;strong&gt;FIPS 205 (SLH-DSA)&lt;/strong&gt; for signatures. &lt;strong&gt;FIPS 206 (FN-DSA)&lt;/strong&gt; remains a draft as of 2026. NIST&amp;rsquo;s transition schedule phases out 112-bit-strength classical algorithms by 2030 and disallows them from 2035; NSA&amp;rsquo;s CNSA 2.0 sets 2030 for national security systems.&lt;/p&gt;
&lt;p&gt;Shor&amp;rsquo;s algorithm on a sufficiently large quantum computer would factor RSA moduli efficiently, breaking RSA at every key size, and would solve elliptic curve discrete logarithms too. No such machine exists today, but ciphertext captured now can be stored for later decryption — the &lt;em&gt;harvest now, decrypt later&lt;/em&gt; problem. The deployed transition path is &lt;strong&gt;hybrid&lt;/strong&gt;: combine a classical key exchange with ML-KEM so the session survives if either component fails.&lt;/p&gt;
&lt;p&gt;For an application team, the actionable version is short: do not rewrite your PKI this quarter, but stop hardcoding algorithm names, keep certificate lifetimes short so rotation is routine, and inventory where long-lived signatures and long-lived encrypted archives live — those are the assets exposed to &amp;ldquo;harvest now, decrypt later&amp;rdquo;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="step-by-step-generating-and-inspecting-keys-with-toolbox"&gt;Step-by-Step: Generating and Inspecting Keys with Toolbox&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Open the tool&lt;/strong&gt;: visit the
.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pick a modulus size&lt;/strong&gt;: 2048 for legacy interoperability, 3072 for a 128-bit strength target, 4096 only when a policy demands it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generate&lt;/strong&gt;: the browser&amp;rsquo;s Web Crypto implementation performs the prime search locally; nothing is sent over the network.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Copy both PEM blocks&lt;/strong&gt;: the PKCS#8 private key and the SPKI public key. Store the private key in a secret manager immediately — a key that has been in a clipboard buffer and then an email is not a secret.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verify the pair matches&lt;/strong&gt; before deploying:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl rsa -in private.pem -pubout &lt;span class="p"&gt;|&lt;/span&gt; diff - public.pem &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;pair OK&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl rsa -in private.pem -noout -text &lt;span class="p"&gt;|&lt;/span&gt; head -2 &lt;span class="c1"&gt;# confirms modulus size&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Outcome:&lt;/strong&gt; a correctly encoded, verified keypair for local development, signing tests, or PKI experiments — generated without pasting a private key into a remote web service.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Related guides:&lt;/strong&gt;
·
·
&lt;/p&gt;
&lt;section class="faqs-container not-prose my-12 border-t-2 border-stone-200 dark:border-stone-800 pt-8" aria-label="Frequently Asked Questions"&gt;
&lt;div class="flex items-center gap-2 mb-6"&gt;
&lt;span class="comic-stamp bg-amber-600 text-white px-2 py-0.5 rounded text-[10px] font-black tracking-wider"&gt;FAQ&lt;/span&gt;
&lt;h2 class="text-2xl font-extrabold text-[#2c221a] dark:text-[#ede6db] tracking-tight m-0"&gt;
Frequently Asked Questions
&lt;/h2&gt;
&lt;/div&gt;
&lt;details name="faq" class="group border-2 border-[#2c221a] dark:border-[#ded4c3] rounded-xl p-4 bg-[#fdfbf7] dark:bg-[#28201a] shadow-[3px_3px_0px_#2c221a] dark:shadow-[3px_3px_0px_#14100d] mb-3 transition-all"&gt;
&lt;summary class="flex items-center justify-between cursor-pointer font-bold text-[#2c221a] dark:text-[#ede6db] select-none text-base"&gt;
&lt;span&gt;Is a 256-bit ECC key really as strong as a 3072-bit RSA key?&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold transition-transform duration-200 group-open:rotate-180 shrink-0 ml-2"&gt;▼&lt;/span&gt;
&lt;/summary&gt;
&lt;p class="mt-3 text-sm text-stone-600 dark:text-stone-300 leading-relaxed font-medium mb-0"&gt;
Against classical attacks, yes. Strength is measured in equivalent symmetric bits: RSA-2048 is about 112 bits, while RSA-3072 and NIST P-256 are both about 128 bits. RSA keys must grow much faster because the general number field sieve is sub-exponential, whereas the best generic attack on elliptic curve discrete logarithms takes square-root time in the group order.
&lt;/p&gt;
&lt;/details&gt;
&lt;details name="faq" class="group border-2 border-[#2c221a] dark:border-[#ded4c3] rounded-xl p-4 bg-[#fdfbf7] dark:bg-[#28201a] shadow-[3px_3px_0px_#2c221a] dark:shadow-[3px_3px_0px_#14100d] mb-3 transition-all"&gt;
&lt;summary class="flex items-center justify-between cursor-pointer font-bold text-[#2c221a] dark:text-[#ede6db] select-none text-base"&gt;
&lt;span&gt;What is the difference between PKCS#8 and SPKI PEM files?&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold transition-transform duration-200 group-open:rotate-180 shrink-0 ml-2"&gt;▼&lt;/span&gt;
&lt;/summary&gt;
&lt;p class="mt-3 text-sm text-stone-600 dark:text-stone-300 leading-relaxed font-medium mb-0"&gt;
PKCS#8 (RFC 5208 / RFC 5958) is the standard private-key container and starts with BEGIN PRIVATE KEY. SPKI, or SubjectPublicKeyInfo (RFC 5280), is the standard public-key container and starts with BEGIN PUBLIC KEY. Both are Base64-wrapped DER ASN.1. The older PKCS#1 form, BEGIN RSA PRIVATE KEY, carries only RSA parameters with no algorithm identifier.
&lt;/p&gt;
&lt;/details&gt;
&lt;details name="faq" class="group border-2 border-[#2c221a] dark:border-[#ded4c3] rounded-xl p-4 bg-[#fdfbf7] dark:bg-[#28201a] shadow-[3px_3px_0px_#2c221a] dark:shadow-[3px_3px_0px_#14100d] mb-3 transition-all"&gt;
&lt;summary class="flex items-center justify-between cursor-pointer font-bold text-[#2c221a] dark:text-[#ede6db] select-none text-base"&gt;
&lt;span&gt;Can I paste a generated PEM public key into authorized_keys for SSH?&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold transition-transform duration-200 group-open:rotate-180 shrink-0 ml-2"&gt;▼&lt;/span&gt;
&lt;/summary&gt;
&lt;p class="mt-3 text-sm text-stone-600 dark:text-stone-300 leading-relaxed font-medium mb-0"&gt;
No. OpenSSH uses its own one-line format beginning with ssh-rsa, ecdsa-sha2-nistp256, or ssh-ed25519 followed by Base64 of a length-prefixed structure. Convert a SPKI PEM with ssh-keygen -i -m PKCS8 -f public.pem. Note that Ed25519, OpenSSH&amp;#39;s preferred modern type, is not produced by the Web Crypto RSA or ECDSA algorithms.
&lt;/p&gt;
&lt;/details&gt;
&lt;details name="faq" class="group border-2 border-[#2c221a] dark:border-[#ded4c3] rounded-xl p-4 bg-[#fdfbf7] dark:bg-[#28201a] shadow-[3px_3px_0px_#2c221a] dark:shadow-[3px_3px_0px_#14100d] mb-3 transition-all"&gt;
&lt;summary class="flex items-center justify-between cursor-pointer font-bold text-[#2c221a] dark:text-[#ede6db] select-none text-base"&gt;
&lt;span&gt;Should I generate post-quantum keys instead of RSA or ECC today?&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold transition-transform duration-200 group-open:rotate-180 shrink-0 ml-2"&gt;▼&lt;/span&gt;
&lt;/summary&gt;
&lt;p class="mt-3 text-sm text-stone-600 dark:text-stone-300 leading-relaxed font-medium mb-0"&gt;
For most TLS, SSH, and signing work RSA and ECC remain the interoperable choice in 2026. NIST finalised ML-KEM (FIPS 203), ML-DSA (FIPS 204), and SLH-DSA (FIPS 205) in August 2024, while FN-DSA (FIPS 206) is still draft, and NIST schedules 112-bit-strength algorithms for phase-out by 2030 and disallowance by 2035. Prioritise crypto-agility: configurable algorithms, short certificate lifetimes, and an inventory of long-lived secrets.
&lt;/p&gt;
&lt;/details&gt;
&lt;/section&gt;</description></item><item><title>AES-256-GCM Authenticated Encryption: How to Secure Data in the Browser</title><link>https://blog.toolbox.vishnudigital.com/aes-256-gcm-authenticated-encryption-guide/</link><pubDate>Sat, 05 Sep 2026 00:00:00 +0000</pubDate><guid>https://blog.toolbox.vishnudigital.com/aes-256-gcm-authenticated-encryption-guide/</guid><description>
&lt;aside class="comic-bubble not-prose my-8 p-6 rounded-2xl border-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#fdfbf7] dark:bg-[#28201a] shadow-[4px_4px_0px_#2c221a] dark:shadow-[4px_4px_0px_#14100d]" aria-label="AEO Quick Answer &amp; Specification Dossier"&gt;
&lt;div class="flex items-center justify-between gap-3 mb-3"&gt;
&lt;div class="flex items-center gap-2"&gt;
&lt;span class="comic-stamp bg-amber-600 text-white px-2.5 py-0.5 rounded text-[11px] font-black tracking-wider"&gt;QUICK ANSWER&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold text-[#2c221a]/70 dark:text-[#ede6db]/70"&gt;RFC SPECIFICATION SUMMARY&lt;/span&gt;
&lt;/div&gt;
&lt;span class="hidden sm:inline-flex items-center gap-1.5 text-[11px] font-bold font-mono px-2 py-0.5 rounded border border-emerald-700 dark:border-emerald-500 bg-emerald-100 dark:bg-emerald-950 text-emerald-900 dark:text-emerald-200"&gt;
&lt;span class="inline-block w-1.5 h-1.5 rounded-full bg-emerald-600 dark:bg-emerald-400"&gt;&lt;/span&gt; 100% Client-Side
&lt;/span&gt;
&lt;/div&gt;
&lt;p class="text-base sm:text-lg text-[#2c221a] dark:text-[#ede6db] leading-relaxed font-semibold mb-4"&gt;
AES-256-GCM is an Authenticated Encryption with Associated Data (AEAD) cipher providing both data confidentiality and cryptographic tamper-proofing via a 128-bit authentication tag. In web browsers, it is executed via the native W3C Web Crypto API using a 256-bit symmetric key and a strictly unique 96-bit (12-byte) Initialization Vector (IV) generated with crypto.getRandomValues().
&lt;/p&gt;
&lt;div class="flex flex-wrap gap-2 text-xs font-mono font-bold mt-4 pt-3 border-t border-[#ded4c3] dark:border-[#3b332c]"&gt;
&lt;span class="px-2.5 py-1 rounded bg-[#ede6db] dark:bg-[#382e26] text-[#2c221a] dark:text-[#ede6db] border border-[#ded4c3] dark:border-[#4a3e35]"&gt;Difficulty: Advanced&lt;/span&gt;
&lt;span class="px-2.5 py-1 rounded bg-[#ede6db] dark:bg-[#382e26] text-[#2c221a] dark:text-[#ede6db] border border-[#ded4c3] dark:border-[#4a3e35]"&gt;Time: 7 Mins&lt;/span&gt;
&lt;span class="px-2.5 py-1 rounded bg-[#ede6db] dark:bg-[#382e26] text-[#2c221a] dark:text-[#ede6db] border border-[#ded4c3] dark:border-[#4a3e35]"&gt;Privacy: 100% Client-Side RAM&lt;/span&gt;
&lt;span class="px-2.5 py-1 rounded bg-[#ede6db] dark:bg-[#382e26] text-[#2c221a] dark:text-[#ede6db] border border-[#ded4c3] dark:border-[#4a3e35]"&gt;Standard: NIST FIPS 197 / SP 800-38D&lt;/span&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;div class="tool-hero-cta not-prose my-10 p-6 sm:p-7 rounded-2xl border-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#fdfbf7] dark:bg-[#28201a] shadow-[4px_4px_0px_#2c221a] dark:shadow-[4px_4px_0px_#14100d] flex flex-col md:flex-row items-start md:items-center justify-between gap-6 transition-all" role="complementary" aria-label="Interactive Companion Tool"&gt;
&lt;div class="space-y-2 max-w-xl"&gt;
&lt;div class="flex items-center gap-2"&gt;
&lt;span class="comic-stamp bg-amber-600 text-white px-2.5 py-0.5 rounded text-[10px] font-black tracking-wider uppercase"&gt;
Free In-Browser Tool
&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold text-stone-500 dark:text-stone-400"&gt;TOOLBOX UTILITY&lt;/span&gt;
&lt;/div&gt;
&lt;h3 class="text-xl font-extrabold text-[#2c221a] dark:text-[#ede6db] tracking-tight m-0"&gt;
AES Encryption &amp;amp; Decryption Utility
&lt;/h3&gt;
&lt;p class="text-sm text-stone-600 dark:text-stone-300 leading-relaxed font-medium m-0"&gt;
Encrypt and decrypt confidential text using AES-GCM or AES-CBC directly in your browser with hardware-accelerated Web Crypto API.
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="shrink-0 w-full md:w-auto"&gt;
&lt;a href="https://toolbox.vishnudigital.com/aes-encryption" class="comic-btn-primary w-full md:w-auto text-center" &gt;
Open AES-256 Web Crypto Tool →
&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="what-is-aes-and-how-does-modern-symmetric-cryptography-work"&gt;What Is AES and How Does Modern Symmetric Cryptography Work?&lt;/h2&gt;
&lt;p&gt;The &lt;strong&gt;Advanced Encryption Standard (AES)&lt;/strong&gt;, standardized by the US National Institute of Standards and Technology (&lt;strong&gt;NIST FIPS 197&lt;/strong&gt;), is the gold standard symmetric block cipher protecting modern internet communications (TLS 1.3), database storage encryption, disk volumes (BitLocker, FileVault), and zero-knowledge cloud applications.&lt;/p&gt;
&lt;p&gt;As a symmetric cipher, AES uses the &lt;strong&gt;same secret key&lt;/strong&gt; for both encryption and decryption. It operates on fixed &lt;strong&gt;128-bit (16-byte) blocks&lt;/strong&gt; of data through multiple rounds of substitution and permutation operations (SubBytes, ShiftRows, MixColumns, and AddRoundKey):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AES-128&lt;/strong&gt;: 10 rounds (128-bit key)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AES-192&lt;/strong&gt;: 12 rounds (192-bit key)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AES-256&lt;/strong&gt;: 14 rounds (256-bit key)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AES-256 provides a theoretical keyspace of $2^{256} \approx 1.15 \times 10^{77}$ combinations, rendering brute-force attacks physically impossible with classical computers.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="the-critical-role-of-block-cipher-modes"&gt;The Critical Role of Block Cipher Modes&lt;/h2&gt;
&lt;p&gt;A raw block cipher can only transform a single 16-byte block of plaintext. To encrypt arbitrary-length messages or streams, a &lt;strong&gt;mode of operation&lt;/strong&gt; must be employed. The choice of mode dictates whether your encryption is robust or fatally flawed.&lt;/p&gt;
&lt;h3 id="1-electronic-codebook-ecb--fatally-insecure"&gt;1. Electronic Codebook (ECB) — Fatally Insecure&lt;/h3&gt;
&lt;p&gt;In ECB mode, every 16-byte block is encrypted independently with the key. Identical plaintext blocks produce identical ciphertext blocks.&lt;/p&gt;
&lt;blockquote class="border-l-4 border-neutral-300 dark:border-neutral-600 pl-4 italic text-neutral-600 dark:text-neutral-400 my-6"&gt;
&lt;p&gt;⚠️ &lt;strong&gt;The ECB Penguin Problem:&lt;/strong&gt; Encrypting a bitmap image with ECB preserves the visual contours and structure of the image in the ciphertext. &lt;strong&gt;Never use ECB in production.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="2-cipher-block-chaining-cbc--legacy-malleability"&gt;2. Cipher Block Chaining (CBC) — Legacy Malleability&lt;/h3&gt;
&lt;p&gt;In CBC mode, each plaintext block is XORed with the preceding ciphertext block before encryption.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Requires an Initialization Vector (IV) for the first block.&lt;/li&gt;
&lt;li&gt;Requires padding (PKCS#7) to round the message up to an exact multiple of 16 bytes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vulnerability:&lt;/strong&gt; CBC only provides confidentiality, not integrity. Without a secondary MAC (Message Authentication Code), CBC is susceptible to &lt;strong&gt;bit-flipping attacks&lt;/strong&gt; and &lt;strong&gt;padding oracle attacks&lt;/strong&gt; (such as POODLE).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-galoiscounter-mode-gcm--the-gold-standard-aead"&gt;3. Galois/Counter Mode (GCM) — The Gold Standard AEAD&lt;/h3&gt;
&lt;p&gt;AES-GCM combines counter-mode encryption with universal hashing over a Galois field $\text{GF}(2^{128})$.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AEAD (Authenticated Encryption with Associated Data):&lt;/strong&gt; Simultaneously encrypts the payload and computes a 128-bit &lt;strong&gt;authentication tag (GMAC)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tamper Resistance:&lt;/strong&gt; If an attacker modifies even a single bit of the ciphertext or IV, decryption fails with an authentication error before any decrypted data is returned.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No Padding Needed:&lt;/strong&gt; Operates as a stream cipher over counter increments; plaintexts of arbitrary byte lengths are encrypted without padding.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High Performance:&lt;/strong&gt; Allows full pipelining and hardware acceleration via CPU instructions like Intel AES-NI and ARMv8 Cryptography.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="the-nonceiv-mandate-why-96-bit-iv-uniqueness-is-absolute"&gt;The Nonce/IV Mandate: Why 96-Bit IV Uniqueness Is Absolute&lt;/h2&gt;
&lt;p&gt;In AES-GCM, the &lt;strong&gt;Initialization Vector (IV)&lt;/strong&gt;, often referred to as a &lt;strong&gt;nonce&lt;/strong&gt; (number used once), initializes the counter function.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Counter Block 1 = IV (96 bits) || 0x00000001 (32 bits)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Counter Block 2 = IV (96 bits) || 0x00000002 (32 bits)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="the-catastrophic-two-time-pad-failure"&gt;The Catastrophic &amp;ldquo;Two-Time Pad&amp;rdquo; Failure&lt;/h3&gt;
&lt;p&gt;If the same key and IV pair is reused across two different plaintexts ($P_1$ and $P_2$):&lt;/p&gt;
$$C_1 = P_1 \oplus \text{Keystream}$$&lt;p&gt;
&lt;/p&gt;
$$C_2 = P_2 \oplus \text{Keystream}$$&lt;p&gt;
&lt;/p&gt;
$$C_1 \oplus C_2 = P_1 \oplus P_2$$&lt;p&gt;An eavesdropper XORs the two ciphertexts to cancel out the keystream entirely, revealing the direct XOR of the plaintexts. Furthermore, the Galois hash key $H$ can be recovered mathematically, allowing the attacker to forge valid authentication tags.&lt;/p&gt;
&lt;h3 id="standard-operating-rules-for-ivs"&gt;Standard Operating Rules for IVs:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Never reuse an IV with the same key.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IVs are not secret:&lt;/strong&gt; The IV is prepended in the clear to the ciphertext (e.g. &lt;code&gt;[12-byte IV] + [Ciphertext] + [16-byte Tag]&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Always use CSPRNG:&lt;/strong&gt; In web applications, generate IVs strictly with &lt;code&gt;window.crypto.getRandomValues(new Uint8Array(12))&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;div class="in-article-ad-wrapper not-prose my-8 p-3 sm:p-4 rounded-xl border-2 border-stone-900/40 dark:border-stone-400/40 bg-[#fdfbf7] dark:bg-[#211c18] shadow-[3px_3px_0px_rgba(41,30,20,0.3)] dark:shadow-[3px_3px_0px_rgba(242,237,228,0.2)] overflow-hidden"&gt;
&lt;div class="flex items-center justify-between mb-2 border-b border-stone-200 dark:border-stone-800 pb-1"&gt;
&lt;span class="text-[10px] font-mono font-bold uppercase tracking-widest text-stone-500 dark:text-stone-400"&gt;Advertisement&lt;/span&gt;
&lt;span class="text-[9px] font-mono uppercase px-1.5 py-0.5 rounded bg-amber-100 dark:bg-amber-950 text-amber-800 dark:text-amber-300"&gt;Sponsored&lt;/span&gt;
&lt;/div&gt;
&lt;div class="w-full flex justify-center items-center overflow-hidden min-h-[250px]"&gt;
&lt;ins class="adsbygoogle"
style="display:block; text-align:center; min-height:250px; width:100%;"
data-ad-layout="in-article"
data-ad-format="fluid"
data-ad-client="ca-pub-5474548764059850"
&gt;&lt;/ins&gt;
&lt;script&gt;
(adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id="architectural-comparison-of-aes-modes"&gt;Architectural Comparison of AES Modes&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Security &amp;amp; Performance Dimension&lt;/th&gt;
&lt;th&gt;AES-GCM (Recommended)&lt;/th&gt;
&lt;th&gt;AES-CBC&lt;/th&gt;
&lt;th&gt;AES-ECB (Broken)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cipher Classification&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;AEAD (Authenticated)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Confidentiality Only&lt;/td&gt;
&lt;td&gt;Raw Block Cipher&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Authentication / Integrity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅ Built-in 128-bit GMAC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ None (Requires HMAC)&lt;/td&gt;
&lt;td&gt;❌ None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Padding Oracle Vulnerability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Immune (No padding used)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Vulnerable to padding oracles&lt;/td&gt;
&lt;td&gt;Not applicable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bit-Flipping Malleability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Detected &amp;amp; rejected immediately&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Vulnerable without HMAC&lt;/td&gt;
&lt;td&gt;Vulnerable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Parallel Processing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fully parallelizable (SIMD)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sequential encryption only&lt;/td&gt;
&lt;td&gt;Parallelizable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Standard IV Length&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;96 bits (12 bytes)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;128 bits (16 bytes)&lt;/td&gt;
&lt;td&gt;No IV used&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Standard Adoption&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;TLS 1.3, IPsec, WebCrypto, SSH&lt;/td&gt;
&lt;td&gt;Legacy TLS, OpenVPN&lt;/td&gt;
&lt;td&gt;Strictly prohibited&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="client-side-web-crypto-api-implementation"&gt;Client-Side Web Crypto API Implementation&lt;/h2&gt;
&lt;p&gt;Modern web browsers feature hardware-accelerated, cryptographically secure primitives via the &lt;strong&gt;W3C Web Cryptography API&lt;/strong&gt; (&lt;code&gt;crypto.subtle&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Here is the standard implementation for AES-GCM encryption and decryption:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 1. Generate a Cryptographically Secure 256-bit Key
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;generateAesKey&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;AES-GCM&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;encrypt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;decrypt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 2. Encrypt UTF-8 Plaintext with AES-GCM
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;encryptAesGcm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;TextEncoder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Generate a fresh, unique 96-bit (12-byte) IV for every encryption operation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getRandomValues&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ciphertextWithTag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;AES-GCM&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;iv&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tagLength&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;ec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Pack IV + Ciphertext + Tag into a single buffer for transmission
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;combined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;ciphertextWithTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;byteLength&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;combined&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;combined&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ciphertextWithTag&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Return as Base64 string
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;btoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromCharCode&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;combined&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 3. Decrypt and Verify Integrity
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;decryptAesGcm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;base64Payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;binaryString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;atob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;base64Payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;combined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;binaryString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charCodeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Extract 12-byte IV and Ciphertext
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;combined&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;combined&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Decryption throws an error if authentication tag does not match
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decrypted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;AES-GCM&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;iv&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tagLength&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;TextDecoder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decrypted&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="step-by-step-encrypting-data-in-toolbox"&gt;Step-by-Step: Encrypting Data in Toolbox&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Open the Tool&lt;/strong&gt;: Visit the
.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Select Mode&lt;/strong&gt;: Choose &lt;strong&gt;AES-GCM (Authenticated)&lt;/strong&gt; for state-of-the-art security, or &lt;strong&gt;AES-CBC&lt;/strong&gt; for legacy compatibility.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set Key Size&lt;/strong&gt;: Choose &lt;strong&gt;256-bit&lt;/strong&gt; for maximum cryptographic resilience.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enter Plaintext &amp;amp; Secret Key&lt;/strong&gt;: Input your text and provide a passphrase, or click &lt;strong&gt;Generate Secure Key&lt;/strong&gt; to obtain a high-entropy hex key.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Client-Side Execution&lt;/strong&gt;: The tool uses your browser&amp;rsquo;s hardware-accelerated &lt;code&gt;crypto.subtle&lt;/code&gt; engine. &lt;strong&gt;Zero plaintext or keys ever touch any remote server.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Copy Encrypted Ciphertext&lt;/strong&gt;: Retrieve the resulting Base64-encoded bundle containing the IV, ciphertext, and authentication tag.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="tool-embed-container comic-panel not-prose my-10 rounded-2xl border-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#fdfbf7] dark:bg-[#28201a] shadow-[4px_4px_0px_#2c221a] dark:shadow-[4px_4px_0px_#14100d] overflow-hidden" id="embed-aes-encryption-1788851897566196000-box" role="region" aria-label="Interactive Tool Workbench"&gt;
&lt;div class="comic-halftone p-4 sm:p-5 border-b-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#f5efe4] dark:bg-[#211a14] flex flex-wrap items-center justify-between gap-3"&gt;
&lt;div class="flex items-center gap-2.5 flex-wrap min-w-0"&gt;
&lt;span class="comic-stamp bg-amber-600 text-white px-2.5 py-0.5 rounded text-[10px] font-black tracking-wider uppercase"&gt;
Interactive Workbench
&lt;/span&gt;
&lt;span class="inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full text-[10px] font-mono font-bold bg-emerald-100 text-emerald-800 dark:bg-emerald-950/60 dark:text-emerald-300 border border-emerald-300 dark:border-emerald-800 shrink-0"&gt;
&lt;span class="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-pulse"&gt;&lt;/span&gt;
&lt;span&gt;LIVE&lt;/span&gt;
&lt;/span&gt;
&lt;h3 class="text-base sm:text-lg font-extrabold text-[#2c221a] dark:text-[#ede6db] tracking-tight truncate m-0"&gt;
AES-256-GCM Authenticated Encryption: How to Secure Data in the Browser
&lt;/h3&gt;
&lt;/div&gt;
&lt;div class="flex items-center gap-2 shrink-0"&gt;
&lt;a href="https://toolbox.vishnudigital.com/aes-encryption" target="_blank" rel="noopener noreferrer" class="comic-btn-secondary !py-1 !px-3 !text-xs font-mono font-bold flex items-center gap-1.5 shadow-[2px_2px_0px_#2c221a] dark:shadow-[2px_2px_0px_#14100d] hover:translate-x-[-1px] hover:translate-y-[-1px] transition-all" title="Open full utility in new window"&gt;
&lt;span&gt;Open Fullscreen ↗&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="px-5 py-2.5 bg-[#fdfbf7] dark:bg-[#28201a] border-b border-[#ded4c3] dark:border-[#3b332c] text-xs font-medium text-[#2c221a]/80 dark:text-[#ede6db]/80"&gt;
Encrypt and decrypt confidential text using AES-GCM or AES-CBC directly in your browser with hardware-accelerated Web Crypto API.
&lt;/div&gt;
&lt;div class="relative w-full overflow-hidden bg-[#fdfbf7] dark:bg-[#1a1410]" style="min-height: 420px;"&gt;
&lt;div id="embed-aes-encryption-1788851897566196000-skeleton" class="absolute inset-0 flex flex-col items-center justify-center p-8 bg-[#fdfbf7] dark:bg-[#1e1814] z-10 transition-opacity duration-300"&gt;
&lt;div class="flex items-center gap-3 p-4 rounded-xl border-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#f5efe4] dark:bg-[#28201a] shadow-[2px_2px_0px_#2c221a] dark:shadow-[2px_2px_0px_#14100d] max-w-sm w-full"&gt;
&lt;div class="w-8 h-8 rounded-lg bg-amber-500/20 flex items-center justify-center shrink-0"&gt;
&lt;svg class="w-5 h-5 text-amber-600 animate-spin" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"&gt;
&lt;circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor"&gt;&lt;/circle&gt;
&lt;path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;div class="min-w-0 flex-1"&gt;
&lt;div class="text-xs font-bold text-[#2c221a] dark:text-[#ede6db] truncate"&gt;Initializing Workbench...&lt;/div&gt;
&lt;div class="text-[10px] font-mono text-[#2c221a]/60 dark:text-[#ede6db]/60"&gt;100% Client-Side RAM Sandbox&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;iframe
id="embed-aes-encryption-1788851897566196000-frame"
data-base-src="https://toolbox.vishnudigital.com/aes-encryption?embed=true"
src="about:blank"
title="AES-256-GCM Authenticated Encryption: How to Secure Data in the Browser – Free Online Utility"
class="w-full border-0 block opacity-0 transition-opacity duration-300"
style="height: 600px; min-height: 420px;"
loading="lazy"
allow="clipboard-read; clipboard-write; web-share"
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-downloads"&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;div class="p-3 sm:px-5 border-t border-[#ded4c3] dark:border-[#3b332c] bg-[#f5efe4]/80 dark:bg-[#211a14]/80 flex flex-wrap items-center justify-between gap-3 text-xs font-mono"&gt;
&lt;div class="flex items-center gap-2 text-[#2c221a]/70 dark:text-[#ede6db]/70"&gt;
&lt;span class="text-emerald-600 dark:text-emerald-400 font-bold"&gt;🔒 Private Execution:&lt;/span&gt;
&lt;span class="hidden sm:inline"&gt;Computations run in local browser memory. Zero server uploads.&lt;/span&gt;
&lt;span class="sm:hidden"&gt;Zero server uploads.&lt;/span&gt;
&lt;/div&gt;
&lt;div class="flex items-center gap-1.5 shrink-0"&gt;
&lt;a href="https://toolbox.vishnudigital.com/aes-encryption" target="_blank" rel="noopener noreferrer" class="font-bold text-amber-700 dark:text-amber-400 hover:text-amber-800 dark:hover:text-amber-300 hover:underline"&gt;
Launch Fullscreen →
&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;script&gt;
(function() {
const containerId = "embed-aes-encryption-1788851897566196000";
const frame = document.getElementById(containerId + "-frame");
const skeleton = document.getElementById(containerId + "-skeleton");
if (!frame) return;
function getCurrentTheme() {
return document.documentElement.classList.contains("dark") ? "dark" : "light";
}
function resolveSrc() {
const baseSrc = frame.getAttribute("data-base-src");
if (!baseSrc) return "";
const theme = getCurrentTheme();
return baseSrc + (baseSrc.includes("?") ? "&amp;" : "?") + "theme=" + theme;
}
function loadIframe() {
if (frame.getAttribute("src") !== "about:blank") return;
const fullSrc = resolveSrc();
frame.src = fullSrc;
frame.onload = function() {
if (skeleton) {
skeleton.classList.add("opacity-0");
setTimeout(function() { skeleton.style.display = "none"; }, 300);
}
frame.classList.remove("opacity-0");
frame.classList.add("opacity-100");
syncThemeToIframe();
};
}
function syncThemeToIframe() {
if (!frame || !frame.contentWindow) return;
try {
frame.contentWindow.postMessage({
type: "TOOLBOX_THEME_CHANGE",
theme: getCurrentTheme()
}, "*");
} catch(e) {}
}
if ("IntersectionObserver" in window) {
const observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
loadIframe();
observer.disconnect();
}
});
}, { rootMargin: "250px" });
observer.observe(frame);
} else {
loadIframe();
}
window.addEventListener("message", function(event) {
if (
event.data &amp;&amp;
typeof event.data === "object" &amp;&amp;
event.data.type === "TOOLBOX_RESIZE" &amp;&amp;
event.data.height
) {
if (event.source === frame.contentWindow) {
const measured = Math.max(event.data.height + 20, 420);
frame.style.height = measured + "px";
}
}
});
const themeObserver = new MutationObserver(function(mutations) {
mutations.forEach(function(m) {
if (m.attributeName === "class") {
syncThemeToIframe();
}
});
});
themeObserver.observe(document.documentElement, { attributes: true });
document.querySelectorAll(".theme-toggle").forEach(function(btn) {
btn.addEventListener("click", function() {
setTimeout(syncThemeToIframe, 50);
});
});
})();
&lt;/script&gt;
&lt;section class="faqs-container not-prose my-12 border-t-2 border-stone-200 dark:border-stone-800 pt-8" aria-label="Frequently Asked Questions"&gt;
&lt;div class="flex items-center gap-2 mb-6"&gt;
&lt;span class="comic-stamp bg-amber-600 text-white px-2 py-0.5 rounded text-[10px] font-black tracking-wider"&gt;FAQ&lt;/span&gt;
&lt;h2 class="text-2xl font-extrabold text-[#2c221a] dark:text-[#ede6db] tracking-tight m-0"&gt;
Frequently Asked Questions
&lt;/h2&gt;
&lt;/div&gt;
&lt;details name="faq" class="group border-2 border-[#2c221a] dark:border-[#ded4c3] rounded-xl p-4 bg-[#fdfbf7] dark:bg-[#28201a] shadow-[3px_3px_0px_#2c221a] dark:shadow-[3px_3px_0px_#14100d] mb-3 transition-all"&gt;
&lt;summary class="flex items-center justify-between cursor-pointer font-bold text-[#2c221a] dark:text-[#ede6db] select-none text-base"&gt;
&lt;span&gt;Why is AES-GCM considered superior to AES-CBC for web applications?&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold transition-transform duration-200 group-open:rotate-180 shrink-0 ml-2"&gt;▼&lt;/span&gt;
&lt;/summary&gt;
&lt;p class="mt-3 text-sm text-stone-600 dark:text-stone-300 leading-relaxed font-medium mb-0"&gt;
AES-GCM is an Authenticated Encryption with Associated Data (AEAD) cipher mode. Unlike AES-CBC, which only provides confidentiality and is vulnerable to padding oracle attacks unless paired with a separate HMAC, AES-GCM simultaneously provides confidentiality and cryptographic integrity through a 128-bit authentication tag (GMAC). Any tampering with the ciphertext causes decryption to fail immediately.
&lt;/p&gt;
&lt;/details&gt;
&lt;details name="faq" class="group border-2 border-[#2c221a] dark:border-[#ded4c3] rounded-xl p-4 bg-[#fdfbf7] dark:bg-[#28201a] shadow-[3px_3px_0px_#2c221a] dark:shadow-[3px_3px_0px_#14100d] mb-3 transition-all"&gt;
&lt;summary class="flex items-center justify-between cursor-pointer font-bold text-[#2c221a] dark:text-[#ede6db] select-none text-base"&gt;
&lt;span&gt;Why is reusing an Initialization Vector (IV) catastrophic in AES-GCM?&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold transition-transform duration-200 group-open:rotate-180 shrink-0 ml-2"&gt;▼&lt;/span&gt;
&lt;/summary&gt;
&lt;p class="mt-3 text-sm text-stone-600 dark:text-stone-300 leading-relaxed font-medium mb-0"&gt;
In Galois/Counter Mode, the keystream is generated by encrypting incrementing counter blocks derived from the IV and key. If the same (Key, IV) pair is used to encrypt two different plaintexts, an attacker can XOR the ciphertexts to eliminate the keystream and uncover the XOR of the plaintexts, completely destroying confidentiality and enabling forgery of the authentication tag.
&lt;/p&gt;
&lt;/details&gt;
&lt;details name="faq" class="group border-2 border-[#2c221a] dark:border-[#ded4c3] rounded-xl p-4 bg-[#fdfbf7] dark:bg-[#28201a] shadow-[3px_3px_0px_#2c221a] dark:shadow-[3px_3px_0px_#14100d] mb-3 transition-all"&gt;
&lt;summary class="flex items-center justify-between cursor-pointer font-bold text-[#2c221a] dark:text-[#ede6db] select-none text-base"&gt;
&lt;span&gt;What is the recommended IV length for AES-GCM?&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold transition-transform duration-200 group-open:rotate-180 shrink-0 ml-2"&gt;▼&lt;/span&gt;
&lt;/summary&gt;
&lt;p class="mt-3 text-sm text-stone-600 dark:text-stone-300 leading-relaxed font-medium mb-0"&gt;
The NIST SP 800-38D specification strongly recommends an Initialization Vector length of exactly 96 bits (12 bytes). A 96-bit IV is used directly as the initial counter block without undergoing additional GHASH processing, maximizing both performance and cryptographic security.
&lt;/p&gt;
&lt;/details&gt;
&lt;details name="faq" class="group border-2 border-[#2c221a] dark:border-[#ded4c3] rounded-xl p-4 bg-[#fdfbf7] dark:bg-[#28201a] shadow-[3px_3px_0px_#2c221a] dark:shadow-[3px_3px_0px_#14100d] mb-3 transition-all"&gt;
&lt;summary class="flex items-center justify-between cursor-pointer font-bold text-[#2c221a] dark:text-[#ede6db] select-none text-base"&gt;
&lt;span&gt;Is client-side browser encryption secure against server eavesdropping?&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold transition-transform duration-200 group-open:rotate-180 shrink-0 ml-2"&gt;▼&lt;/span&gt;
&lt;/summary&gt;
&lt;p class="mt-3 text-sm text-stone-600 dark:text-stone-300 leading-relaxed font-medium mb-0"&gt;
Yes. When encryption executes inside the browser using the W3C Web Crypto API (crypto.subtle), plaintext data is transformed into ciphertext in local machine memory before any network transmission occurs. As long as keys are derived and held client-side and the serving domain has strict HTTPS and Content Security Policy (CSP), zero-knowledge confidentiality is preserved.
&lt;/p&gt;
&lt;/details&gt;
&lt;/section&gt;</description></item><item><title>How to Generate SHA-256 and MD5 Hashes Online (Securely in Browser)</title><link>https://blog.toolbox.vishnudigital.com/how-to-generate-sha256-md5-hashes-online/</link><pubDate>Fri, 04 Sep 2026 00:00:00 +0000</pubDate><guid>https://blog.toolbox.vishnudigital.com/how-to-generate-sha256-md5-hashes-online/</guid><description>
&lt;aside class="comic-bubble not-prose my-8 p-6 rounded-2xl border-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#fdfbf7] dark:bg-[#28201a] shadow-[4px_4px_0px_#2c221a] dark:shadow-[4px_4px_0px_#14100d]" aria-label="AEO Quick Answer &amp; Specification Dossier"&gt;
&lt;div class="flex items-center justify-between gap-3 mb-3"&gt;
&lt;div class="flex items-center gap-2"&gt;
&lt;span class="comic-stamp bg-amber-600 text-white px-2.5 py-0.5 rounded text-[11px] font-black tracking-wider"&gt;QUICK ANSWER&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold text-[#2c221a]/70 dark:text-[#ede6db]/70"&gt;RFC SPECIFICATION SUMMARY&lt;/span&gt;
&lt;/div&gt;
&lt;span class="hidden sm:inline-flex items-center gap-1.5 text-[11px] font-bold font-mono px-2 py-0.5 rounded border border-emerald-700 dark:border-emerald-500 bg-emerald-100 dark:bg-emerald-950 text-emerald-900 dark:text-emerald-200"&gt;
&lt;span class="inline-block w-1.5 h-1.5 rounded-full bg-emerald-600 dark:bg-emerald-400"&gt;&lt;/span&gt; 100% Client-Side
&lt;/span&gt;
&lt;/div&gt;
&lt;p class="text-base sm:text-lg text-[#2c221a] dark:text-[#ede6db] leading-relaxed font-semibold mb-4"&gt;
To generate a SHA-256 hash online securely, use an in-browser tool powered by the native Web Cryptography API (crypto.subtle.digest). The tool streams your input into your local CPU, calculating the 256-bit hexadecimal digest in milliseconds without transmitting your passwords, files, or sensitive strings across the network.
&lt;/p&gt;
&lt;div class="flex flex-wrap gap-2 text-xs font-mono font-bold mt-4 pt-3 border-t border-[#ded4c3] dark:border-[#3b332c]"&gt;
&lt;span class="px-2.5 py-1 rounded bg-[#ede6db] dark:bg-[#382e26] text-[#2c221a] dark:text-[#ede6db] border border-[#ded4c3] dark:border-[#4a3e35]"&gt;Difficulty: Beginner&lt;/span&gt;
&lt;span class="px-2.5 py-1 rounded bg-[#ede6db] dark:bg-[#382e26] text-[#2c221a] dark:text-[#ede6db] border border-[#ded4c3] dark:border-[#4a3e35]"&gt;Time: 2 Mins&lt;/span&gt;
&lt;span class="px-2.5 py-1 rounded bg-[#ede6db] dark:bg-[#382e26] text-[#2c221a] dark:text-[#ede6db] border border-[#ded4c3] dark:border-[#4a3e35]"&gt;Privacy: 100% Client-Side RAM&lt;/span&gt;
&lt;span class="px-2.5 py-1 rounded bg-[#ede6db] dark:bg-[#382e26] text-[#2c221a] dark:text-[#ede6db] border border-[#ded4c3] dark:border-[#4a3e35]"&gt;Standard: FIPS 180-4 / RFC 1321&lt;/span&gt;
&lt;/div&gt;
&lt;/aside&gt;
&lt;div class="tool-hero-cta not-prose my-10 p-6 sm:p-7 rounded-2xl border-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#fdfbf7] dark:bg-[#28201a] shadow-[4px_4px_0px_#2c221a] dark:shadow-[4px_4px_0px_#14100d] flex flex-col md:flex-row items-start md:items-center justify-between gap-6 transition-all" role="complementary" aria-label="Interactive Companion Tool"&gt;
&lt;div class="space-y-2 max-w-xl"&gt;
&lt;div class="flex items-center gap-2"&gt;
&lt;span class="comic-stamp bg-amber-600 text-white px-2.5 py-0.5 rounded text-[10px] font-black tracking-wider uppercase"&gt;
Free In-Browser Tool
&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold text-stone-500 dark:text-stone-400"&gt;TOOLBOX UTILITY&lt;/span&gt;
&lt;/div&gt;
&lt;h3 class="text-xl font-extrabold text-[#2c221a] dark:text-[#ede6db] tracking-tight m-0"&gt;
Cryptographic Hash Generator
&lt;/h3&gt;
&lt;p class="text-sm text-stone-600 dark:text-stone-300 leading-relaxed font-medium m-0"&gt;
Generate instant SHA-256, MD5, and SHA-512 hashes with uppercase/lowercase toggles and binary file checksum support.
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="shrink-0 w-full md:w-auto"&gt;
&lt;a href="https://toolbox.vishnudigital.com/hash-generator?algo=sha256" class="comic-btn-primary w-full md:w-auto text-center" &gt;
Generate SHA-256 Hash Now →
&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="what-is-a-cryptographic-hash-function"&gt;What Is a Cryptographic Hash Function?&lt;/h2&gt;
&lt;p&gt;A &lt;strong&gt;cryptographic hash function&lt;/strong&gt; is a mathematical algorithm that transforms an arbitrary block of input data into a fixed-size bit string (a &lt;strong&gt;digest&lt;/strong&gt; or &lt;strong&gt;checksum&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;Every secure cryptographic hash possesses four essential properties:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deterministic&lt;/strong&gt;: The same input always produces the exact same hash.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quick Computation&lt;/strong&gt;: The digest can be computed rapidly for any data stream.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pre-Image Resistance (One-Way)&lt;/strong&gt;: Given a hash $H$, it is computationally infeasible to find the original message $M$ such that $\text{hash}(M) = H$.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Avalanche Effect&lt;/strong&gt;: Modifying a single character or bit in the input radically alters the resulting digest.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="algorithm-comparison-md5-vs-sha-1-vs-sha-256-vs-sha-512"&gt;Algorithm Comparison: MD5 vs SHA-1 vs SHA-256 vs SHA-512&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Algorithm&lt;/th&gt;
&lt;th&gt;Digest Size&lt;/th&gt;
&lt;th&gt;Collision Resistance&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Primary Modern Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MD5&lt;/strong&gt; (RFC 1321)&lt;/td&gt;
&lt;td&gt;128 bits (32 hex)&lt;/td&gt;
&lt;td&gt;❌ Broken ($2^{16}$ operations)&lt;/td&gt;
&lt;td&gt;Insecure for Crypto&lt;/td&gt;
&lt;td&gt;Legacy file integrity checksums&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SHA-1&lt;/strong&gt; (FIPS 180-1)&lt;/td&gt;
&lt;td&gt;160 bits (40 hex)&lt;/td&gt;
&lt;td&gt;❌ Broken (SHAttered in 2017)&lt;/td&gt;
&lt;td&gt;Deprecated&lt;/td&gt;
&lt;td&gt;Git commit object identification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SHA-256&lt;/strong&gt; (FIPS 180-4)&lt;/td&gt;
&lt;td&gt;256 bits (64 hex)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅ Unbroken ($2^{128}$ complexity)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Gold Standard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;TLS certificates, Bitcoin, file verification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SHA-512&lt;/strong&gt; (FIPS 180-4)&lt;/td&gt;
&lt;td&gt;512 bits (128 hex)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅ Unbroken ($2^{256}$ complexity)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maximum Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High-security government &amp;amp; banking applications&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="in-article-ad-wrapper not-prose my-8 p-3 sm:p-4 rounded-xl border-2 border-stone-900/40 dark:border-stone-400/40 bg-[#fdfbf7] dark:bg-[#211c18] shadow-[3px_3px_0px_rgba(41,30,20,0.3)] dark:shadow-[3px_3px_0px_rgba(242,237,228,0.2)] overflow-hidden"&gt;
&lt;div class="flex items-center justify-between mb-2 border-b border-stone-200 dark:border-stone-800 pb-1"&gt;
&lt;span class="text-[10px] font-mono font-bold uppercase tracking-widest text-stone-500 dark:text-stone-400"&gt;Advertisement&lt;/span&gt;
&lt;span class="text-[9px] font-mono uppercase px-1.5 py-0.5 rounded bg-amber-100 dark:bg-amber-950 text-amber-800 dark:text-amber-300"&gt;Sponsored&lt;/span&gt;
&lt;/div&gt;
&lt;div class="w-full flex justify-center items-center overflow-hidden min-h-[250px]"&gt;
&lt;ins class="adsbygoogle"
style="display:block; text-align:center; min-height:250px; width:100%;"
data-ad-layout="in-article"
data-ad-format="fluid"
data-ad-client="ca-pub-5474548764059850"
&gt;&lt;/ins&gt;
&lt;script&gt;
(adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id="why-you-should-never-hash-passwords-with-plain-sha-256"&gt;Why You Should Never Hash Passwords with Plain SHA-256&lt;/h2&gt;
&lt;p&gt;While SHA-256 is ideal for verifying file integrity and code signatures, &lt;strong&gt;it is dangerous to hash passwords directly with plain SHA-256 or MD5&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Modern GPUs can compute over &lt;strong&gt;10 billion SHA-256 hashes per second&lt;/strong&gt;. Attackers with precomputed rainbow tables can crack unsalted SHA-256 passwords in seconds. For password storage, always use slow, memory-hard key derivation functions like &lt;strong&gt;Argon2id&lt;/strong&gt;, &lt;strong&gt;bcrypt&lt;/strong&gt;, or &lt;strong&gt;PBKDF2&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="client-side-hashing-with-the-web-crypto-api"&gt;Client-Side Hashing with the Web Crypto API&lt;/h2&gt;
&lt;p&gt;Modern web browsers support hardware-accelerated cryptographic operations natively via &lt;code&gt;window.crypto.subtle&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;calculateSHA256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;encoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;TextEncoder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;encoder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hashBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;SHA-256&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hashArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hashBuffer&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;hashArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;padStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Because execution happens within your device&amp;rsquo;s browser sandbox, your sensitive data is completely protected from interception. Test it right now with our
.&lt;/p&gt;
&lt;div class="tool-embed-container comic-panel not-prose my-10 rounded-2xl border-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#fdfbf7] dark:bg-[#28201a] shadow-[4px_4px_0px_#2c221a] dark:shadow-[4px_4px_0px_#14100d] overflow-hidden" id="embed-hash-generator-1788851897572582000-box" role="region" aria-label="Interactive Tool Workbench"&gt;
&lt;div class="comic-halftone p-4 sm:p-5 border-b-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#f5efe4] dark:bg-[#211a14] flex flex-wrap items-center justify-between gap-3"&gt;
&lt;div class="flex items-center gap-2.5 flex-wrap min-w-0"&gt;
&lt;span class="comic-stamp bg-amber-600 text-white px-2.5 py-0.5 rounded text-[10px] font-black tracking-wider uppercase"&gt;
Interactive Workbench
&lt;/span&gt;
&lt;span class="inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full text-[10px] font-mono font-bold bg-emerald-100 text-emerald-800 dark:bg-emerald-950/60 dark:text-emerald-300 border border-emerald-300 dark:border-emerald-800 shrink-0"&gt;
&lt;span class="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-pulse"&gt;&lt;/span&gt;
&lt;span&gt;LIVE&lt;/span&gt;
&lt;/span&gt;
&lt;h3 class="text-base sm:text-lg font-extrabold text-[#2c221a] dark:text-[#ede6db] tracking-tight truncate m-0"&gt;
Generate SHA-256 and MD5 Hashes Online (Securely in Browser)
&lt;/h3&gt;
&lt;/div&gt;
&lt;div class="flex items-center gap-2 shrink-0"&gt;
&lt;a href="https://toolbox.vishnudigital.com/hash-generator?algo%3dsha256" target="_blank" rel="noopener noreferrer" class="comic-btn-secondary !py-1 !px-3 !text-xs font-mono font-bold flex items-center gap-1.5 shadow-[2px_2px_0px_#2c221a] dark:shadow-[2px_2px_0px_#14100d] hover:translate-x-[-1px] hover:translate-y-[-1px] transition-all" title="Open full utility in new window"&gt;
&lt;span&gt;Open Fullscreen ↗&lt;/span&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="px-5 py-2.5 bg-[#fdfbf7] dark:bg-[#28201a] border-b border-[#ded4c3] dark:border-[#3b332c] text-xs font-medium text-[#2c221a]/80 dark:text-[#ede6db]/80"&gt;
Generate instant SHA-256, MD5, and SHA-512 hashes with uppercase/lowercase toggles and binary file checksum support.
&lt;/div&gt;
&lt;div class="relative w-full overflow-hidden bg-[#fdfbf7] dark:bg-[#1a1410]" style="min-height: 420px;"&gt;
&lt;div id="embed-hash-generator-1788851897572582000-skeleton" class="absolute inset-0 flex flex-col items-center justify-center p-8 bg-[#fdfbf7] dark:bg-[#1e1814] z-10 transition-opacity duration-300"&gt;
&lt;div class="flex items-center gap-3 p-4 rounded-xl border-2 border-[#2c221a] dark:border-[#ded4c3] bg-[#f5efe4] dark:bg-[#28201a] shadow-[2px_2px_0px_#2c221a] dark:shadow-[2px_2px_0px_#14100d] max-w-sm w-full"&gt;
&lt;div class="w-8 h-8 rounded-lg bg-amber-500/20 flex items-center justify-center shrink-0"&gt;
&lt;svg class="w-5 h-5 text-amber-600 animate-spin" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"&gt;
&lt;circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor"&gt;&lt;/circle&gt;
&lt;path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;div class="min-w-0 flex-1"&gt;
&lt;div class="text-xs font-bold text-[#2c221a] dark:text-[#ede6db] truncate"&gt;Initializing Workbench...&lt;/div&gt;
&lt;div class="text-[10px] font-mono text-[#2c221a]/60 dark:text-[#ede6db]/60"&gt;100% Client-Side RAM Sandbox&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;iframe
id="embed-hash-generator-1788851897572582000-frame"
data-base-src="https://toolbox.vishnudigital.com/hash-generator?embed=true&amp;amp;algo=sha256"
src="about:blank"
title="Generate SHA-256 and MD5 Hashes Online (Securely in Browser) – Free Online Utility"
class="w-full border-0 block opacity-0 transition-opacity duration-300"
style="height: 560px; min-height: 420px;"
loading="lazy"
allow="clipboard-read; clipboard-write; web-share"
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-downloads"&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;div class="p-3 sm:px-5 border-t border-[#ded4c3] dark:border-[#3b332c] bg-[#f5efe4]/80 dark:bg-[#211a14]/80 flex flex-wrap items-center justify-between gap-3 text-xs font-mono"&gt;
&lt;div class="flex items-center gap-2 text-[#2c221a]/70 dark:text-[#ede6db]/70"&gt;
&lt;span class="text-emerald-600 dark:text-emerald-400 font-bold"&gt;🔒 Private Execution:&lt;/span&gt;
&lt;span class="hidden sm:inline"&gt;Computations run in local browser memory. Zero server uploads.&lt;/span&gt;
&lt;span class="sm:hidden"&gt;Zero server uploads.&lt;/span&gt;
&lt;/div&gt;
&lt;div class="flex items-center gap-1.5 shrink-0"&gt;
&lt;a href="https://toolbox.vishnudigital.com/hash-generator?algo%3dsha256" target="_blank" rel="noopener noreferrer" class="font-bold text-amber-700 dark:text-amber-400 hover:text-amber-800 dark:hover:text-amber-300 hover:underline"&gt;
Launch Fullscreen →
&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;script&gt;
(function() {
const containerId = "embed-hash-generator-1788851897572582000";
const frame = document.getElementById(containerId + "-frame");
const skeleton = document.getElementById(containerId + "-skeleton");
if (!frame) return;
function getCurrentTheme() {
return document.documentElement.classList.contains("dark") ? "dark" : "light";
}
function resolveSrc() {
const baseSrc = frame.getAttribute("data-base-src");
if (!baseSrc) return "";
const theme = getCurrentTheme();
return baseSrc + (baseSrc.includes("?") ? "&amp;" : "?") + "theme=" + theme;
}
function loadIframe() {
if (frame.getAttribute("src") !== "about:blank") return;
const fullSrc = resolveSrc();
frame.src = fullSrc;
frame.onload = function() {
if (skeleton) {
skeleton.classList.add("opacity-0");
setTimeout(function() { skeleton.style.display = "none"; }, 300);
}
frame.classList.remove("opacity-0");
frame.classList.add("opacity-100");
syncThemeToIframe();
};
}
function syncThemeToIframe() {
if (!frame || !frame.contentWindow) return;
try {
frame.contentWindow.postMessage({
type: "TOOLBOX_THEME_CHANGE",
theme: getCurrentTheme()
}, "*");
} catch(e) {}
}
if ("IntersectionObserver" in window) {
const observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
loadIframe();
observer.disconnect();
}
});
}, { rootMargin: "250px" });
observer.observe(frame);
} else {
loadIframe();
}
window.addEventListener("message", function(event) {
if (
event.data &amp;&amp;
typeof event.data === "object" &amp;&amp;
event.data.type === "TOOLBOX_RESIZE" &amp;&amp;
event.data.height
) {
if (event.source === frame.contentWindow) {
const measured = Math.max(event.data.height + 20, 420);
frame.style.height = measured + "px";
}
}
});
const themeObserver = new MutationObserver(function(mutations) {
mutations.forEach(function(m) {
if (m.attributeName === "class") {
syncThemeToIframe();
}
});
});
themeObserver.observe(document.documentElement, { attributes: true });
document.querySelectorAll(".theme-toggle").forEach(function(btn) {
btn.addEventListener("click", function() {
setTimeout(syncThemeToIframe, 50);
});
});
})();
&lt;/script&gt;
&lt;section class="faqs-container not-prose my-12 border-t-2 border-stone-200 dark:border-stone-800 pt-8" aria-label="Frequently Asked Questions"&gt;
&lt;div class="flex items-center gap-2 mb-6"&gt;
&lt;span class="comic-stamp bg-amber-600 text-white px-2 py-0.5 rounded text-[10px] font-black tracking-wider"&gt;FAQ&lt;/span&gt;
&lt;h2 class="text-2xl font-extrabold text-[#2c221a] dark:text-[#ede6db] tracking-tight m-0"&gt;
Frequently Asked Questions
&lt;/h2&gt;
&lt;/div&gt;
&lt;details name="faq" class="group border-2 border-[#2c221a] dark:border-[#ded4c3] rounded-xl p-4 bg-[#fdfbf7] dark:bg-[#28201a] shadow-[3px_3px_0px_#2c221a] dark:shadow-[3px_3px_0px_#14100d] mb-3 transition-all"&gt;
&lt;summary class="flex items-center justify-between cursor-pointer font-bold text-[#2c221a] dark:text-[#ede6db] select-none text-base"&gt;
&lt;span&gt;Why is MD5 no longer considered cryptographically secure?&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold transition-transform duration-200 group-open:rotate-180 shrink-0 ml-2"&gt;▼&lt;/span&gt;
&lt;/summary&gt;
&lt;p class="mt-3 text-sm text-stone-600 dark:text-stone-300 leading-relaxed font-medium mb-0"&gt;
MD5 is vulnerable to collision attacks, where two distinct input strings produce the exact same 128-bit hash digest. In 2008, security researchers demonstrated forging rogue SSL certificates using MD5 collisions. However, MD5 is still widely used as a fast, non-cryptographic checksum for file transfer verification.
&lt;/p&gt;
&lt;/details&gt;
&lt;details name="faq" class="group border-2 border-[#2c221a] dark:border-[#ded4c3] rounded-xl p-4 bg-[#fdfbf7] dark:bg-[#28201a] shadow-[3px_3px_0px_#2c221a] dark:shadow-[3px_3px_0px_#14100d] mb-3 transition-all"&gt;
&lt;summary class="flex items-center justify-between cursor-pointer font-bold text-[#2c221a] dark:text-[#ede6db] select-none text-base"&gt;
&lt;span&gt;Can a SHA-256 hash be decrypted back to its original input?&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold transition-transform duration-200 group-open:rotate-180 shrink-0 ml-2"&gt;▼&lt;/span&gt;
&lt;/summary&gt;
&lt;p class="mt-3 text-sm text-stone-600 dark:text-stone-300 leading-relaxed font-medium mb-0"&gt;
No. Cryptographic hash functions are strictly one-way mathematical algorithms, not encryption. You cannot reverse or decrypt a hash digest. The only way to find the original input is via brute-force dictionary attacks (rainbow tables).
&lt;/p&gt;
&lt;/details&gt;
&lt;details name="faq" class="group border-2 border-[#2c221a] dark:border-[#ded4c3] rounded-xl p-4 bg-[#fdfbf7] dark:bg-[#28201a] shadow-[3px_3px_0px_#2c221a] dark:shadow-[3px_3px_0px_#14100d] mb-3 transition-all"&gt;
&lt;summary class="flex items-center justify-between cursor-pointer font-bold text-[#2c221a] dark:text-[#ede6db] select-none text-base"&gt;
&lt;span&gt;Does hashing files in Toolbox upload my data to a server?&lt;/span&gt;
&lt;span class="text-xs font-mono font-bold transition-transform duration-200 group-open:rotate-180 shrink-0 ml-2"&gt;▼&lt;/span&gt;
&lt;/summary&gt;
&lt;p class="mt-3 text-sm text-stone-600 dark:text-stone-300 leading-relaxed font-medium mb-0"&gt;
No. The hashing engine uses the browser&amp;#39;s native Web Cryptography API (crypto.subtle.digest) to compute digests locally on your CPU/GPU. Zero bytes of your file or text are transmitted over the internet.
&lt;/p&gt;
&lt;/details&gt;
&lt;/section&gt;</description></item></channel></rss>