Skip to content

Commit 7c0b10f

Browse files
authored
Merge pull request #5 from yfxu/temp-hashing
temporary hashing post commit
2 parents 76541f0 + 5311618 commit 7c0b10f

File tree

20 files changed

+360
-35
lines changed

20 files changed

+360
-35
lines changed

content/about/_index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Hi, I'm Yifei (逸飞)!
88

99
This is my personal website where I maintain a very cool blog and share various photos I've taken on my camera (FujiFilm X100) and on my smartphone (Samsung Galaxy S9).
1010

11-
This website doesn't use any JavaScript or cookies, just some plain HTML and CSS built with Hugo, hosted on GitHub Pages. The website theme was designed and coded by myself ! :D !
11+
This website doesn't use any cookies, and for the most part doesn't use any JavaScript. Pages that do contain scripting will indicate so at the top of the page. This website is built with Hugo, and is hosted on GitHub Pages. The website theme was designed and coded by myself ! :D !
1212

1313
## life
1414

content/gallery/hypnosis.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ location: "University of Waterloo, SCH to Arts Tunnel"
66
imageUrl: "https://live.staticflickr.com/65535/53713021703_83ddf8ec50_o.jpg"
77
width: 2870
88
height: 4310
9-
---
9+
---
10+
11+
One time during university, my friend and I 1v1'ed each other here in a fierce battle of the [penis game](https://www.urbandictionary.com/define.php?term=the+penis+game).

content/gallery/solar-eclipse.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ width: 4310
88
height: 2870
99
---
1010

11-
First in my life experiencing a total solar eclipse, and holy shit that was magical. Unfortunately I didn't have a zoom lens so this photo hopefully captures more accurately what the real experience is like seeing the sun through eclipse glasses.
11+
First time in my life experiencing a total solar eclipse, and holy shit was that magical. Unfortunately I didn't have a zoom lens so this photo hopefully captures more accurately what the real experience is like seeing the sun through eclipse glasses.
1212

1313
A few weeks before the eclipse, I suggested to one of my good friends that we organize a small trip to see the total solar eclipse. That small group ended up becoming 10 or so people, and we struggled for a while coming to a decision on where to go. Initially we were thinking of going to Niagara Falls. It was right under the path of totality, and there were a lot of fun things to do in the area while we waited. Buuuuut eventually we all came to realize that the other six million people living in the GTA were all going to go there as well, so we figured we'd go somewhere else with hopefully fewer people. Spoiler alert: Niagara Falls ended up being completely clouded out for the entire eclipse ! :D !
1414

content/posts/hashing.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
title: "SHA-256"
3+
date: 2025-03-05
4+
draft: false
5+
scripts: ["hash.js"]
6+
stylesheets: ["hash"]
7+
---
8+
9+
*The data visualizations in this post may be more legible on a light colour-scheme.*
10+
11+
I had this sudden idea to visualize each and every single bit of a SHA-256 hash in a heatmap-style visual, not really sure where the inspiration came from.
12+
13+
We generally know that SHA-256 is pretty secure (for now), but aside from just trusting that it works, I've never really stopped to understand nor proven to myself that it truly is secure.
14+
15+
Now I'm not really a mathematician, but I _do_ have some rapidly decaying leftover memories from [ECE 307 - Probability Theory and Statistics 2](https://ucalendar.uwaterloo.ca/2324/COURSE/course-ECE.html#ECE307), so let's run some un-scientific tests to see if we can find any predictable patterns in how SHA-256 hashes are computed.
16+
17+
One of the craziest things to me is that this algorithm is supposed to be able to generate two virtually indistinguishable hashes from two nearly-identical strings. You'd think that the difference between `0x61` ('a') and `0x63` ('c') is pretty minute right? Bit-wise, they differ by 1 bit-flip in the 2nd least significant bit.
18+
19+
```
20+
'a' -> 0x61 -> 01100001
21+
'c' -> 0x63 -> 01100011
22+
```
23+
24+
Below, I've displayed two heatmaps for the SHA-256 hashes of both 'a' and 'c'. Each column of the heatmap corresponds to one byte of the 32 byte long hash, and each cell corresponds to one of the eight bits in that byte. The left-most column displays the most significant byte, and the top of each column represents the most significant bit.
25+
26+
{{< hash id="hash-a" caption="SHA-256 hash of UTF-8 string 'a'" >}}
27+
<br>
28+
{{< hash id="hash-c" caption="SHA-256 hash of UTF-8 string 'c'" >}}
29+
30+
It's pretty hard to compare these two visualizations at a glance, so let's overlay them on top of each other.
31+
32+
{{< hash id="hash-a-c" caption="SHA-256 hashes of UTF-8 string 'a' & 'c' overlaid on top of each other" >}}
33+
34+
I don't know about you, but I don't really see any obvious patterns going on here. The
35+
36+
# Playground
37+
38+
Before we begin, here's a little interactive sandbox to compute the SHA-256 hash of any text.
39+
40+
{{< hash id="table" >}}
41+
<table id="hash" class="hash-grid">
42+
<tr><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td><td><div></div></td></tr>
43+
</table>
44+
<input type="text" oninput="update(this.value);" id="input" placeholder="type here" autocomplete="off">
45+
46+
Now that that's out of the way, let's begin with test #1.

