No Login Data Private Local Save

Subresource Integrity (SRI) Hash Generator - Online

8
0
0
0

SRI Hash Generator

Generate Subresource Integrity hashes for your CDN scripts and stylesheets.

Quick fill:
0 characters

Drag & drop your file here

or click to browse

|
Crossorigin:
Processing...

Generating SRI hash...

Generated SRI Hashes

Frequently Asked Questions

Subresource Integrity (SRI) is a W3C security feature that allows browsers to verify that resources loaded from third-party sources (like CDNs) have not been tampered with. It works by comparing a cryptographic hash of the fetched resource against a hash value you provide in the integrity attribute of <script> or <link> tags. If the hashes don't match, the browser blocks the resource from loading, protecting your users from potential supply-chain attacks or compromised CDN files.

Using SRI hashes adds a critical layer of security to your website. If a CDN is compromised, hacked, or serves a malicious version of a library, SRI prevents that corrupted file from executing in your users' browsers. This protects against supply-chain attacks, man-in-the-middle modifications, and accidental resource corruption. Without SRI, your site implicitly trusts that the CDN delivers exactly what you expect — a risky assumption in today's threat landscape.

These are members of the SHA-2 family of cryptographic hash functions. The main difference is the output size: SHA-256 produces a 256-bit hash, SHA-384 produces 384-bit, and SHA-512 produces 512-bit. SHA-384 is the most commonly recommended algorithm for SRI because it offers a strong balance of security and performance. SHA-256 is faster to compute but slightly less collision-resistant. SHA-512 provides the highest security margin but results in longer hash strings. All three are currently considered cryptographically secure; the choice often comes down to your security requirements and the recommendations of the resource provider.

The crossorigin attribute controls how the browser handles cross-origin requests for the resource. For SRI to work properly on cross-origin resources (like CDN files), the resource must be served with the appropriate CORS headers. The crossorigin="anonymous" setting sends the request without credentials (cookies, HTTP auth), while crossorigin="use-credentials" includes them. Most CDN resources work with anonymous. If you omit crossorigin on a cross-origin resource, SRI verification will fail silently in some browsers. For same-origin resources, the crossorigin attribute is not required.

Simply copy the generated HTML tag or integrity attribute and replace your existing <script> or <link> tag. For example:

Before: <script src="https://cdn.example.com/lib.js"></script>
After: <script src="https://cdn.example.com/lib.js" integrity="sha384-xxxxx" crossorigin="anonymous"></script>

Our tool generates the complete tag with the correct integrity and crossorigin attributes, ready to paste into your HTML.

SRI is supported by all modern browsers, including Chrome (v45+), Firefox (v43+), Safari (v11+), Edge (v17+), and Opera (v32+). Internet Explorer does not support SRI. However, since IE's market share is now negligible and most major websites have dropped IE support, SRI is considered safe to deploy for the vast majority of users. Browsers that don't support SRI simply ignore the integrity attribute and load the resource normally, so adding SRI hashes causes no breakage for legacy browsers.

If the CDN updates the resource (even by a single byte), the SRI hash will no longer match, and the browser will block the resource from loading. This is by design — it prevents unexpected changes from affecting your site. For this reason, you should always use versioned URLs (e.g., jquery@3.7.1 rather than jquery@latest) so that the file content is immutable. When you intentionally upgrade a library, you must regenerate the SRI hash for the new version. This tool makes that process quick and easy.

Yes! Use the Upload File tab to select a local JavaScript or CSS file, or paste the file content directly into the Paste Content tab. The hash is computed entirely in your browser using the Web Crypto API — your file never leaves your computer. This is useful for verifying the integrity of files before uploading them to a CDN, or for generating SRI hashes for self-hosted resources that you want to protect.

SRI and CSP are complementary security mechanisms. CSP controls which sources your site is allowed to load resources from (via directives like script-src). SRI ensures that resources from allowed sources haven't been modified. You can (and should) use both together: CSP to restrict which CDNs are permitted, and SRI to verify the integrity of the files served by those CDNs. When used together, they provide defense-in-depth against XSS and supply-chain attacks. Starting with CSP Level 3, you can even require SRI for certain resource types using the require-sri-for directive.

