Blog illustrations

This commit is contained in:
Pascal Engélibert 2026-06-23 20:22:16 +02:00
commit abcb3137f1
6 changed files with 89 additions and 16 deletions

View file

@ -4,6 +4,8 @@ GNU AGPL v3, CopyLeft 2025 Pascal Engélibert [(why copyleft?)](https://txmn.tk/
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.
This program's output may be licensed as you wish, no obligation to credit and provide a link to the source code, even if it's always better ;)
"""
import math
@ -53,23 +55,24 @@ SVG = """\
"""
class Block:
def __init__(self, svg, x, y, r):
def __init__(self, svg, x, y, rx, ry=None):
self.svg = svg
self.x = x
self.y = y
self.r = r
self.rx = rx
self.ry = ry if ry != None else rx
def to(self, block):
if self.x == block.x:
if self.y > block.y:
self.svg.t += arrow(self.x, self.y-self.r, block.x, block.y+block.r)
self.svg.t += arrow(self.x, self.y-self.ry, block.x, block.y+block.ry)
else:
self.svg.t += arrow(self.x, self.y+self.r, block.x, block.y-block.r)
self.svg.t += arrow(self.x, self.y+self.ry, block.x, block.y-block.ry)
elif self.y == block.y:
if self.x > block.x:
self.svg.t += arrow(self.x-self.r, self.y, block.x+block.r, block.y)
self.svg.t += arrow(self.x-self.rx, self.y, block.x+block.rx, block.y)
else:
self.svg.t += arrow(self.x+self.r, self.y, block.x-block.r, block.y)
self.svg.t += arrow(self.x+self.rx, self.y, block.x-block.rx, block.y)
XOR_R = 8
ENCRYPT_SIZE = 32
@ -126,12 +129,12 @@ class Svg:
"""
return Block(self, x, y, XOR_R)
def encrypt(self, x, y):
def encrypt(self, x, y, text="E"):
xl = x-ENCRYPT_SIZE//2
yt = y-ENCRYPT_SIZE//2
self.t += f"""\
<rect x="{xl}" y="{yt}" width="{ENCRYPT_SIZE}" height="{ENCRYPT_SIZE}"/>
<text class="t" x="{x}" y="{y}">E</text>
<text class="t" x="{x}" y="{y}">{text}</text>
"""
return Block(self, x, y, ENCRYPT_SIZE//2)
@ -164,7 +167,13 @@ class Svg:
tx_ = (tx+0.5)*cell_w+xl
ty_ = (ty+0.5)*cell_h+yt
self.t += f"""<text class="t" x="{tx_}" y="{ty_}">{t}</text>\n"""
return Block(self, x, y, ENCRYPT_SIZE//2)
for (x1, y1, x2, y2) in borders:
x1_ = x1*cell_w+xl
y1_ = y1*cell_h+yt
x2_ = x2*cell_w+xl
y2_ = y2*cell_h+yt
self.t += f"""<line x1="{x1_}" y1="{y1_}" x2="{x2_}" y2="{y2_}"/>\n"""
return Block(self, x, y, w//2, h//2)
def knot(self, x, y):
self.t += f"""\
@ -380,13 +389,58 @@ def chacha_encryption():
(0.5, 3, "count"),
(2.5, 3, "nonce"),
],
[])
P = s.text(16, 144, "P")
E = s.encrypt(64, 96)
X = s.xor(64, 144)
C = s.text(64, 180, "C")
[
(0, 1, 4, 1),
(0, 3, 4, 3),
(2, 3, 2, 4),
])
P = s.text(16, 160, "P")
E = s.encrypt(64, 112)
X = s.xor(64, 160)
C = s.text(64, 200, "C")
B.to(E)
E.to(X)
P.to(X)
X.to(C)
return SVG.format(body=s.t, title="ChaCha Encryption", w=372, h=192, **ARGS)
return SVG.format(body=s.t, title="ChaCha Encryption", w=128, h=224, **ARGS)
def chacha_xts():
s = Svg()
B = s.block(64, 96, 4, 4, [
(1.5, 0, "const"),
(1.5, 1.5, "K"),
(0.5, 3, "count"),
(2.5, 3, "nonce"),
],
[
(0, 1, 4, 1),
(0, 3, 4, 3),
(2, 3, 2, 4),
])
P = s.text(304, 16, "P")
X1 = s.xor(304, 56)
E1 = s.encrypt(304, 96, 'E<tspan dy="6">r</tspan>')
X2 = s.xor(304, 144)
C = s.text(304, 180, "C")
E2 = s.encrypt(176, 96)
J = s.text(240, 16, "j")
A = s.square(240, 96, '×α <tspan dy="-8">j</tspan>')
B.to(E2)
P.to(X1)
X1.to(E1)
E1.to(X2)
X2.to(C)
E2.to(A)
J.to(A)
s.t += arrow_path([(256,96), (272,96), (272,56), (296,56)])
s.t += arrow_path([(256,96), (272,96), (272,144), (296,144)])
return SVG.format(body=s.t, title="XTS", w=372, h=192, **ARGS)
def save(name, data):
f = open(f"{name}.svg", "w")
@ -399,3 +453,4 @@ if __name__ == "__main__":
save("cbc", cbc())
save("xts", xts())
save("../flash-filesystem-encryption-2/chacha-encryption", chacha_encryption())
save("../flash-filesystem-encryption-2/chacha-xts", chacha_xts())

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View file

@ -9,6 +9,10 @@ tags = ["cryptography", "ESP32"]
katex = true
+++
![Illustration picture: DIE of a flash memory showing beautiful light interference](illustration.webp)
_Illustration: CC By-SA 4.0 by [MacroWorld21 on Wikimedia Commons](https://commons.wikimedia.org/wiki/File:AMD_and_Fujitsu_Flash_Memory_Chip_from_1997.png)_
One of my long-term projects is an ESP32-based phone, using an SD card for storage. Then, why not encrypting the SD card?
_In this post, we first explain the basics of filesystem encryption, then explore ways to apply it to the case of an embedded device and flash memory. This last part is quite rarely analyzed in the literature._
@ -194,6 +198,12 @@ The fastest is XTS with one key (and salted sector number) and long sectors.
Sectors must not be too long, however, as random access to block j needs computing all j successive powers of $\alpha$. 32 blocks may be a good value, as it matches flash erase size.
### Erase size and program size
Damn, I forgot to tell about erasing and programming flash memories!
Flash memories work in a peculiar way: you first have to erase some part of the memory (by filling it with ones) then you can write data by replacing some zeros with ones. But that's not all. Each operation has a minimum size. You can generally (it depends on the chip) program down to 16 bytes, but you can only erase by chunks of (again, generally) 512 bytes!
## The key
### Deriving the key from a password
@ -222,7 +232,7 @@ If an adversary **steals your device**, they may copy your encrypted data before
**Data can be scrambled.** Altering encrypted blocks will produce valid garbage plaintexts, which may or may not be detected, depending on what files or filesystem structures are affected. Again LittleFS partly mitigates this issue, because every bit of data is covered by a checksum. A checksum is not a cryptographic tool as it has low entropy and is malleable, and its goal is to detect hardware faults, not attacks. However as XTS is not bitwise malleable, it may contribute to render active attacks harder, as a scrambled block can be marked as faulty.
**Why not authenticate?** We could write authentication tags along the data (e.g. AES-GCM, HMAC), but that would be very expensive to compute. It would also break the 1:1 correspondance between ciphertext blocks and plaintext blocks, that is vital to its performance. We would need either to write all authentication tags to a different partition (out of the filesystem, hence causing performance issues), or to make encryption part of the filesystem itself, which is a lot of work.
**Why not authenticate?** We could write authentication tags along the data (e.g. AES-GCM, HMAC), but that would be very expensive to compute. It would also break the 1:1 correspondance between ciphertext blocks and plaintext blocks, that is vital for performance. We would need either to write all authentication tags to a different partition (out of the filesystem, hence causing performance issues), or to make encryption part of the filesystem itself, which is a lot of work.
## Conclusion

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View file

@ -7,6 +7,10 @@ insert_anchor_links = "left"
tags = ["politique"]
+++
![Illustration picture: Numerous files on shelves from the archives of the Stasi](illustration.webp)
_Illustration: [Bundesarchiv, Bild 183-1989-1204-023 / Heinz Hirndorf / CC-BY-SA 3.0](https://commons.wikimedia.org/wiki/File:Bundesarchiv_Bild_183-1989-1204-023,_Erfurt,_Bezirks-Archiv_des_Ministeriums_f%C3%BCr_Staatssicherheit.jpg)_
Même si vous n'avez rien à cacher, voici quelques raisons de vous soucier de la surveillance généralisée.
## Une expérimentation policière illégale est une future loi

View file

@ -8,6 +8,10 @@ draft = false
tags = ["politics"]
+++
![Illustration picture: Numerous files on shelves from the archives of the Stasi](illustration.webp)
_Illustration: [Bundesarchiv, Bild 183-1989-1204-023 / Heinz Hirndorf / CC-BY-SA 3.0](https://commons.wikimedia.org/wiki/File:Bundesarchiv_Bild_183-1989-1204-023,_Erfurt,_Bezirks-Archiv_des_Ministeriums_f%C3%BCr_Staatssicherheit.jpg)_
Even if you have nothing to hide, here are some reasons to worry about general surveillance.
> This article has been translated from French using Firefox 128's offline AI translator, and manually corrected by myself. It refers to events and structures known to a French audience but instances of such phenomena should be found in other countries as well.