trying to convert state into [u64; 25]

This commit is contained in:
Guilleag01
2025-09-25 18:30:45 +02:00
parent f00dc3e637
commit d9de93d6a6
8 changed files with 843 additions and 40 deletions

BIN
file.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 KiB

491
flamegraph.svg Normal file
View File

@@ -0,0 +1,491 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" width="1200" height="230" onload="init(evt)" viewBox="0 0 1200 230" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fg="http://github.com/jonhoo/inferno"><!--Flame graph stack visualization. See https://github.com/brendangregg/FlameGraph for latest version, and http://www.brendangregg.com/flamegraphs.html for examples.--><!--NOTES: --><defs><linearGradient id="background" y1="0" y2="1" x1="0" x2="0"><stop stop-color="#eeeeee" offset="5%"/><stop stop-color="#eeeeb0" offset="95%"/></linearGradient></defs><style type="text/css">
text { font-family:monospace; font-size:12px }
#title { text-anchor:middle; font-size:17px; }
#matched { text-anchor:end; }
#search { text-anchor:end; opacity:0.1; cursor:pointer; }
#search:hover, #search.show { opacity:1; }
#subtitle { text-anchor:middle; font-color:rgb(160,160,160); }
#unzoom { cursor:pointer; }
#frames > *:hover { stroke:black; stroke-width:0.5; cursor:pointer; }
.hide { display:none; }
.parent { opacity:0.5; }
</style><script type="text/ecmascript"><![CDATA[
var nametype = 'Function:';
var fontsize = 12;
var fontwidth = 0.59;
var xpad = 10;
var inverted = false;
var searchcolor = 'rgb(230,0,230)';
var fluiddrawing = true;
var truncate_text_right = false;
]]><![CDATA["use strict";
var details, searchbtn, unzoombtn, matchedtxt, svg, searching, frames, known_font_width;
function init(evt) {
details = document.getElementById("details").firstChild;
searchbtn = document.getElementById("search");
unzoombtn = document.getElementById("unzoom");
matchedtxt = document.getElementById("matched");
svg = document.getElementsByTagName("svg")[0];
frames = document.getElementById("frames");
known_font_width = get_monospace_width(frames);
total_samples = parseInt(frames.attributes.total_samples.value);
searching = 0;
// Use GET parameters to restore a flamegraph's state.
var restore_state = function() {
var params = get_params();
if (params.x && params.y)
zoom(find_group(document.querySelector('[*|x="' + params.x + '"][y="' + params.y + '"]')));
if (params.s)
search(params.s);
};
if (fluiddrawing) {
// Make width dynamic so the SVG fits its parent's width.
svg.removeAttribute("width");
// Edge requires us to have a viewBox that gets updated with size changes.
var isEdge = /Edge\/\d./i.test(navigator.userAgent);
if (!isEdge) {
svg.removeAttribute("viewBox");
}
var update_for_width_change = function() {
if (isEdge) {
svg.attributes.viewBox.value = "0 0 " + svg.width.baseVal.value + " " + svg.height.baseVal.value;
}
// Keep consistent padding on left and right of frames container.
frames.attributes.width.value = svg.width.baseVal.value - xpad * 2;
// Text truncation needs to be adjusted for the current width.
update_text_for_elements(frames.children);
// Keep search elements at a fixed distance from right edge.
var svgWidth = svg.width.baseVal.value;
searchbtn.attributes.x.value = svgWidth - xpad;
matchedtxt.attributes.x.value = svgWidth - xpad;
};
window.addEventListener('resize', function() {
update_for_width_change();
});
// This needs to be done asynchronously for Safari to work.
setTimeout(function() {
unzoom();
update_for_width_change();
restore_state();
}, 0);
} else {
restore_state();
}
}
// event listeners
window.addEventListener("click", function(e) {
var target = find_group(e.target);
if (target) {
if (target.nodeName == "a") {
if (e.ctrlKey === false) return;
e.preventDefault();
}
if (target.classList.contains("parent")) unzoom();
zoom(target);
// set parameters for zoom state
var el = target.querySelector("rect");
if (el && el.attributes && el.attributes.y && el.attributes["fg:x"]) {
var params = get_params()
params.x = el.attributes["fg:x"].value;
params.y = el.attributes.y.value;
history.replaceState(null, null, parse_params(params));
}
}
else if (e.target.id == "unzoom") {
unzoom();
// remove zoom state
var params = get_params();
if (params.x) delete params.x;
if (params.y) delete params.y;
history.replaceState(null, null, parse_params(params));
}
else if (e.target.id == "search") search_prompt();
}, false)
// mouse-over for info
// show
window.addEventListener("mouseover", function(e) {
var target = find_group(e.target);
if (target) details.nodeValue = nametype + " " + g_to_text(target);
}, false)
// clear
window.addEventListener("mouseout", function(e) {
var target = find_group(e.target);
if (target) details.nodeValue = ' ';
}, false)
// ctrl-F for search
window.addEventListener("keydown",function (e) {
if (e.keyCode === 114 || (e.ctrlKey && e.keyCode === 70)) {
e.preventDefault();
search_prompt();
}
}, false)
// functions
function get_params() {
var params = {};
var paramsarr = window.location.search.substr(1).split('&');
for (var i = 0; i < paramsarr.length; ++i) {
var tmp = paramsarr[i].split("=");
if (!tmp[0] || !tmp[1]) continue;
params[tmp[0]] = decodeURIComponent(tmp[1]);
}
return params;
}
function parse_params(params) {
var uri = "?";
for (var key in params) {
uri += key + '=' + encodeURIComponent(params[key]) + '&';
}
if (uri.slice(-1) == "&")
uri = uri.substring(0, uri.length - 1);
if (uri == '?')
uri = window.location.href.split('?')[0];
return uri;
}
function find_child(node, selector) {
var children = node.querySelectorAll(selector);
if (children.length) return children[0];
return;
}
function find_group(node) {
var parent = node.parentElement;
if (!parent) return;
if (parent.id == "frames") return node;
return find_group(parent);
}
function orig_save(e, attr, val) {
if (e.attributes["fg:orig_" + attr] != undefined) return;
if (e.attributes[attr] == undefined) return;
if (val == undefined) val = e.attributes[attr].value;
e.setAttribute("fg:orig_" + attr, val);
}
function orig_load(e, attr) {
if (e.attributes["fg:orig_"+attr] == undefined) return;
e.attributes[attr].value = e.attributes["fg:orig_" + attr].value;
e.removeAttribute("fg:orig_" + attr);
}
function g_to_text(e) {
var text = find_child(e, "title").firstChild.nodeValue;
return (text)
}
function g_to_func(e) {
var func = g_to_text(e);
// if there's any manipulation we want to do to the function
// name before it's searched, do it here before returning.
return (func);
}
function get_monospace_width(frames) {
// Given the id="frames" element, return the width of text characters if
// this is a monospace font, otherwise return 0.
text = find_child(frames.children[0], "text");
originalContent = text.textContent;
text.textContent = "!";
bangWidth = text.getComputedTextLength();
text.textContent = "W";
wWidth = text.getComputedTextLength();
text.textContent = originalContent;
if (bangWidth === wWidth) {
return bangWidth;
} else {
return 0;
}
}
function update_text_for_elements(elements) {
// In order to render quickly in the browser, you want to do one pass of
// reading attributes, and one pass of mutating attributes. See
// https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/ for details.
// Fall back to inefficient calculation, if we're variable-width font.
// TODO This should be optimized somehow too.
if (known_font_width === 0) {
for (var i = 0; i < elements.length; i++) {
update_text(elements[i]);
}
return;
}
var textElemNewAttributes = [];
for (var i = 0; i < elements.length; i++) {
var e = elements[i];
var r = find_child(e, "rect");
var t = find_child(e, "text");
var w = parseFloat(r.attributes.width.value) * frames.attributes.width.value / 100 - 3;
var txt = find_child(e, "title").textContent.replace(/\([^(]*\)$/,"");
var newX = format_percent((parseFloat(r.attributes.x.value) + (100 * 3 / frames.attributes.width.value)));
// Smaller than this size won't fit anything
if (w < 2 * known_font_width) {
textElemNewAttributes.push([newX, ""]);
continue;
}
// Fit in full text width
if (txt.length * known_font_width < w) {
textElemNewAttributes.push([newX, txt]);
continue;
}
var substringLength = Math.floor(w / known_font_width) - 2;
if (truncate_text_right) {
// Truncate the right side of the text.
textElemNewAttributes.push([newX, txt.substring(0, substringLength) + ".."]);
continue;
} else {
// Truncate the left side of the text.
textElemNewAttributes.push([newX, ".." + txt.substring(txt.length - substringLength, txt.length)]);
continue;
}
}
console.assert(textElemNewAttributes.length === elements.length, "Resize failed, please file a bug at https://github.com/jonhoo/inferno/");
// Now that we know new textContent, set it all in one go so we don't refresh a bazillion times.
for (var i = 0; i < elements.length; i++) {
var e = elements[i];
var values = textElemNewAttributes[i];
var t = find_child(e, "text");
t.attributes.x.value = values[0];
t.textContent = values[1];
}
}
function update_text(e) {
var r = find_child(e, "rect");
var t = find_child(e, "text");
var w = parseFloat(r.attributes.width.value) * frames.attributes.width.value / 100 - 3;
var txt = find_child(e, "title").textContent.replace(/\([^(]*\)$/,"");
t.attributes.x.value = format_percent((parseFloat(r.attributes.x.value) + (100 * 3 / frames.attributes.width.value)));
// Smaller than this size won't fit anything
if (w < 2 * fontsize * fontwidth) {
t.textContent = "";
return;
}
t.textContent = txt;
// Fit in full text width
if (t.getComputedTextLength() < w)
return;
if (truncate_text_right) {
// Truncate the right side of the text.
for (var x = txt.length - 2; x > 0; x--) {
if (t.getSubStringLength(0, x + 2) <= w) {
t.textContent = txt.substring(0, x) + "..";
return;
}
}
} else {
// Truncate the left side of the text.
for (var x = 2; x < txt.length; x++) {
if (t.getSubStringLength(x - 2, txt.length) <= w) {
t.textContent = ".." + txt.substring(x, txt.length);
return;
}
}
}
t.textContent = "";
}
// zoom
function zoom_reset(e) {
if (e.tagName == "rect") {
e.attributes.x.value = format_percent(100 * parseInt(e.attributes["fg:x"].value) / total_samples);
e.attributes.width.value = format_percent(100 * parseInt(e.attributes["fg:w"].value) / total_samples);
}
if (e.childNodes == undefined) return;
for(var i = 0, c = e.childNodes; i < c.length; i++) {
zoom_reset(c[i]);
}
}
function zoom_child(e, x, zoomed_width_samples) {
if (e.tagName == "text") {
var parent_x = parseFloat(find_child(e.parentNode, "rect[x]").attributes.x.value);
e.attributes.x.value = format_percent(parent_x + (100 * 3 / frames.attributes.width.value));
} else if (e.tagName == "rect") {
e.attributes.x.value = format_percent(100 * (parseInt(e.attributes["fg:x"].value) - x) / zoomed_width_samples);
e.attributes.width.value = format_percent(100 * parseInt(e.attributes["fg:w"].value) / zoomed_width_samples);
}
if (e.childNodes == undefined) return;
for(var i = 0, c = e.childNodes; i < c.length; i++) {
zoom_child(c[i], x, zoomed_width_samples);
}
}
function zoom_parent(e) {
if (e.attributes) {
if (e.attributes.x != undefined) {
e.attributes.x.value = "0.0%";
}
if (e.attributes.width != undefined) {
e.attributes.width.value = "100.0%";
}
}
if (e.childNodes == undefined) return;
for(var i = 0, c = e.childNodes; i < c.length; i++) {
zoom_parent(c[i]);
}
}
function zoom(node) {
var attr = find_child(node, "rect").attributes;
var width = parseInt(attr["fg:w"].value);
var xmin = parseInt(attr["fg:x"].value);
var xmax = xmin + width;
var ymin = parseFloat(attr.y.value);
unzoombtn.classList.remove("hide");
var el = frames.children;
var to_update_text = [];
for (var i = 0; i < el.length; i++) {
var e = el[i];
var a = find_child(e, "rect").attributes;
var ex = parseInt(a["fg:x"].value);
var ew = parseInt(a["fg:w"].value);
// Is it an ancestor
if (!inverted) {
var upstack = parseFloat(a.y.value) > ymin;
} else {
var upstack = parseFloat(a.y.value) < ymin;
}
if (upstack) {
// Direct ancestor
if (ex <= xmin && (ex+ew) >= xmax) {
e.classList.add("parent");
zoom_parent(e);
to_update_text.push(e);
}
// not in current path
else
e.classList.add("hide");
}
// Children maybe
else {
// no common path
if (ex < xmin || ex >= xmax) {
e.classList.add("hide");
}
else {
zoom_child(e, xmin, width);
to_update_text.push(e);
}
}
}
update_text_for_elements(to_update_text);
}
function unzoom() {
unzoombtn.classList.add("hide");
var el = frames.children;
for(var i = 0; i < el.length; i++) {
el[i].classList.remove("parent");
el[i].classList.remove("hide");
zoom_reset(el[i]);
}
update_text_for_elements(el);
}
// search
function reset_search() {
var el = document.querySelectorAll("#frames rect");
for (var i = 0; i < el.length; i++) {
orig_load(el[i], "fill")
}
var params = get_params();
delete params.s;
history.replaceState(null, null, parse_params(params));
}
function search_prompt() {
if (!searching) {
var term = prompt("Enter a search term (regexp " +
"allowed, eg: ^ext4_)", "");
if (term != null) {
search(term)
}
} else {
reset_search();
searching = 0;
searchbtn.classList.remove("show");
searchbtn.firstChild.nodeValue = "Search"
matchedtxt.classList.add("hide");
matchedtxt.firstChild.nodeValue = ""
}
}
function search(term) {
var re = new RegExp(term);
var el = frames.children;
var matches = new Object();
var maxwidth = 0;
for (var i = 0; i < el.length; i++) {
var e = el[i];
// Skip over frames which are either not visible, or below the zoomed-to frame
if (e.classList.contains("hide") || e.classList.contains("parent")) {
continue;
}
var func = g_to_func(e);
var rect = find_child(e, "rect");
if (func == null || rect == null)
continue;
// Save max width. Only works as we have a root frame
var w = parseInt(rect.attributes["fg:w"].value);
if (w > maxwidth)
maxwidth = w;
if (func.match(re)) {
// highlight
var x = parseInt(rect.attributes["fg:x"].value);
orig_save(rect, "fill");
rect.attributes.fill.value = searchcolor;
// remember matches
if (matches[x] == undefined) {
matches[x] = w;
} else {
if (w > matches[x]) {
// overwrite with parent
matches[x] = w;
}
}
searching = 1;
}
}
if (!searching)
return;
var params = get_params();
params.s = term;
history.replaceState(null, null, parse_params(params));
searchbtn.classList.add("show");
searchbtn.firstChild.nodeValue = "Reset Search";
// calculate percent matched, excluding vertical overlap
var count = 0;
var lastx = -1;
var lastw = 0;
var keys = Array();
for (k in matches) {
if (matches.hasOwnProperty(k))
keys.push(k);
}
// sort the matched frames by their x location
// ascending, then width descending
keys.sort(function(a, b){
return a - b;
});
// Step through frames saving only the biggest bottom-up frames
// thanks to the sort order. This relies on the tree property
// where children are always smaller than their parents.
for (var k in keys) {
var x = parseInt(keys[k]);
var w = matches[keys[k]];
if (x >= lastx + lastw) {
count += w;
lastx = x;
lastw = w;
}
}
// display matched percent
matchedtxt.classList.remove("hide");
var pct = 100 * count / maxwidth;
if (pct != 100) pct = pct.toFixed(1);
matchedtxt.firstChild.nodeValue = "Matched: " + pct + "%";
}
function format_percent(n) {
return n.toFixed(4) + "%";
}
]]></script><rect x="0" y="0" width="100%" height="230" fill="url(#background)"/><text id="title" fill="rgb(0,0,0)" x="50.0000%" y="24.00">Flame Graph</text><text id="details" fill="rgb(0,0,0)" x="10" y="213.00"> </text><text id="unzoom" class="hide" fill="rgb(0,0,0)" x="10" y="24.00">Reset Zoom</text><text id="search" fill="rgb(0,0,0)" x="1190" y="24.00">Search</text><text id="matched" fill="rgb(0,0,0)" x="1190" y="213.00"> </text><svg id="frames" x="10" width="1180" total_samples="54903767"><g><title>[ld-linux-x86-64.so.2] (149,404 samples, 0.27%)</title><rect x="0.0000%" y="101" width="0.2721%" height="15" fill="rgb(227,0,7)" fg:x="0" fg:w="149404"/><text x="0.2500%" y="111.50"></text></g><g><title>[ld-linux-x86-64.so.2] (137,469 samples, 0.25%)</title><rect x="0.0217%" y="85" width="0.2504%" height="15" fill="rgb(217,0,24)" fg:x="11935" fg:w="137469"/><text x="0.2717%" y="95.50"></text></g><g><title>[ld-linux-x86-64.so.2] (137,469 samples, 0.25%)</title><rect x="0.0217%" y="69" width="0.2504%" height="15" fill="rgb(221,193,54)" fg:x="11935" fg:w="137469"/><text x="0.2717%" y="79.50"></text></g><g><title>[ld-linux-x86-64.so.2] (137,469 samples, 0.25%)</title><rect x="0.0217%" y="53" width="0.2504%" height="15" fill="rgb(248,212,6)" fg:x="11935" fg:w="137469"/><text x="0.2717%" y="63.50"></text></g><g><title>[ld-linux-x86-64.so.2] (137,469 samples, 0.25%)</title><rect x="0.0217%" y="37" width="0.2504%" height="15" fill="rgb(208,68,35)" fg:x="11935" fg:w="137469"/><text x="0.2717%" y="47.50"></text></g><g><title>[ld-linux-x86-64.so.2] (150,103 samples, 0.27%)</title><rect x="0.0000%" y="117" width="0.2734%" height="15" fill="rgb(232,128,0)" fg:x="0" fg:w="150103"/><text x="0.2500%" y="127.50"></text></g><g><title>[ld-linux-x86-64.so.2] (150,164 samples, 0.27%)</title><rect x="0.0000%" y="133" width="0.2735%" height="15" fill="rgb(207,160,47)" fg:x="0" fg:w="150164"/><text x="0.2500%" y="143.50"></text></g><g><title>[ld-linux-x86-64.so.2] (150,165 samples, 0.27%)</title><rect x="0.0000%" y="149" width="0.2735%" height="15" fill="rgb(228,23,34)" fg:x="0" fg:w="150165"/><text x="0.2500%" y="159.50"></text></g><g><title>[unknown] (54,753,263 samples, 99.73%)</title><rect x="0.2735%" y="149" width="99.7259%" height="15" fill="rgb(218,30,26)" fg:x="150165" fg:w="54753263"/><text x="0.5235%" y="159.50">[unknown]</text></g><g><title>sha3::sha3::keccak_permute (54,753,263 samples, 99.73%)</title><rect x="0.2735%" y="133" width="99.7259%" height="15" fill="rgb(220,122,19)" fg:x="150165" fg:w="54753263"/><text x="0.5235%" y="143.50">sha3::sha3::keccak_permute</text></g><g><title>all (54,903,767 samples, 100%)</title><rect x="0.0000%" y="181" width="100.0000%" height="15" fill="rgb(250,228,42)" fg:x="0" fg:w="54903767"/><text x="0.2500%" y="191.50"></text></g><g><title>sha3 (54,903,767 samples, 100.00%)</title><rect x="0.0000%" y="165" width="100.0000%" height="15" fill="rgb(240,193,28)" fg:x="0" fg:w="54903767"/><text x="0.2500%" y="175.50">sha3</text></g></svg></svg>

After

Width:  |  Height:  |  Size: 20 KiB

BIN
perf.data Normal file

Binary file not shown.

BIN
perf.data.old Normal file

Binary file not shown.

258
src/consts.rs Normal file
View File

@@ -0,0 +1,258 @@
pub const LFSR_LUT: [(bool, u8); 256] = [
(false, 0x00),
(true, 0x02),
(false, 0x04),
(true, 0x06),
(false, 0x08),
(true, 0x0a),
(false, 0x0c),
(true, 0x0e),
(false, 0x10),
(true, 0x12),
(false, 0x14),
(true, 0x16),
(false, 0x18),
(true, 0x1a),
(false, 0x1c),
(true, 0x1e),
(false, 0x20),
(true, 0x22),
(false, 0x24),
(true, 0x26),
(false, 0x28),
(true, 0x2a),
(false, 0x2c),
(true, 0x2e),
(false, 0x30),
(true, 0x32),
(false, 0x34),
(true, 0x36),
(false, 0x38),
(true, 0x3a),
(false, 0x3c),
(true, 0x3e),
(false, 0x40),
(true, 0x42),
(false, 0x44),
(true, 0x46),
(false, 0x48),
(true, 0x4a),
(false, 0x4c),
(true, 0x4e),
(false, 0x50),
(true, 0x52),
(false, 0x54),
(true, 0x56),
(false, 0x58),
(true, 0x5a),
(false, 0x5c),
(true, 0x5e),
(false, 0x60),
(true, 0x62),
(false, 0x64),
(true, 0x66),
(false, 0x68),
(true, 0x6a),
(false, 0x6c),
(true, 0x6e),
(false, 0x70),
(true, 0x72),
(false, 0x74),
(true, 0x76),
(false, 0x78),
(true, 0x7a),
(false, 0x7c),
(true, 0x7e),
(false, 0x80),
(true, 0x82),
(false, 0x84),
(true, 0x86),
(false, 0x88),
(true, 0x8a),
(false, 0x8c),
(true, 0x8e),
(false, 0x90),
(true, 0x92),
(false, 0x94),
(true, 0x96),
(false, 0x98),
(true, 0x9a),
(false, 0x9c),
(true, 0x9e),
(false, 0xa0),
(true, 0xa2),
(false, 0xa4),
(true, 0xa6),
(false, 0xa8),
(true, 0xaa),
(false, 0xac),
(true, 0xae),
(false, 0xb0),
(true, 0xb2),
(false, 0xb4),
(true, 0xb6),
(false, 0xb8),
(true, 0xba),
(false, 0xbc),
(true, 0xbe),
(false, 0xc0),
(true, 0xc2),
(false, 0xc4),
(true, 0xc6),
(false, 0xc8),
(true, 0xca),
(false, 0xcc),
(true, 0xce),
(false, 0xd0),
(true, 0xd2),
(false, 0xd4),
(true, 0xd6),
(false, 0xd8),
(true, 0xda),
(false, 0xdc),
(true, 0xde),
(false, 0xe0),
(true, 0xe2),
(false, 0xe4),
(true, 0xe6),
(false, 0xe8),
(true, 0xea),
(false, 0xec),
(true, 0xee),
(false, 0xf0),
(true, 0xf2),
(false, 0xf4),
(true, 0xf6),
(false, 0xf8),
(true, 0xfa),
(false, 0xfc),
(true, 0xfe),
(false, 0x71),
(true, 0x73),
(false, 0x75),
(true, 0x77),
(false, 0x79),
(true, 0x7b),
(false, 0x7d),
(true, 0x7f),
(false, 0x61),
(true, 0x63),
(false, 0x65),
(true, 0x67),
(false, 0x69),
(true, 0x6b),
(false, 0x6d),
(true, 0x6f),
(false, 0x51),
(true, 0x53),
(false, 0x55),
(true, 0x57),
(false, 0x59),
(true, 0x5b),
(false, 0x5d),
(true, 0x5f),
(false, 0x41),
(true, 0x43),
(false, 0x45),
(true, 0x47),
(false, 0x49),
(true, 0x4b),
(false, 0x4d),
(true, 0x4f),
(false, 0x31),
(true, 0x33),
(false, 0x35),
(true, 0x37),
(false, 0x39),
(true, 0x3b),
(false, 0x3d),
(true, 0x3f),
(false, 0x21),
(true, 0x23),
(false, 0x25),
(true, 0x27),
(false, 0x29),
(true, 0x2b),
(false, 0x2d),
(true, 0x2f),
(false, 0x11),
(true, 0x13),
(false, 0x15),
(true, 0x17),
(false, 0x19),
(true, 0x1b),
(false, 0x1d),
(true, 0x1f),
(false, 0x01),
(true, 0x03),
(false, 0x05),
(true, 0x07),
(false, 0x09),
(true, 0x0b),
(false, 0x0d),
(true, 0x0f),
(false, 0xf1),
(true, 0xf3),
(false, 0xf5),
(true, 0xf7),
(false, 0xf9),
(true, 0xfb),
(false, 0xfd),
(true, 0xff),
(false, 0xe1),
(true, 0xe3),
(false, 0xe5),
(true, 0xe7),
(false, 0xe9),
(true, 0xeb),
(false, 0xed),
(true, 0xef),
(false, 0xd1),
(true, 0xd3),
(false, 0xd5),
(true, 0xd7),
(false, 0xd9),
(true, 0xdb),
(false, 0xdd),
(true, 0xdf),
(false, 0xc1),
(true, 0xc3),
(false, 0xc5),
(true, 0xc7),
(false, 0xc9),
(true, 0xcb),
(false, 0xcd),
(true, 0xcf),
(false, 0xb1),
(true, 0xb3),
(false, 0xb5),
(true, 0xb7),
(false, 0xb9),
(true, 0xbb),
(false, 0xbd),
(true, 0xbf),
(false, 0xa1),
(true, 0xa3),
(false, 0xa5),
(true, 0xa7),
(false, 0xa9),
(true, 0xab),
(false, 0xad),
(true, 0xaf),
(false, 0x91),
(true, 0x93),
(false, 0x95),
(true, 0x97),
(false, 0x99),
(true, 0x9b),
(false, 0x9d),
(true, 0x9f),
(false, 0x81),
(true, 0x83),
(false, 0x85),
(true, 0x87),
(false, 0x89),
(true, 0x8b),
(false, 0x8d),
(true, 0x8f),
];

View File

@@ -1,3 +1,4 @@
pub mod consts;
pub mod sha3;
#[cfg(test)]

View File

@@ -1,26 +1,48 @@
use std::{env, fs::File, io::Read, time};
use sha3::sha3::Sha3_256;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
eprintln!("Usage: {} <filename>", args[0]);
std::process::exit(1);
}
let filename = &args[1];
let mut file = File::open(filename).unwrap();
let mut file_data = Vec::new();
file.read_to_end(&mut file_data).unwrap();
let mut sha = Sha3_256::default();
// println!("{:?}", (0x01 as u64).to_ne_bytes());
let text = "hola";
// let text = "hola";
sha.absorb(text.as_bytes());
let res = sha.squeeze();
let now = time::Instant::now();
let expected_res: [u8; 32] = [
0x8a, 0xf1, 0x3d, 0x92, 0x44, 0x61, 0x8e, 0xee, 0x87, 0x6d, 0x04, 0x31, 0xf3, 0x44, 0x9a,
0xa4, 0xff, 0x95, 0x27, 0x4c, 0xa3, 0xe7, 0xe5, 0xc6, 0x54, 0x19, 0x79, 0x49, 0x9f, 0x5b,
0x85, 0xde,
];
sha.absorb(&file_data);
let res: [u8; 32] = sha.squeeze();
let elapsed = now.elapsed().as_micros() as f32;
// let expected_res: [u8; 32] = [
// 0x8a, 0xf1, 0x3d, 0x92, 0x44, 0x61, 0x8e, 0xee, 0x87, 0x6d, 0x04, 0x31, 0xf3, 0x44, 0x9a,
// 0xa4, 0xff, 0x95, 0x27, 0x4c, 0xa3, 0xe7, 0xe5, 0xc6, 0x54, 0x19, 0x79, 0x49, 0x9f, 0x5b,
// 0x85, 0xde,
// ];
print!("SHA3-256: ");
for i in 0..32 {
print!("{:#001x} ", res[i]);
print!("{:x}", res[i]);
}
println!();
assert!(res == expected_res);
println!("FUNCIONAAAAA");
println!("Time taken: {} ms", elapsed / 1000_f32);
// assert!(res == expected_res);
}