Yes. When you use the From URL feature, the tool fetches the resource directly from the specified URL using your browser's standard fetch API. The content is processed entirely on your device — it is never sent to any server. The hash is computed locally using the browser's built-in Web Crypto API. If a CDN does not support CORS (Cross-Origin Resource Sharing), the fetch may fail; in that case, you can download the file and use the Upload File or Paste Content options instead.
'; } else { return ''; } } else { if (resourceUrl) { return ''; } else { return ''; } } } } // Show results async function showResults(data, resourceUrl) { const algos = getSelectedAlgorithms(); if (algos.length === 0) { showError('Please select at least one hash algorithm.'); return; } $resultsContainer.empty(); $resultsSection.removeClass('d-none'); $errorAlert.addClass('d-none'); for (const algo of algos) { try { const base64Hash = await computeHash(data, algo.id); const resultStr = buildResultString(algo.prefix, base64Hash, resourceUrl); const sriValue = algo.prefix + '-' + base64Hash; const cardId = 'result-card-' + algo.prefix; const cardHtml = `
${algo.id}
${escapeHtml(sriValue)}
${escapeHtml(resultStr)}
Click the copy button to copy the full result.
`; $resultsContainer.append(cardHtml); } catch (err) { showError('Hash computation failed for ' + algo.id + ': ' + err.message); } } // Bind copy buttons $resultsContainer.find('.copy-btn').off('click').on('click', function() { const text = $(this).data('copy'); copyToClipboard(text); const $btn = $(this); const $icon = $btn.find('i'); $icon.removeClass('fa-copy').addClass('fa-check'); $btn.removeClass('btn-outline-secondary').addClass('btn-success'); setTimeout(() => { $icon.removeClass('fa-check').addClass('fa-copy'); $btn.removeClass('btn-success').addClass('btn-outline-secondary'); }, 1500); }); } function escapeHtml(str) { const div = document.createElement('div'); div.textContent = str; return div.innerHTML; } // Copy to clipboard with toast function copyToClipboard(text) { if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(text).then(() => { showCopyToast(); }).catch(() => { fallbackCopy(text); }); } else { fallbackCopy(text); } } function fallbackCopy(text) { const textarea = document.createElement('textarea'); textarea.value = text; textarea.style.position = 'fixed'; textarea.style.opacity = '0'; document.body.appendChild(textarea); textarea.select(); try { document.execCommand('copy'); showCopyToast(); } catch (e) { alert('Failed to copy. Please copy manually.'); } document.body.removeChild(textarea); } function showCopyToast() { const existing = document.querySelector('.copy-toast'); if (existing) existing.remove(); const toast = document.createElement('div'); toast.className = 'copy-toast'; toast.innerHTML = 'Copied to clipboard!'; document.body.appendChild(toast); setTimeout(() => toast.remove(), 1900); } function showError(msg) { $errorMsg.text(msg); $errorAlert.removeClass('d-none'); $resultsSection.addClass('d-none'); } function showLoading() { $loading.removeClass('d-none'); $errorAlert.addClass('d-none'); $resultsSection.addClass('d-none'); } function hideLoading() { $loading.addClass('d-none'); } function formatFileSize(bytes) { if (bytes < 1024) return bytes + ' B'; if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB'; return (bytes / 1048576).toFixed(2) + ' MB'; } // --- URL Tab --- async function fetchFromUrl() { const url = $urlInput.val().trim(); if (!url) { showError('Please enter a valid URL.'); return; } try { new URL(url); } catch (e) { showError('Please enter a valid URL (e.g., https://cdn.example.com/file.js).'); return; } currentResourceUrl = url; showLoading(); $urlStatus.html(''); try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 30000); const response = await fetch(url, { signal: controller.signal, mode: 'cors', credentials: 'omit' }); clearTimeout(timeoutId); if (!response.ok) { throw new Error('HTTP ' + response.status + ': ' + response.statusText); } const arrayBuffer = await response.arrayBuffer(); const contentLength = arrayBuffer.byteLength; $urlStatus.html('Fetched successfully — ' + formatFileSize(contentLength) + ''); hideLoading(); await showResults(arrayBuffer, url); } catch (err) { hideLoading(); if (err.name === 'AbortError') { showError('Request timed out after 30 seconds. Please try again or use the Paste/Upload options.'); } else if (err.message.includes('Failed to fetch') || err.message.includes('NetworkError')) { showError('Unable to fetch the resource. The CDN may not support CORS. Try downloading the file and using the Upload or Paste Content tab instead.'); $urlStatus.html('CORS may be blocked for this URL. Try Paste Content or Upload File.'); } else { showError('Error fetching URL: ' + err.message); } } } $fetchBtn.on('click', fetchFromUrl); $urlInput.on('keydown', function(e) { if (e.key === 'Enter') { e.preventDefault(); fetchFromUrl(); } }); // Quick URL buttons $tool.find('.quick-url-btn').on('click', function() { const url = $(this).data('url'); $urlInput.val(url); // Switch to URL tab $('#sriMainTabs button[data-bs-target="#tab-url"]').tab('show'); fetchFromUrl(); }); // --- Text Tab --- $textInput.on('input', function() { const len = $(this).val().length; $charCount.text(len.toLocaleString() + ' characters'); }); $textGenerateBtn.on('click', async function() { const text = $textInput.val(); if (!text.trim()) { showError('Please paste some content to generate a hash.'); return; } currentResourceUrl = ''; showLoading(); try { await showResults(text, ''); } catch (err) { showError('Error generating hash: ' + err.message); } hideLoading(); }); // --- File Tab --- function handleFile(file) { if (!file) return; const validTypes = ['text/javascript', 'application/javascript', 'text/css', 'application/x-javascript', 'text/plain']; const ext = file.name.split('.').pop().toLowerCase(); const validExts = ['js', 'css', 'txt', 'mjs']; if (!validExts.includes(ext) && !validTypes.includes(file.type) && file.type !== '') { showError('Please select a JavaScript (.js) or CSS (.css) file. For other files, use the Paste Content tab.'); return; } currentFileName = file.name; const reader = new FileReader(); reader.onload = function(e) { currentFileData = new Uint8Array(e.target.result); $fileName.text(file.name); $fileSize.text(formatFileSize(file.size)); $fileInfo.removeClass('d-none'); $fileGenerateBtn.removeClass('d-none'); $dropZone.addClass('d-none'); $errorAlert.addClass('d-none'); }; reader.onerror = function() { showError('Failed to read file. Please try again.'); }; reader.readAsArrayBuffer(file); } $browseBtn.on('click', function(e) { e.stopPropagation(); $fileInput.click(); }); $dropZone.on('click', function() { $fileInput.click(); }); $fileInput.on('change', function() { if (this.files && this.files[0]) { handleFile(this.files[0]); } }); // Drag and drop $dropZone.on('dragover', function(e) { e.preventDefault(); e.stopPropagation(); $(this).addClass('drag-over'); }); $dropZone.on('dragleave', function(e) { e.preventDefault(); e.stopPropagation(); $(this).removeClass('drag-over'); }); $dropZone.on('drop', function(e) { e.preventDefault(); e.stopPropagation(); $(this).removeClass('drag-over'); const files = e.originalEvent.dataTransfer.files; if (files && files[0]) { handleFile(files[0]); } }); $fileClear.on('click', function() { currentFileData = null; currentFileName = null; $fileInput.val(''); $fileInfo.addClass('d-none'); $fileGenerateBtn.addClass('d-none'); $dropZone.removeClass('d-none'); $resultsSection.addClass('d-none'); }); $fileGenerateBtn.on('click', async function() { if (!currentFileData) { showError('Please select a file first.'); return; } currentResourceUrl = ''; showLoading(); try { await showResults(currentFileData, ''); } catch (err) { showError('Error generating hash: ' + err.message); } hideLoading(); }); // Initialize - set active tab properly $('#sriMainTabs button[data-bs-target="#tab-url"]').tab('show'); // Check Web Crypto API availability if (!window.crypto || !window.crypto.subtle) { showError('Web Crypto API is not available. This tool requires a secure context (HTTPS) or localhost to function.'); $fetchBtn.prop('disabled', true); $textGenerateBtn.prop('disabled', true); $fileGenerateBtn.prop('disabled', true); } })();