content/posts/sdvx-controller.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
title: "Sound Voltex Controller: Embedded Systems Project (Ongoing)"
3+
date: 2024-07-05
4+
draft: true
5+
---
6+
7+
## Intro
8+
9+
I've decided to start making my own personal [Sound Voltex](https://remywiki.com/What_is_SOUND_VOLTEX) rhythm game controller. It'll be a project that involves electronics, maybe some PCB design, embedded programming, and 3D design.
10+
11+
## Why
12+
13+
While I was co-oping in Tokyo, I found myself visiting rhythm game arcades a lot. A few games that I really stuck with were *Chunithm*, *Dance Dance Revolution*, and *Sound Voltex*.
14+
15+
## Parts
16+
17+
I haven't yet picked out specific parts. I'll need:
18+
19+
- 2 rotary encoders (100-200 PPR minimum)
20+
- 7 buttons (probably mechanical key switches)

hugo.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,9 @@ menus:
4848
weight: 20
4949
- name: github
5050
url: "https://github.com/yfxu"
51-
weight: 30
51+
weight: 30
52+
markup:
53+
goldmark:
54+
renderer:
55+
unsafe: true
56+
enableGitInfo: true

themes/ennui/assets/js/hash.js

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
const textEncoder = new TextEncoder();
2+
const table = document.getElementById("table");
3+
const rows = table.getElementsByTagName("tr");
4+
const hashRow = document.getElementById("hash").children[0].children[0].children;
5+
6+
async function update(text) {
7+
const hash = await crypto.subtle
8+
.digest("SHA-256", textEncoder.encode(text))
9+
.then((hashBuffer) => {
10+
const hashArray = Array.from(new Uint8Array(hashBuffer));
11+
return hashArray;
12+
});
13+
var i = 0;
14+
hash.forEach((byte) => {
15+
for (var j = 0; j < 8; j++) {
16+
var bitwiseAnd = byte & Math.pow(2, j);
17+
if (bitwiseAnd > 0) {
18+
rows[7 - j].children[i].children[0].className = "set";
19+
} else {
20+
rows[7 - j].children[i].children[0].className = "";
21+
}
22+
}
23+
i++;
24+
});
25+
26+
for (var i = 0; i < 32; i++) {
27+
var byteString = hash[i].toString(16).padStart(2, "0");
28+
hashRow[i].children[0].innerHTML = byteString;
29+
}
30+
}
31+
32+
async function draw(id, texts) {
33+
const staticTable = document.getElementById(id);
34+
const staticRows = staticTable.getElementsByTagName("tr");
35+
36+
const hashes = texts.map(async (text) => {
37+
return await crypto.subtle
38+
.digest("SHA-256", textEncoder.encode(text))
39+
.then((hashBuffer) => {
40+
const hashArray = Array.from(new Uint8Array(hashBuffer));
41+
return hashArray;
42+
})
43+
});
44+
45+
var opacityValues = [
46+
[
47+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
48+
0, 0, 0, 0, 0, 0, 0,
49+
],
50+
[
51+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52+
0, 0, 0, 0, 0, 0, 0,
53+
],
54+
[
55+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56+
0, 0, 0, 0, 0, 0, 0,
57+
],
58+
[
59+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
60+
0, 0, 0, 0, 0, 0, 0,
61+
],
62+
[
63+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64+
0, 0, 0, 0, 0, 0, 0,
65+
],
66+
[
67+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68+
0, 0, 0, 0, 0, 0, 0,
69+
],
70+
[
71+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72+
0, 0, 0, 0, 0, 0, 0,
73+
],
74+
[
75+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76+
0, 0, 0, 0, 0, 0, 0,
77+
],
78+
];
79+
80+
Promise.all(hashes).then((values) => {
81+
values.forEach((hash) => {
82+
var i = 0;
83+
hash.forEach((byte) => {
84+
for (var j = 0; j < 8; j++) {
85+
var bitwiseAnd = byte & Math.pow(2, j);
86+
if (bitwiseAnd > 0) {
87+
staticRows[7 - j].children[i].children[0].className = "set";
88+
opacityValues[7 - j][i] += 1 / texts.length;
89+
}
90+
}
91+
i++;
92+
});
93+
});
94+
95+
for (var i = 0; i < 8; i++) {
96+
for (var j = 0; j < 32; j++) {
97+
staticRows[i].children[j].children[0].style.opacity =
98+
opacityValues[i][j];
99+
}
100+
}
101+
});
102+
}
103+
104+
document.addEventListener(
105+
"DOMContentLoaded",
106+
function () {
107+
update("");
108+
draw("hash-a", ["a"]);
109+
draw("hash-c", ["c"]);
110+
draw("hash-a-c", ["a", "c"]);
111+
},
112+
false
113+
);
114+
115+
window.textEncoder = textEncoder;
116+
window.rows = rows;
117+
window.update = update;
118+
window.hashRow = hashRow;
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
:root {
2-
--color-background: #ffffff;
2+
--color-background: #f0f2f8;
3+
--color-background-secondary: #e9e9e9;
4+
--color-background-tertiary: #ffffff;
35
--color-text-primary: #3b393d;
4-
--color-text-secondary: #a6a9ad;
5-
--color-accent: #45b694;
6+
--color-text-secondary: #929497;
7+
--color-accent: #3d37ec;
68
--max-width: 600px;
79
--mobile-width: 450px;
810
}
911