View File

@@ -5,37 +5,42 @@
use std::array;
use crate::consts::LFSR_LUT;
const RATE_256: usize = 136;
const TOTAL_STATE_SIZE: usize = 200;
const TOTAL_STATE_SIZE_U64: usize = 25;
const ROUNDS: usize = 24;
const DELIMITER_SUFFIX: u8 = 0x06; // delimiter suffix for sha3
#[derive(Debug)]
pub struct Sha3_256 {
state: [u8; TOTAL_STATE_SIZE],
state: [u64; TOTAL_STATE_SIZE_U64],
}
impl Default for Sha3_256 {
fn default() -> Self {
Self {
state: [0; TOTAL_STATE_SIZE],
state: [0; TOTAL_STATE_SIZE_U64],
}
}
}
impl Sha3_256 {
pub fn absorb(&mut self, input: &[u8]) {
// let (inputs_u64, rem) = input.as_chunks::<8>();
let state_u8 = [u8; 200];
// Xor input with rate
let mut remaining = input.len();
let mut off = 0;
let mut in_len = 0;
while remaining > 0 {
in_len = remaining.min(RATE_256);
println!("{}", in_len);
for i in 0..in_len {
self.state[i] ^= input[i + off];
}
off += in_len - 1;
off += in_len;
remaining -= in_len;
if in_len == RATE_256 {
@@ -44,6 +49,10 @@ impl Sha3_256 {
}
}
// for bytes in inputs_u64 {
// }
self.state[in_len] ^= DELIMITER_SUFFIX;
if (DELIMITER_SUFFIX & 0x80) != 0 && in_len == RATE_256 - 1 {
@@ -69,35 +78,35 @@ impl Sha3_256 {
keccak_permute(&mut self.state);
}
}
// *self.state.first_chunk().unwrap()
res
}
}
fn keccak_permute(input: &mut [u8; TOTAL_STATE_SIZE]) {
let (lanes, _) = input.as_chunks_mut::<8>();
// let (lanes, _) = input.as_chunks_mut::<8>();
let mut lfsr_state = 0x01_u8;
for _ in 0..ROUNDS {
// θ step
let c: [u64; 5] = array::from_fn(|x| {
get_lane(lanes, x, 0)
^ get_lane(lanes, x, 1)
^ get_lane(lanes, x, 2)
^ get_lane(lanes, x, 3)
^ get_lane(lanes, x, 4)
get_lane2(input, x, 0)
^ get_lane2(input, x, 1)
^ get_lane2(input, x, 2)
^ get_lane2(input, x, 3)
^ get_lane2(input, x, 4)
});
let mut d: u64;
for x in 0..5 {
d = c[(x + 4) % 5] ^ rol64(c[(x + 1) % 5], 1);
for y in 0..5 {
xor_lane(d, lanes, x, y);
xor_lane2(d, input, x, y);
}
}
// ρ and π steps
let (mut x, mut y) = (1, 0);
let mut current = get_lane(lanes, x, y);
let mut current = get_lane2(input, x, y);
let mut temp: u64;
for t in 0..24 {
@@ -106,8 +115,8 @@ fn keccak_permute(input: &mut [u8; TOTAL_STATE_SIZE]) {
x = y;
y = y2;
temp = get_lane(lanes, x, y);
set_lane(rol64(current, r), x, y, lanes);
temp = get_lane2(input, x, y);
set_lane2(rol64(current, r), x, y, input);
current = temp;
}
@@ -115,14 +124,14 @@ fn keccak_permute(input: &mut [u8; TOTAL_STATE_SIZE]) {
let mut temp2 = [0_u64; 5];
for y in 0..5 {
for x in 0..5 {
temp2[x] = get_lane(lanes, x, y);
temp2[x] = get_lane2(input, x, y);
}
for x in 0..5 {
set_lane(
set_lane2(
temp2[x] ^ ((!temp2[(x + 1) % 5]) & temp2[(x + 2) % 5]),
x,
y,
lanes,
input,
);
}
}
@@ -131,8 +140,14 @@ fn keccak_permute(input: &mut [u8; TOTAL_STATE_SIZE]) {
for j in 0..7 {
let bit_pos: usize = (1 << j) - 1;
if lfsr86540(&mut lfsr_state) {
xor_lane((1 as u64) << bit_pos, lanes, 0, 0);
let (lfsr_out, new_lfsr) = LFSR_LUT[lfsr_state as usize];
lfsr_state = new_lfsr;
// if lfsr86540(&mut lfsr_state) {
// xor_lane((1 as u64) << bit_pos, lanes, 0, 0);
// }
if lfsr_out {
xor_lane2((1 as u64) << bit_pos, input, 0, 0);
}
}
}
@@ -143,11 +158,22 @@ fn get_lane(lanes: &[[u8; 8]], x: usize, y: usize) -> u64 {
u64::from_ne_bytes(lanes[x + 5 * y])
}
#[inline]
fn get_lane2(lanes: &[64; TOTAL_STATE_SIZE], x: usize, y: usize) -> u64 {
u64::from_ne_bytes(lanes[x + 5 * y..x + 5 * y + 8].try_into().unwrap())
}
#[inline]
fn set_lane(lane: u64, x: usize, y: usize, lanes: &mut [[u8; 8]]) {
lanes[x + 5 * y] = lane.to_ne_bytes();
}
#[inline]
fn set_lane2(lane: u64, x: usize, y: usize, lanes: &mut [u8; TOTAL_STATE_SIZE]) {
// lanes[x + 5 * y] = lane.to_ne_bytes();
lanes[x + 5 * y..x + 5 * y + 8].copy_from_slice(&lane.to_ne_bytes());
}
#[inline]
fn rol64(v: u64, off: usize) -> u64 {
((v) << off) ^ ((v) >> (64 - off))
@@ -157,15 +183,20 @@ fn rol64(v: u64, off: usize) -> u64 {
fn xor_lane(lane: u64, lanes: &mut [[u8; 8]], x: usize, y: usize) {
set_lane(get_lane(lanes, x, y) ^ lane, x, y, lanes);
}
#[inline]
fn xor_lane2(lane: u64, lanes: &mut [u8; TOTAL_STATE_SIZE], x: usize, y: usize) {
set_lane2(get_lane2(lanes, x, y) ^ lane, x, y, lanes);
}
// Function that computes the linear feedback shift register (LFSR)
// I have absolutely no idea wtf is this shit. Copied from a github repo lol.
fn lfsr86540(lfsr: &mut u8) -> bool {
let res = (*lfsr & 0x01) != 0;
if (*lfsr & 0x80) != 0 {
*lfsr = (*lfsr << 1) ^ 0x71;
} else {
*lfsr <<= 1;
}
res
}
// SUSCEPTIBLE TO BE CONVERTED INTO A TABLE
// fn lfsr86540(lfsr: &mut u8) -> bool {
// let res = (*lfsr & 0x01) != 0;
// if (*lfsr & 0x80) != 0 {
// *lfsr = (*lfsr << 1) ^ 0x71;
// } else {
// *lfsr <<= 1;
// }
// res
// }