Skip to content

Commit f4edb52

Browse files
committed
added hasher tool
1 parent f31847a commit f4edb52

File tree

8 files changed

+521
-4
lines changed

8 files changed

+521
-4
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
/filetype_wasm/target/
22
/filetype_wasm/pkg/
33
/filetype_wasm/.wasm-pack
4+
/hasher_wasm/target/
5+
/hasher_wasm/pkg/
6+
/hasher_wasm/.wasm-pack
47
/node_modules/
58
*.log
69
.DS_Store

content/posts/taskerbot.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ tags: "discord"
55
---
66

77
Developing my latest project, a Discord bot called [Taskerbot](https://github.com/rsomonte/taskerbot), has been an interesting journey full of unexpected turns. The inspiration came from a bot I saw during an event on a Discord server that gamified tasks, and I decided to build my own version. This project quickly evolved into a valuable lesson in modern bot development, especially after a five-year hiatus from the Discord API.
8+
<!-- excerpt -->
89

910
---
1011

content/tools.html

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@
77
<p>Here you will find a list of tools I've developed using different technologies such as Wasm:</p>
88
{% assign tools = collections.tools %}
99
{% for tool in tools %}
10-
<div class="tool-entry">
11-
<a href="{{ tool.url }}"><h2>{{ tool.data.title | default: tool.fileSlug }}</h2></a>
10+
<h2><a href="{{ tool.url }}">{{ tool.data.title | default: tool.fileSlug }}</a></h2>
1211
{% if tool.data.description %}
1312
<p>{{ tool.data.description }}</p>
1413
{% endif %}
15-
</div>
1614
{% endfor %}

content/tools/hash.html

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
---
2+
layout: layout.html
3+
title: Hasher
4+
description: Generate file hashes in the browser using Rust and WebAssembly.
5+
---
6+
<h1>Hasher</h1>
7+
<p>Select a file no bigger than 1.5GB from your computer to calculate its hash using Rust and WebAssembly. The entire process runs locally in your browser.</p>
8+
<p>Don't forget to choose which hashing algorithms you want to use.</p>
9+
<!-- File input -->
10+
<input type="file" id="fileInput">
11+
12+
<!-- Algorithm checkboxes -->
13+
<ul>
14+
<li><input type="checkbox" id="sha1"> SHA-1</li>
15+
<li><input type="checkbox" id="sha256"> SHA-256</li>
16+
<li><input type="checkbox" id="sha512"> SHA-512</li>
17+
<li><input type="checkbox" id="md5"> MD5</li>
18+
<li><input type="checkbox" id="blake2b"> BLAKE2b</li>
19+
<li><input type="checkbox" id="blake2s"> BLAKE2s</li>
20+
<li><input type="checkbox" id="whirlpool"> Whirlpool</li>
21+
<li><input type="checkbox" id="tiger"> Tiger</li>
22+
</ul>
23+
24+
<!-- Control buttons -->
25+
<button id="selectAll">Select All</button>
26+
<button id="deselectAll">Deselect All</button>
27+
<button id="calculateBtn" disabled>Calculate Hashes</button>
28+
29+
<script type="module">
30+
import init, { hasher_results } from '/pkg/hasher_wasm.js';
31+
32+
const fileInput = document.getElementById('fileInput');
33+
const calculateBtn = document.getElementById('calculateBtn');
34+
const resultsOutput = document.getElementById('results');
35+
const selectAllBtn = document.getElementById('selectAll');
36+
const deselectAllBtn = document.getElementById('deselectAll');
37+
const checkboxes = document.querySelectorAll('input[type="checkbox"]');
38+
39+
async function run() {
40+
await init();
41+
fileInput.disabled = false;
42+
43+
// Enable/disable calculate button based on file selection
44+
fileInput.addEventListener('change', () => {
45+
calculateBtn.disabled = !fileInput.files.length;
46+
});
47+
48+
// Select/Deselect all functionality
49+
selectAllBtn.addEventListener('click', () => {
50+
checkboxes.forEach(checkbox => checkbox.checked = true);
51+
});
52+
53+
deselectAllBtn.addEventListener('click', () => {
54+
checkboxes.forEach(checkbox => checkbox.checked = false);
55+
});
56+
57+
// Calculate hashes when button is clicked
58+
calculateBtn.addEventListener('click', async () => {
59+
// Check if any algorithm is selected
60+
const selectedCount = Array.from(checkboxes).filter(cb => cb.checked).length;
61+
if (selectedCount === 0) {
62+
const div = document.createElement('div');
63+
div.innerHTML = '<p>Please select at least one hashing algorithm.</p>';
64+
resultsOutput.innerHTML = '';
65+
resultsOutput.appendChild(div);
66+
return;
67+
}
68+
69+
// Add size validation after algorithm check
70+
const file = fileInput.files[0];
71+
const MAX_FILE_SIZE = 1.5 * 1024 * 1024 * 1024; // 1.5GB limit
72+
/*
73+
This limit is required because of the limits of the WebAssembly memory and the browser's FileReader API.
74+
The maximum size of a file that can be processed is 1.5GB.
75+
*/
76+
77+
if (file.size > MAX_FILE_SIZE) {
78+
const div = document.createElement('div');
79+
div.innerHTML = '<p>File is too large. Please select a file smaller than 1.5GB.</p>';
80+
resultsOutput.innerHTML = '';
81+
resultsOutput.appendChild(div);
82+
return;
83+
}
84+
85+
const reader = new FileReader();
86+
87+
reader.onload = async function(e) {
88+
const arrayBuffer = e.target.result;
89+
const bytes = new Uint8Array(arrayBuffer);
90+
91+
// Get selected algorithms
92+
const selectedAlgorithms = Array.from(checkboxes)
93+
.filter(cb => cb.checked)
94+
.map(cb => cb.id)
95+
.join(' ');
96+
97+
const results = hasher_results(bytes, selectedAlgorithms);
98+
displayResults(results);
99+
};
100+
101+
reader.readAsArrayBuffer(file);
102+
});
103+
}
104+
105+
function displayResults(results) {
106+
// Create table
107+
let table = `
108+
<table style="width:100%; margin-top: 20px; border-collapse: collapse; table-layout: fixed;">
109+
<tr>
110+
<th style="text-align: left; padding: 8px; border: 1px solid #ddd; width: 20%;">Algorithm</th>
111+
<th style="text-align: left; padding: 8px; border: 1px solid #ddd; width: 80%;">Hash</th>
112+
</tr>
113+
`;
114+
115+
// Split results into lines and process each
116+
results.split('\n').forEach(line => {
117+
const [algorithm, ...hashParts] = line.split(' ');
118+
const hash = hashParts.join(' ');
119+
table += `
120+
<tr>
121+
<td style="padding: 8px; border: 1px solid #ddd;">${algorithm}</td>
122+
<td style="padding: 8px; border: 1px solid #ddd; font-family: monospace;
123+
word-wrap: break-word; word-break: break-all;">${hash}</td>
124+
</tr>
125+
`;
126+
});
127+
128+
table += '</table>';
129+
130+
// Add copy buttons for each hash
131+
const div = document.createElement('div');
132+
div.innerHTML = table;
133+
resultsOutput.innerHTML = '';
134+
resultsOutput.appendChild(div);
135+
}
136+
137+
run();
138+
</script>
139+
<div id="results"></div>

0 commit comments

Comments
 (0)