1012
@media (prefers-color-scheme: dark) {
1113
:root {
12-
--color-background: #2B2A33;
14+
--color-background: #2b2a33;
15+
--color-background-secondary: #323238;
16+
--color-background-tertiary: #26242b;
1317
--color-text-primary: #ede3dd;
1418
--color-text-secondary: #747a7a;
15-
--color-accent: #03CEA4;
19+
--color-accent: #5a5ae7;
1620
}
1721
}

themes/ennui/assets/scss/hash.scss

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
table.hash-grid {
2+
width: calc(100% + 4px);
3+
border-collapse: separate;
4+
border-spacing: 2px;
5+
margin: 0 -2px;
6+
7+
td {
8+
padding: 0;
9+
background-color: var(--color-background-secondary);
10+
11+
div {
12+
font-family: monospace;
13+
font-size: 0.625rem;
14+
text-align: center;
15+
aspect-ratio: 1;
16+
padding: 0;
17+
margin: 0;
18+
19+
&.set {
20+
background-color: var(--color-accent);
21+
}
22+
}
23+
}
24+
25+
caption {
26+
caption-side: bottom;
27+
font-size: 0.75rem;
28+
font-style: italic;
29+
}
30+
}
31+
32+
33+
table#hash td {
34+
line-height: 1rem;
35+
height: auto;
36+
background-color: var(--color-background-tertiary);
37+
}
38+
39+
div.centre {
40+
display: flex;
41+
justify-content: center;
42+
}
43+
44+
input#input {
45+
width: 100%;
46+
height: 1.5rem;
47+
text-align: center;
48+
outline: none;
49+
border: none;
50+
margin: auto;
51+
background-color: var(--color-background-secondary);
52+
color: var(--color-text-primary);
53+
padding: 0;
54+
}
55+
56+
input#input:focus {
57+
outline: none;
58+
}

themes/ennui/assets/scss/main.scss

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,18 @@ body {
3333
min-height: 100vh;
3434
}
3535

36+
div.section {
37+
width: 100%;
38+
39+
&.highlight {
40+
background-color: var(--color-background-tertiary);
41+
}
42+
}
43+
3644
div.name-header {
3745
text-transform: lowercase;
3846
margin: 1rem auto;
39-
text-align: center;
47+
// text-align: center;
4048

4149
h1 { margin: 0 }
4250
h4 {
@@ -76,9 +84,12 @@ div.gallery {
7684
nav.main-nav {
7785
@include flex-row();
7886
justify-content: space-evenly;
79-
padding-bottom: 1rem;
8087
column-gap: 1rem;
81-
width: 100%
88+
width: 100%;
89+
90+
a {
91+
font-weight: bold;
92+
}
8293
}
8394

8495
footer {
@@ -91,6 +102,10 @@ footer {
91102
}
92103
}
93104

105+
div#git-hash {
106+
font-family: monospace;
107+
}
108+
94109
blockquote {
95110
border-left: 4px solid var(--color-accent);
96111
margin-left: 0;
@@ -148,13 +163,15 @@ div.image-info, div.post-info {
148163
}
149164
}
150165

151-
p.image-time, p.post-time {
166+
td.image-time, td.post-time {
152167
margin: 0;
153168
font-size: 0.75rem;
154169
font-weight: bold;
155170

156-
svg {
171+
> svg {
157172
margin-right: 0.25em;
173+
width: 1rem;
174+
fill: var(--color-text-secondary);
158175
}
159176
}
160177
}
@@ -240,4 +257,8 @@ div.home-container {
240257
column-gap: 1rem;
241258
}
242259
}
260+
}
261+
262+
.secondary-font {
263+
font-family: monospace;
243264
}

0 commit comments

Comments
 (0)