Compare commits
63 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d689a700c | ||
|
|
fb34ff0c64 | ||
|
|
12db898381 | ||
|
|
0e09cd96ed | ||
|
|
00005da741 | ||
|
|
ea0940ff66 | ||
|
|
d8bee2acc2 | ||
|
|
ccdffd6c65 | ||
|
|
904f21f1e9 | ||
|
|
fed2333433 | ||
|
|
4993431bbe | ||
|
|
7fefec320d | ||
|
|
ebb0df945e | ||
|
|
0a095fa359 | ||
|
|
d70e23068c | ||
|
|
d2891b448a | ||
|
|
3fd0c107e0 | ||
|
|
02abb01549 | ||
|
|
90e8ff7ac0 | ||
|
|
f5d03ed1cf | ||
|
|
338de75fb4 | ||
|
|
9d55ae84a8 | ||
|
|
322eddf574 | ||
|
|
752f296a77 | ||
|
|
16655c00e0 | ||
|
|
a324ba7b64 | ||
|
|
bce789de7b | ||
|
|
9ee28abd50 | ||
|
|
74e119b6e2 | ||
|
|
b357b50525 | ||
|
|
c12db2ab42 | ||
|
|
2bb3b936b4 | ||
|
|
77fffce8a2 | ||
|
|
d7ca6c9cdc | ||
|
|
29f6e652de | ||
|
|
5fb6e37fdc | ||
|
|
588b0a9e10 | ||
|
|
096ffb8c4e | ||
|
|
f87afaaf44 | ||
|
|
2cdeee2a3c | ||
|
|
dff5da4d50 | ||
|
|
2fd22e30ce | ||
|
|
9afd55a603 | ||
|
|
32d3a98101 | ||
|
|
81f65823f2 | ||
|
|
aa54c194ff | ||
|
|
9d2ecb11fd | ||
|
|
6658952dcf | ||
|
|
3c6957467f | ||
|
|
c55e92fe93 | ||
|
|
77469be23f | ||
|
|
92e3b5f49f | ||
|
|
072b2d38e2 | ||
|
|
5e93f56038 | ||
|
|
fdb87d6c0b | ||
|
|
e7a91af6b5 | ||
|
|
396c62e422 | ||
|
|
a6ecebf648 | ||
|
|
c4af22d852 | ||
|
|
3dfca328ee | ||
|
|
f61c032d23 | ||
|
|
345867359e | ||
|
|
28dae21621 |
78
config.toml
|
|
@ -1,4 +1,76 @@
|
||||||
baseURL = "https://blog.jaseg.de/"
|
baseURL = "http://jaseg.de/"
|
||||||
languageCode = "en-us"
|
languageCode = "en-us"
|
||||||
title = "jaseg.de"
|
title = "Home"
|
||||||
theme = "hugo-classic"
|
copyright = "Jan Sebastian Götte"
|
||||||
|
theme = "conspiracy"
|
||||||
|
enableRobotsTXT = true
|
||||||
|
|
||||||
|
[outputs]
|
||||||
|
home = ['html', 'rss']
|
||||||
|
taxonomy = ['html', 'rss']
|
||||||
|
|
||||||
|
[params]
|
||||||
|
fediverse_account = "@jaseg@chaos.social"
|
||||||
|
|
||||||
|
[taxonomies]
|
||||||
|
category = "Categories"
|
||||||
|
blog = "Posts"
|
||||||
|
|
||||||
|
[[menu.main]]
|
||||||
|
name = "Home"
|
||||||
|
url = "/"
|
||||||
|
weight = 1
|
||||||
|
|
||||||
|
[[menu.main]]
|
||||||
|
name = "Blog"
|
||||||
|
url = "/blog/"
|
||||||
|
weight = 2
|
||||||
|
|
||||||
|
[[menu.main]]
|
||||||
|
name = "Projects"
|
||||||
|
url = "/projects/"
|
||||||
|
weight = 3
|
||||||
|
|
||||||
|
[[menu.main]]
|
||||||
|
name = "About"
|
||||||
|
url = "/about/"
|
||||||
|
weight = 4
|
||||||
|
|
||||||
|
[[params.profile_links]]
|
||||||
|
name = "cgit"
|
||||||
|
url = "https://git.jaseg.de/"
|
||||||
|
weight = 1
|
||||||
|
|
||||||
|
[[params.profile_links]]
|
||||||
|
name = "Github"
|
||||||
|
url = "https://github.com/jaseg"
|
||||||
|
weight = 2
|
||||||
|
|
||||||
|
[[params.profile_links]]
|
||||||
|
name = "Gitlab"
|
||||||
|
url = "https://gitlab.com/neinseg"
|
||||||
|
weight = 3
|
||||||
|
|
||||||
|
[[params.profile_links]]
|
||||||
|
name = "Mastodon"
|
||||||
|
url = "https://chaos.social/@jaseg"
|
||||||
|
weight = 4
|
||||||
|
|
||||||
|
[[params.footer_links]]
|
||||||
|
name = "About"
|
||||||
|
url = "/about/"
|
||||||
|
weight = 1
|
||||||
|
|
||||||
|
[[params.footer_links]]
|
||||||
|
name = "Imprint"
|
||||||
|
url = "/imprint/"
|
||||||
|
weight = 2
|
||||||
|
|
||||||
|
[[params.homepage_categories]]
|
||||||
|
title = "Blog"
|
||||||
|
key = "blog"
|
||||||
|
weight = 2
|
||||||
|
count = 10
|
||||||
|
|
||||||
|
[security.exec]
|
||||||
|
allow = ["^dart-sass-embedded$", "^go$", "^npx$", "^postcss$", "^rst2html$"]
|
||||||
|
|
|
||||||
9
content/_index.rst
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
title: jaseg.de
|
||||||
|
---
|
||||||
|
|
||||||
|
Hi there, and welcome to my personal website.
|
||||||
|
|
||||||
|
I'm jaseg, and I write about my projects here. You can find long-form articles in the blog, and links to my open-source
|
||||||
|
projects on the projects page. On the top right of this page, there are links to my git repositories and social media
|
||||||
|
pages. If you want to learn more about me, head over to the about page.
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
---
|
|
||||||
title: "About jaseg"
|
|
||||||
---
|
|
||||||
|
|
||||||
About
|
|
||||||
-----
|
|
||||||
|
|
||||||
65
content/about/index.rst
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
---
|
||||||
|
title: "About jaseg"
|
||||||
|
---
|
||||||
|
|
||||||
|
About
|
||||||
|
-----
|
||||||
|
|
||||||
|
Hej, I'm Jan, or jaseg. At the moment I'm doing a PhD (Dr.-Ing.) at TU Darmstadt in Computer Science, specializing on
|
||||||
|
Hardware Security. This is my personal website where I publish things that I find interesting.
|
||||||
|
|
||||||
|
I self-host my code at `git.jaseg.de <https://git.jaseg.de/>`__, but I am also on `github <https://github.com/jaseg>`__
|
||||||
|
and on `gitlab <https://gitlab.com/neinseg>`__. I use github for issue tracking for some of my projects such as
|
||||||
|
`gerbolyze <https://github.com/jaseg/gerbolyze>`__ and `python-mpv <https://github.com/jaseg/python-mpv>`__. I maintain
|
||||||
|
the `python-mpv <https://pypi.org/project/python-mpv/>`__ and `gerbolyze <https://pypi.org/project/gerbolyze/>`__ python
|
||||||
|
packages on PyPI. Release tags on these two repositories are signed with the release signing key found `on github
|
||||||
|
<https://github.com/jaseg.gpg>`__ and below.
|
||||||
|
|
||||||
|
I am not on any social network, but feel free to write me an email at `hello@jaseg.de
|
||||||
|
<mailto:hello@jaseg.de?subject=About\ page\ on\ blog.jaseg.de>`__.
|
||||||
|
|
||||||
|
I do not use application-level email encryption such as S/MIME or PGP. If you need a higher level of secrecy than
|
||||||
|
regular old email provides, please ask around for my signal contact or email me a file encrypted using `age
|
||||||
|
<https://github.com/FiloSottile/age>`__ with one of the SSH keys listed `on my github
|
||||||
|
<https://github.com/jaseg.keys>`__. You can find both PGP and other SSH keys that I have used in the past on the
|
||||||
|
internet, but please consider these keys revoked, and do not use them to encrypt anything you send me.
|
||||||
|
|
||||||
|
Python package release signing key
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
I use this GPG key (key ID ``ED7A208EEEC76F2D``) to sign git release tags of both `gerbolyze <https://github.com/jaseg/gerbolyze>`__ and `python-mpv
|
||||||
|
<https://github.com/jaseg/python-mpv>`__:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
mDMEXom49xYJKwYBBAHaRw8BAQdA/KrWMt2MKGIZUvlQZnWjNd6i8/ZYjRsBQqEf
|
||||||
|
PJ8pJ+20NHB5dGhvbi1tcHYgUmVsZWFzZSBTaWduaW5nIEtleSA8cHl0aG9uLW1w
|
||||||
|
dkBqYXNlZy5kZT6IlgQTFggAPhYhBONvdTB/Cg7C0UX/XO16II7ux28tBQJeibj3
|
||||||
|
AhsDBQkSzAMABQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEO16II7ux28thRYA
|
||||||
|
/3Yl1RdeUGor6K0RTxce9TIBB+DpLNupJgB9f6onuocpAQC614zQ/RQ6rkGTHCwA
|
||||||
|
ElFClWRQ5eppj0jpAuH15udqAbg4BF6JuPcSCisGAQQBl1UBBQEBB0A0mrXSv6rj
|
||||||
|
ajCmZR4H4OtowAx477YS+yWARqo1NtdgJwMBCAeIfgQYFggAJhYhBONvdTB/Cg7C
|
||||||
|
0UX/XO16II7ux28tBQJeibj3AhsMBQkSzAMAAAoJEO16II7ux28tMZwBAIUpHHvP
|
||||||
|
gRW2jQuzdw1r06kItfFk/0t+mgNUQ2+vtbhzAP98BoWx7lv+bvlIbBaVgLldusj0
|
||||||
|
pHnZI/0y3ksMBkdbBw==
|
||||||
|
=Mr6G
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
|
About this site
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This site is made with the hugo static site generator. I made the theme myself, feel free to grab a copy at
|
||||||
|
`git.jaseg.de <https://git.jaseg.de/blog.git/tree/themes/conspiracy?h=main>`__. The nifty auto-reflowing code embeds are
|
||||||
|
made with some CSS magic I made that you can find in `style.css
|
||||||
|
<https://git.jaseg.de/blog.git/tree/themes/conspiracy/assets/css/style.css?h=main&id=2fd22e30ce176d8d8a641fd371ad1623b082eaaf#n367>`__.
|
||||||
|
The body text is typeset in Roboto Slab, created by `Christian Robertson <https://christianrobertson.com/>`__ while
|
||||||
|
working at Google. The headlines are set in Nyght Serif, a font by `Maksym Kobuzan <https://linktr.ee/mkobuzan>`__.
|
||||||
|
Check out their other fonts, their work is beautiful! Source code is typeset in Fira Code, a derivate by ... from
|
||||||
|
Mozilla's `Fira Mono <https://github.com/mozilla/Fira>`__ font, designed by `Erik Spiekermann
|
||||||
|
<https://spiekermann.com/>`__, `Ralph du Carrois <https://carrois.com/>`__, `Anja Meiners
|
||||||
|
<https://anjameiners.com/de/hallo/>`__ and Botio Nikoltchev of Carrois Type Design, now succeeded by `bBoxType
|
||||||
|
<https://bboxtype.com/typefaces/FiraMono/#!layout=specimen>`__ , and Patryk Adamczyk of Mozilla. The photo of mountains
|
||||||
|
that's used in the background of this site is by `Fabrizio Conti <https://www.conti.photos/>`__ and can be found on
|
||||||
|
`Unsplash <https://unsplash.com/photos/TUmjK7ZJgbI>`__.
|
||||||
|
|
||||||
BIN
content/blog/8seg/8seg-digit-circuit.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
203
content/blog/8seg/index.rst
Normal file
|
|
@ -0,0 +1,203 @@
|
||||||
|
---
|
||||||
|
title: "8seg Technical Overview"
|
||||||
|
date: 2023-12-26T15:26:00+01:00
|
||||||
|
summary: >
|
||||||
|
8seg is a large-scale LED light art installation that displays text on a 1.5 meter high, 30 meter wide
|
||||||
|
8-segment display made from cheap LED tape.
|
||||||
|
---
|
||||||
|
|
||||||
|
Prologue
|
||||||
|
--------
|
||||||
|
|
||||||
|
German hacker culture has this intense love for things that light up in colorful ways. Like for many others in this
|
||||||
|
community, I have always been fascinated by LEDs. One of the first things on my pile of unfinished projects was to build
|
||||||
|
my own LED matrix and use it to display text. When I started that project, I was still new to electronics. Back then,
|
||||||
|
commercial LED matrices were limited to red or green color only, and were very expensive, so there was an incentive to
|
||||||
|
build your own. At the same time, while individual LEDs were'nt expensive anymore, they hadn't started to be cheap yet,
|
||||||
|
either. On top of the material cost, back then there were no PCB fabs, and especially no PCB assembly houses that a
|
||||||
|
hobbyist could afford. Ultimately, I ended up never finishing this project because I felt it was more of a feat of
|
||||||
|
material wealth than of technical prowess.
|
||||||
|
|
||||||
|
Over time, LEDs came down in price, and peoople started using them in all sorts of fun things. Around the mid-2010s,
|
||||||
|
cheap-ish, ready-made tapes and chains of RGB LEDs that included WS2811 or similar digitally controllable driver chips
|
||||||
|
led to a cambrian explosion in projects involving large amounds of colorful LEDs since suddenly, all you needed was an
|
||||||
|
arduino and a beefy power supply to individually control an almost unlimited number of these LEDs.
|
||||||
|
|
||||||
|
Today, LED technology has advanced even furhter, to a point where now you can buy staggering quantities of the second
|
||||||
|
generation of these controllable LEDs that provides better color rendering embedded in all sorts of shapes, from tapes
|
||||||
|
through rings to grids. When I built the first matelight_ in 2013, the matelight's 640 individually-controllable LEDs
|
||||||
|
were *a lot*. Today, you can buy a roll with several thousand channels for about the price of a nice pizza.
|
||||||
|
|
||||||
|
The idea behind 8seg
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Living through this amazing escalation of LED technology, in 2018, I looked at a then-obsolete piece of single-color,
|
||||||
|
dumb, non-controllable LED tape with a simple question in mind: Taking this unsophisticated artifact of yesterday's
|
||||||
|
technology, what would be the coolest thing I could build from it? Can I buld something that not only rivals, but
|
||||||
|
outmatches the modern controllable LED stuff? From that question, I set myself two goals. First, I wanted to keep the
|
||||||
|
project's use of financial and labor resources reasonable. A lot of art consists of taking a simple idea, and simply
|
||||||
|
extrapolating its implementation to a ridiculous scale at the expense of the artist's time and wallet. That wasn't the
|
||||||
|
point I wanted to make. I wanted to make something cool from an obsolete technology, not prove how much patience I had
|
||||||
|
soldering. My second goal was to create something that is meaningfully controllable. Controllability is much harder with
|
||||||
|
these dumb LED tapes, but it is possible nontheless, and I wanted to test out how far you could go with it.
|
||||||
|
|
||||||
|
After thinking through a number of possibilities, I settled on the basics of the 8seg design I ended up realizing. The
|
||||||
|
installation would be a banner-style display consisting of a series of characters made from non-controllable LED tape.
|
||||||
|
The banner can be rigged up in any convenient air space, bending and folding to conform to the space's shape and size.
|
||||||
|
The key idea behind 8seg is that it makes up for it's lack of control fidelity with sheer size. If nothing else, this
|
||||||
|
non-controllable LED tape is *cheap*.
|
||||||
|
|
||||||
|
The design of a single 8seg character
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
Each 8seg character consists of 8 *segments* of LED tape that are inter-connected through small circuit boards, four in
|
||||||
|
the corners, and one in the center. As it turns out, 8 segments arranged in this shape are enough to display all of the
|
||||||
|
English language's alphabet as well as numbers in a weird, but readable form.
|
||||||
|
|
||||||
|
The electrical design of an 8seg character has one weird trick at its core. To avoid having to run a bunch of wires from
|
||||||
|
some kind of driver circuit board to each of the eight segments, I thought, why not use the LED tape itself instead for
|
||||||
|
power and data transmission? Wires are heavy, expensive, and annoying to solder, so if I could find a way to
|
||||||
|
interconnect the LED tape so that it can all be driven from a driver circuit located at one of the character's
|
||||||
|
junctions while simultaneously powering that driver circuit, an 8seg character wouldn't need any wires at all anymore.
|
||||||
|
|
||||||
|
8seg achieves this feat using a circuit as shown in the diagram below. Interconnections between the LED tape segments
|
||||||
|
are done with a small circuit board in each of the four corners. The design is rotationally symmetric, and all four of
|
||||||
|
these boards are identicaly. The top right and bottom left corners simply use the back side of the same circuit board
|
||||||
|
used in the top left and bottom right corners.
|
||||||
|
|
||||||
|
.. image:: 8seg-digit-circuit.png
|
||||||
|
|
||||||
|
The driver circuit sits at the center of the character and directly connects to the four diagonal segments. The key
|
||||||
|
thought behind 8seg's driving scheme is that there are two common phases wound through the display in a zig-zag pattern
|
||||||
|
as shown in red and blue in the schema below. These phases alternate their polarity at a high frequency. Each segment
|
||||||
|
has its negative pole connected to one of these two phases, and can be turned on by the driver while that phase is low
|
||||||
|
and the other phase is high. While a phase is high, the LEDs on all segments connected to that phase are reverse-biased,
|
||||||
|
and thus these segments remain dark.
|
||||||
|
|
||||||
|
The positive poles of all segments are connected to the driver circuit in the center through a spiral pattern. Each arm
|
||||||
|
of the spiral is made up of two segments, one diagonal on the inside, and one horizontal or vertical on the outside.
|
||||||
|
The two segments on each spiral arm are on different phases, one on each of the two phases. Thus, during a single cycle
|
||||||
|
of the two phases alternating polarity, first one of the two segments has its polarity the right way around, then the
|
||||||
|
other. The driver can turn on the active segment by connecting the spiral control line to the positive LED supply
|
||||||
|
voltage.
|
||||||
|
|
||||||
|
Both phases cross at the center where the driver circuit is located, so the driver can power itself from the two phases
|
||||||
|
using a simple full bridge rectifier.
|
||||||
|
|
||||||
|
Saving copper with point of load regulation
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
In the beginning, I experimented with the design above, putting 12V AC on the two phases, and letting the driver switch
|
||||||
|
its derived LED supply using some cheap MOSFETs. This simple design totally works, but it has an important shortcoming.
|
||||||
|
|
||||||
|
8seg is designed to be physically *very* large. This means that not only does it have a large number of LEDs that
|
||||||
|
together need a lot of current, it also has to transmit all of that current across significant physical distances. The
|
||||||
|
consequence of this was that in the initial design, I was looking at either needing hundreds of Euros worth of copper
|
||||||
|
cables, or burning hundreds of Watts of electricity into heat if I were to use thinner cables. In this case, cables act
|
||||||
|
like resistors. In a resistor, power dissipation rises with the square of the current inside the cable. This is bad for
|
||||||
|
8seg since it means halving the amount of copper in those wires increases power dissipation in these wires fourfold.
|
||||||
|
|
||||||
|
Despite that downside, this square law does come with an upside, too. If we assume we have wires of a particular fixed
|
||||||
|
diameter, if we can halve the current through those wires, we can quarter the wires' power dissipation. If we want to
|
||||||
|
deliver the same amount of power to the LEDs as before, to halve wire current, we have to double the voltage, and add
|
||||||
|
some circuitry on the drivers to convert that increased voltage back down to close to our LED tape's nominal 12V.
|
||||||
|
|
||||||
|
Alas, simply doubling the voltage leads to one question: How is it that we can pass double the voltage through our LED
|
||||||
|
tape to the center control circuit? Isn't the LED tape made for 12V operation only, not 24V? The answer to this
|
||||||
|
apparent problem is that the center is connected to the AC bus voltage only through the negative side of the LED tapes,
|
||||||
|
and controls their positive sides to turn them on or off. The AC bus voltage never appears directly across any single of
|
||||||
|
the eight segments. At the same time, a simple buck converter stepping down our new 24V bus voltage to 12V, and feeding
|
||||||
|
the segment control transistors with that instead of feeding them straight from the rectified AC bus allows us to feed
|
||||||
|
the segments with 12V. The only difference between this circuit and the straight 12V variant is that now, during OFF
|
||||||
|
times, the LED tapes see a negative 24 v across them. To make sure that's not a problem, I tested a number of them with
|
||||||
|
different LED colors and from different manufacturers, and all of them held up past the 50 V I could easily generate
|
||||||
|
with my lab power supply.
|
||||||
|
|
||||||
|
Synchronous rectification
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
I implemented the point-of-load regulation in a new revision of the center circuit, and built a prototype digit. When I
|
||||||
|
tested this prototype, to my dismay, I noticed some really strange behavior. In my tests, the LED tape did not properly
|
||||||
|
light up, and when I checked the voltages with my oscilloscope, I noticed that the center circuit's ground was floating
|
||||||
|
several volts *below* the AC bus voltage's negative phase. How come?
|
||||||
|
|
||||||
|
After some head-scratching, I found that this problem was due to a simple instance of Kirchhoff's current law. Consider
|
||||||
|
the point where the AC bus voltage's currently negative phase enters the center circuit board. Let's say that we
|
||||||
|
dissipate 24 Watts in the segments' LEDs. In this case, at 24 Volts, 1 Ampère will flow into the center circuit's
|
||||||
|
terminal connected to the currently positive phase, and out from the center circuit's terminal connected to the
|
||||||
|
currently negative phase.
|
||||||
|
|
||||||
|
Now consider the current through the LED tape. During one half-cycle of the AC bus, the center circuit can only address
|
||||||
|
the four segments that have their negative rail connected to the currently negative phase of the AC bus. If one of these
|
||||||
|
four segments is currently on and dissipating our 24 Watts, that segment will be fed 2 Ampère of current from the center
|
||||||
|
circuit through its positive rail. My mistake was that I did not consider what happened to the return current here.
|
||||||
|
The corresponding 2 Ampère return current of course flows back through the segment's negative rail into the center
|
||||||
|
circuit, and herein lies the issue: That negative rail is where our center circuit's supply current comes from! This
|
||||||
|
means that according to Kirchhoff's current law, the 1 A flowing out from the center circuit at its input are adding up
|
||||||
|
with the 2 A flowing into it. The result of this is that in the currently positive phase's connection, we get 1 A
|
||||||
|
flowing into the center circuit, while in the negative phase connection, we get (-1) + (+2) resulting in another 1 A
|
||||||
|
flowing into it! The only terminal where current flows *out* of the center circuit is the positive terminal connected to
|
||||||
|
the active segment, out of which 2 A of current are flowing.
|
||||||
|
|
||||||
|
The big problem with this confusing scenario is that this means the bridge recitifier in our center circuit cannot work,
|
||||||
|
since its negative-side diodes are reverse biased while any of the segments are on. We can't just add more diodes here,
|
||||||
|
since that would just short both AC bus rails together. Instead, the solution is to add one rather chonky MOSFET in
|
||||||
|
parallel with each of the two negative-side diodes of the bridge rectifier that are controlled by the center circuit to
|
||||||
|
act as a sort of synchronous rectifier. When we turn on one of the segments, we have to turn on the MOSFET on the
|
||||||
|
currently negative rail to allow the segment's return current to bypass the bridge rectifier's negative-side diode. Fun
|
||||||
|
fact: If we turn on the wrong MOSFET out of the pair, we short the AC bus, resulting in a very quick end of life for that
|
||||||
|
poor MOSFET.
|
||||||
|
|
||||||
|
Power line data communication
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
As we saw above, the driver providing power to a string of digits has to continuously alternate the polarity of its
|
||||||
|
output voltage to provide one part of the digit circuits' multiplexing. Since we want to provide the control information
|
||||||
|
to the center circuits through those same two wires, we can choose between a number of viable power line communication
|
||||||
|
schemes. These schemes usually require a beefy transmitter adding a modulation at a frequency much larger than the
|
||||||
|
underlying bus frequency, and a filter circuit at each receiver to filter that signal from the much stronger fundamental
|
||||||
|
AC waveform. In our application, I saw two issues with these classical approaches. First, they require fairly complex
|
||||||
|
circuitry, especially the beefy transmitter at the driver. Second, they are susceptible to attenuation with either
|
||||||
|
changing load or over long distances, which could potentially be a problem with the high currents and long(ish) wiring
|
||||||
|
runs 8seg needs.
|
||||||
|
|
||||||
|
Because of these disadvantages, I decided on another approach entirely. Instead of modulating our control signal on top
|
||||||
|
of the AC power waveform, we modulate our control data *into* the AC power waveform. To not interfere with the display
|
||||||
|
and cause outages or flicker, and to avoid having to blank the display during transmissions, we choose a modulating
|
||||||
|
technique that leaves the proportions of negative and positive half-waves undisturbed. The practical realization of this
|
||||||
|
is that instead of alternating positive and negative half-waves, we send a positive half wave for each "one" bit, and a
|
||||||
|
negative half wave for each "zero" bit, effectively creating a phase shift keyed signal with two states with an
|
||||||
|
180-degree phase shift, with the transmitted bit rate synchronized to twice the underlying carrier frequency.
|
||||||
|
|
||||||
|
The remaining question is how one can encode arbitrary binary data into a continuous stream of ones and zeros that is
|
||||||
|
precisely 50 % ones and 50 % zeros across any time span longer than a few dozen bits. There exists a near-optimal
|
||||||
|
solution to this question from ethernet over copper twisted pairs. In ethernet, the encoded and modulated signal passes
|
||||||
|
through an isolation transformer to protect the ethernet transceiver from interference or dangerous voltages coming in
|
||||||
|
through the ethernet port. For this isolation transformer to work, the modulated ethernet signal must be exactly
|
||||||
|
balanced to avoid saturating the transformer's core with a DC offset. Ethernet solves this issue by using an encoding
|
||||||
|
known as `8b/10b encoding`_. 8b/10b encoding is named like that because it specifies a way to produce a 10 bit codeword
|
||||||
|
from any 8 bit input data word while guaranteeing that the resulting codewords are always precisely balanced when
|
||||||
|
looking at two or more consecutively.
|
||||||
|
|
||||||
|
Framing
|
||||||
|
-------
|
||||||
|
|
||||||
|
Since 8b/10b encoding maps a space of 256 data words to 1024 code words, there necessarily are a number of unused code
|
||||||
|
words. While for some of them, leaving them unallocated is beneficial because it improves error tolerance by decreasing
|
||||||
|
the probability of one code word turning into another undetectably when a single one of its bits is flipped, even
|
||||||
|
accounting for that it leaves some room for other uses. In 8b/10b, these leftover code words are used for synchronizing
|
||||||
|
the receiver to the transmitter, and for framing transmissions. Synchronization is necessary for the receiver to know
|
||||||
|
where a code word stards, and 8b/10b has a handful of special "comma" code words that can be uniquely identified in a
|
||||||
|
continuous stream of received ones and zeros, because no other combination of 8b/10b code words could produce the same
|
||||||
|
sequence of ones and zeros of the comma code word anywhere.
|
||||||
|
|
||||||
|
The leftover code words that are not commas are useful, too. They can be used, for instance, as filler code words
|
||||||
|
betwene actual data transmissions, or to act as framing markers denoting things like the end of a protocol message.
|
||||||
|
|
||||||
|
The 8seg driver produces its modulation waveform by translating all data to be transmitted into 8b/10b codes, padding
|
||||||
|
the result with framing markers and filler codes, and copy-pasting together the corresponding AC waveform from a small
|
||||||
|
set of pre-programmed waveform transitions.
|
||||||
|
|
||||||
|
.. _matelight: https://github.com/jaseg/matelight
|
||||||
|
.. _`8b/10b encoding`: https://en.wikipedia.org/wiki/8b/10b_encoding
|
||||||
|
|
||||||
3
content/blog/_index.rst
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
title: Blog
|
||||||
|
---
|
||||||
37
content/blog/ashen-yanartas/ashen-logo-text-dark-plain.svg
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="60mm"
|
||||||
|
height="18mm"
|
||||||
|
viewBox="0 0 60 18"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<rect
|
||||||
|
x="73.275604"
|
||||||
|
y="7.5154462"
|
||||||
|
width="82.669907"
|
||||||
|
height="60.687229"
|
||||||
|
id="rect1" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-60.324998,-47.365882)">
|
||||||
|
<path
|
||||||
|
id="path4-6"
|
||||||
|
style="fill:#ececec;stroke-width:0.105392;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1"
|
||||||
|
d="m 69.324799,48.865886 a 7.5,7.5 0 0 0 -7.499801,7.499801 7.5,7.5 0 0 0 3.273185,6.195487 c -0.913481,-0.983452 -1.40067,-2.340488 -1.315165,-3.825089 0.198575,-3.447783 1.631942,-4.848283 1.631942,-4.848283 l 1.590084,3.588411 c -0.48406,-2.540144 -0.201121,-4.995971 2.766756,-8.596891 a 7.5,7.5 0 0 0 -0.447001,-0.01344 z m 1.328084,0.118339 c 0.310055,1.43067 1.013609,4.202913 2.107882,5.883879 1.029143,1.580919 1.930339,2.092129 1.865519,4.55166 -0.03918,1.486422 -0.657454,2.712199 -1.732194,3.542419 a 7.5,7.5 0 0 0 3.931026,-6.596496 7.5,7.5 0 0 0 -6.172233,-7.381462 z" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
transform="matrix(0.67004375,0,0,0.67004375,30.304048,47.575216)"
|
||||||
|
id="text1"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:21.3333px;line-height:13.9843px;font-family:Equateur;-inkscape-font-specification:Equateur;text-decoration-color:#000000;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect1);display:inline;fill:#f9f9f9;fill-opacity:1;stroke-width:0.755906;stroke-linecap:round;stroke-linejoin:round"><tspan
|
||||||
|
x="73.275391"
|
||||||
|
y="19.8411"
|
||||||
|
id="tspan2">ashen</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
37
content/blog/ashen-yanartas/ashen-logo-text-light-plain.svg
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="60mm"
|
||||||
|
height="18mm"
|
||||||
|
viewBox="0 0 60 18"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<rect
|
||||||
|
x="73.275604"
|
||||||
|
y="7.5154462"
|
||||||
|
width="82.669907"
|
||||||
|
height="60.687229"
|
||||||
|
id="rect1" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-60.324998,-47.365882)">
|
||||||
|
<path
|
||||||
|
id="path4-6"
|
||||||
|
style="fill:#000000;stroke-width:0.105392;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
d="m 69.324799,48.865886 a 7.5,7.5 0 0 0 -7.499801,7.499801 7.5,7.5 0 0 0 3.273185,6.195487 c -0.913481,-0.983452 -1.40067,-2.340488 -1.315165,-3.825089 0.198575,-3.447783 1.631942,-4.848283 1.631942,-4.848283 l 1.590084,3.588411 c -0.48406,-2.540144 -0.201121,-4.995971 2.766756,-8.596891 a 7.5,7.5 0 0 0 -0.447001,-0.01344 z m 1.328084,0.118339 c 0.310055,1.43067 1.013609,4.202913 2.107882,5.883879 1.029143,1.580919 1.930339,2.092129 1.865519,4.55166 -0.03918,1.486422 -0.657454,2.712199 -1.732194,3.542419 a 7.5,7.5 0 0 0 3.931026,-6.596496 7.5,7.5 0 0 0 -6.172233,-7.381462 z" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
transform="matrix(0.67004375,0,0,0.67004375,30.304048,47.575216)"
|
||||||
|
id="text1"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:21.3333px;line-height:13.9843px;font-family:Equateur;-inkscape-font-specification:Equateur;text-decoration-color:#000000;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect1);display:inline;fill:#000000;fill-opacity:1;stroke-width:0.755906;stroke-linecap:round;stroke-linejoin:round"><tspan
|
||||||
|
x="73.275391"
|
||||||
|
y="19.8411"
|
||||||
|
id="tspan2">ashen</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
59
content/blog/ashen-yanartas/index.rst
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
title: "Project Announcement: Ashen and Yanartas"
|
||||||
|
date: 2026-05-31T08:00:00+02:00
|
||||||
|
summary: >
|
||||||
|
There are exciting things ahead for the next year: I have been granted funding by both nlnet and by prototype fund
|
||||||
|
for open-source work on an open source hardware Hardware Security Module. As a vessel for this project, I created a
|
||||||
|
consulting company, yasec.
|
||||||
|
---
|
||||||
|
|
||||||
|
I'm currently in the last days of finishing my PhD (Dr.-Ing.) in Electrical Engineering. To make sure things don't get
|
||||||
|
boring afterwards, I've been busy looking for new opportunities. As a result, there are exciting things ahead for the
|
||||||
|
next year: I have been granted funding by both nlnet *and* by Prototype Fund for open-source work on an Open Source
|
||||||
|
Hardware Hardware Security Module. As infrastructure for these projects, I created a consulting company, `yasec
|
||||||
|
<https://yasec.de>`__.
|
||||||
|
|
||||||
|
Prototype Fund supports Ashen, the OS for open-source HSMs
|
||||||
|
----------------------------------------------------------
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<picture style="max-width: 10em; margin: 1em auto 1em auto">
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="ashen-logo-text-light-plain.svg">
|
||||||
|
<img src="ashen-logo-text-dark-plain.svg alt="Ashen project logo showing a stylized flame in a circle">
|
||||||
|
</picture>
|
||||||
|
|
||||||
|
Starting June 2026, I will be working on Ashen_, an open-source software stack that provides the operating system layer
|
||||||
|
for open-source HSMs. The project is funded as part of `Prototype Fund`_'s Class 02.
|
||||||
|
|
||||||
|
Compared to existing open-source HSM software that work at the application level and that don't
|
||||||
|
consider physical attacks, this stack will provide the underlying operating system services to protect such systems from
|
||||||
|
physical attacks. A key component of this stack will be a portable mechanism to connect hardware tamper sensors to a
|
||||||
|
system. The stack will enable deterministic guarantees of the maximum latency until secrets are destroyed after a tamper
|
||||||
|
alarm was raised.
|
||||||
|
|
||||||
|
.. _Ashen: https://yasec.de/projects/ashen/
|
||||||
|
.. _`Prototype Fund`: https://www.prototypefund.de/
|
||||||
|
|
||||||
|
nlnet supports Yanartas, the OSHW HSM platform
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
After work on the Ashen software stack is completed, I will continue by creating Yanartas_, an Open Source Hardware
|
||||||
|
design for a complete open-source Hardware Security Module that provides protection against advanced physical attacks
|
||||||
|
using a security mesh based on the `Inertial HSM`_ technology I developed during my PhD. The design will be customizable
|
||||||
|
to different use cases and payload sizes from microcontrollers to whole servers.
|
||||||
|
|
||||||
|
.. _Yanartas: https://yasec.de/projects/yanartas/
|
||||||
|
.. _`Inertial HSM`: https://tches.iacr.org/index.php/TCHES/article/view/9290
|
||||||
|
|
||||||
|
Let's talk!
|
||||||
|
-----------
|
||||||
|
|
||||||
|
In case you're interested to talk about hardware security engineering or open-source hardware, feel free to reach out
|
||||||
|
through email or on mastodon. The projects are in an early stage, and I'm looking both for collaborators for these
|
||||||
|
projects, and for opportunities once these projects have been completed. At this time, I only have a small amount of
|
||||||
|
spare capacity outside of these projects, but that will change with time. I'd love to hear about *your* projects and
|
||||||
|
your needs for specialist work in case you're interested.
|
||||||
|
|
||||||
|
Follow this blog's `RSS <https://jaseg.de/index.xml>`__ and follow me `on mastodon <https://chaos.social/@jaseg>`__ for
|
||||||
|
updates!
|
||||||
31
content/blog/ashen-yanartas/yasec-logo-v1-dark-plain.svg
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="35mm"
|
||||||
|
height="17.549mm"
|
||||||
|
viewBox="0 0 35 17.549"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<rect
|
||||||
|
x="33.844814"
|
||||||
|
y="193.19748"
|
||||||
|
width="593.69446"
|
||||||
|
height="361.01135"
|
||||||
|
id="rect1" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-30.000001,-82.703)">
|
||||||
|
<path
|
||||||
|
style="font-size:21.3333px;line-height:13.9843px;font-family:Equateur;-inkscape-font-specification:Equateur;white-space:pre;fill:#e0e0e0;stroke-width:0.755906;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
d="m 33.611037,211.68229 v 0.10667 h 3.583994 l 7.082656,-15.33865 1.87733,-0.55466 v -0.10667 h -5.503991 v 0.10667 l 2.111996,0.53333 -2.218663,6.82666 -3.135995,-6.84799 2.239997,-0.512 v -0.10667 h -6.549323 v 0.10667 l 1.68533,0.512 4.543993,9.66398 c -1.727997,2.816 -3.135995,4.416 -5.717324,5.61066 z m 14.762647,-5.11999 c 1.151998,0 1.834664,-0.74667 2.794662,-1.45067 0.277333,0.78934 0.853332,1.42934 1.642664,1.42934 1.087999,0 1.941331,-1.216 2.474663,-2.112 l -0.08533,-0.0853 c -0.256,0.256 -0.874665,0.76799 -1.237331,0.76799 -0.341333,0 -0.490666,-0.46933 -0.490666,-1.13066 v -5.63199 c 0,-1.408 -1.130665,-2.816 -2.51733,-2.816 -1.62133,0 -5.205325,1.94133 -5.205325,2.83733 0,0.66133 1.919997,1.81333 3.093329,2.368 l 0.08533,-0.10667 c -0.511999,-0.704 -1.045332,-1.83466 -1.045332,-2.53866 0,-0.896 0.895999,-1.536 1.727997,-1.536 1.066665,0 1.471998,1.024 1.471998,2.24 v 2.21866 l -4.906659,1.25867 c 0,0 -0.447999,0.85333 -0.447999,1.79199 0,1.68533 1.450664,2.496 2.645329,2.496 z m -0.362666,-3.05066 c 0,-0.384 0.08533,-0.85334 0.08533,-0.85334 l 2.986662,-1.13066 v 3.072 c -0.554666,0.31999 -0.981332,0.61866 -1.578664,0.61866 -0.895999,0 -1.493331,-0.704 -1.493331,-1.70666 z m 11.818665,3.09333 c 1.727997,0 4.053327,-1.088 4.053327,-3.37067 0,-0.95999 -0.405333,-1.91999 -1.535998,-2.47466 l -2.794662,-1.38666 c -0.725332,-0.36267 -1.194665,-0.832 -1.194665,-1.536 0,-0.896 0.746666,-1.62133 1.813331,-1.62133 1.578664,0 2.19733,1.62133 2.090663,3.11466 l 0.128,0.0427 1.301331,-2.88 c -0.639999,-0.49066 -2.090663,-0.87466 -3.199995,-0.87466 -1.770663,0 -3.839994,0.98133 -3.839994,3.22132 0,0.896 0.341333,1.92 1.450665,2.45333 l 2.794662,1.344 c 0.746666,0.36267 1.151998,0.85333 1.151998,1.55733 0,1.00267 -0.810665,1.83467 -1.919997,1.83467 -1.855997,0 -3.007995,-2.38933 -2.794662,-4.11733 l -0.106666,-0.0427 -1.514665,3.28533 c 0.810666,0.74667 2.709329,1.45067 4.117327,1.45067 z m 9.96266,0 c 2.111996,0 3.221328,-1.152 4.245326,-2.688 L 73.90967,203.8103 c -0.938666,0.96 -1.813331,1.42933 -2.922662,1.42933 -2.51733,0 -3.669328,-2.43199 -3.669328,-4.69332 0,-0.17067 0,-0.32 0.02133,-0.46933 l 6.186657,-0.68267 c 0,-2.09066 -0.725332,-3.83999 -3.157328,-3.83999 -2.346663,0 -4.415993,1.94133 -5.077325,4.37332 l -1.407998,0.384 0.02133,0.128 1.279998,-0.14933 c -0.08533,0.42666 -0.128,0.85333 -0.128,1.28 0,2.92266 1.855997,5.03466 4.735993,5.03466 z m -2.38933,-7.25333 c 0.256,-1.94133 1.194665,-3.02933 2.431996,-3.02933 0.895999,0 1.493331,0.93867 1.557331,1.92 z m 12.181323,7.25333 c 1.919997,0 3.498661,-1.00267 4.586659,-2.688 l -0.128,-0.10667 c -0.895998,0.896 -2.00533,1.42933 -3.221328,1.42933 -2.751996,0 -3.797327,-2.73066 -3.797327,-4.86399 0,-2.23999 1.173331,-3.98933 2.837329,-3.98933 1.130665,0 1.87733,0.98134 1.87733,2.176 0,0.832 -0.234666,1.77067 -0.511999,2.41066 l 0.106666,0.0853 c 0.810666,-0.85333 2.495996,-2.41067 2.495996,-3.456 0,-1.06666 -1.151998,-2.06933 -2.986662,-2.06933 -3.370661,0 -6.165323,2.41067 -6.165323,5.84533 0,2.87999 1.962663,5.22666 4.906659,5.22666 z"
|
||||||
|
id="text1"
|
||||||
|
transform="matrix(0.58740671,0,0,0.58740671,12.90413,-25.337712)"
|
||||||
|
aria-label="yasec" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.8 KiB |
31
content/blog/ashen-yanartas/yasec-logo-v1-light-plain.svg
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="35mm"
|
||||||
|
height="17.549mm"
|
||||||
|
viewBox="0 0 35 17.549"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<rect
|
||||||
|
x="33.844814"
|
||||||
|
y="193.19748"
|
||||||
|
width="593.69446"
|
||||||
|
height="361.01135"
|
||||||
|
id="rect1" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-30.000001,-82.703)">
|
||||||
|
<path
|
||||||
|
style="font-size:21.3333px;line-height:13.9843px;font-family:Equateur;-inkscape-font-specification:Equateur;white-space:pre;stroke-width:0.755906;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
d="m 33.611037,211.68229 v 0.10667 h 3.583994 l 7.082656,-15.33865 1.87733,-0.55466 v -0.10667 h -5.503991 v 0.10667 l 2.111996,0.53333 -2.218663,6.82666 -3.135995,-6.84799 2.239997,-0.512 v -0.10667 h -6.549323 v 0.10667 l 1.68533,0.512 4.543993,9.66398 c -1.727997,2.816 -3.135995,4.416 -5.717324,5.61066 z m 14.762647,-5.11999 c 1.151998,0 1.834664,-0.74667 2.794662,-1.45067 0.277333,0.78934 0.853332,1.42934 1.642664,1.42934 1.087999,0 1.941331,-1.216 2.474663,-2.112 l -0.08533,-0.0853 c -0.256,0.256 -0.874665,0.76799 -1.237331,0.76799 -0.341333,0 -0.490666,-0.46933 -0.490666,-1.13066 v -5.63199 c 0,-1.408 -1.130665,-2.816 -2.51733,-2.816 -1.62133,0 -5.205325,1.94133 -5.205325,2.83733 0,0.66133 1.919997,1.81333 3.093329,2.368 l 0.08533,-0.10667 c -0.511999,-0.704 -1.045332,-1.83466 -1.045332,-2.53866 0,-0.896 0.895999,-1.536 1.727997,-1.536 1.066665,0 1.471998,1.024 1.471998,2.24 v 2.21866 l -4.906659,1.25867 c 0,0 -0.447999,0.85333 -0.447999,1.79199 0,1.68533 1.450664,2.496 2.645329,2.496 z m -0.362666,-3.05066 c 0,-0.384 0.08533,-0.85334 0.08533,-0.85334 l 2.986662,-1.13066 v 3.072 c -0.554666,0.31999 -0.981332,0.61866 -1.578664,0.61866 -0.895999,0 -1.493331,-0.704 -1.493331,-1.70666 z m 11.818665,3.09333 c 1.727997,0 4.053327,-1.088 4.053327,-3.37067 0,-0.95999 -0.405333,-1.91999 -1.535998,-2.47466 l -2.794662,-1.38666 c -0.725332,-0.36267 -1.194665,-0.832 -1.194665,-1.536 0,-0.896 0.746666,-1.62133 1.813331,-1.62133 1.578664,0 2.19733,1.62133 2.090663,3.11466 l 0.128,0.0427 1.301331,-2.88 c -0.639999,-0.49066 -2.090663,-0.87466 -3.199995,-0.87466 -1.770663,0 -3.839994,0.98133 -3.839994,3.22132 0,0.896 0.341333,1.92 1.450665,2.45333 l 2.794662,1.344 c 0.746666,0.36267 1.151998,0.85333 1.151998,1.55733 0,1.00267 -0.810665,1.83467 -1.919997,1.83467 -1.855997,0 -3.007995,-2.38933 -2.794662,-4.11733 l -0.106666,-0.0427 -1.514665,3.28533 c 0.810666,0.74667 2.709329,1.45067 4.117327,1.45067 z m 9.96266,0 c 2.111996,0 3.221328,-1.152 4.245326,-2.688 L 73.90967,203.8103 c -0.938666,0.96 -1.813331,1.42933 -2.922662,1.42933 -2.51733,0 -3.669328,-2.43199 -3.669328,-4.69332 0,-0.17067 0,-0.32 0.02133,-0.46933 l 6.186657,-0.68267 c 0,-2.09066 -0.725332,-3.83999 -3.157328,-3.83999 -2.346663,0 -4.415993,1.94133 -5.077325,4.37332 l -1.407998,0.384 0.02133,0.128 1.279998,-0.14933 c -0.08533,0.42666 -0.128,0.85333 -0.128,1.28 0,2.92266 1.855997,5.03466 4.735993,5.03466 z m -2.38933,-7.25333 c 0.256,-1.94133 1.194665,-3.02933 2.431996,-3.02933 0.895999,0 1.493331,0.93867 1.557331,1.92 z m 12.181323,7.25333 c 1.919997,0 3.498661,-1.00267 4.586659,-2.688 l -0.128,-0.10667 c -0.895998,0.896 -2.00533,1.42933 -3.221328,1.42933 -2.751996,0 -3.797327,-2.73066 -3.797327,-4.86399 0,-2.23999 1.173331,-3.98933 2.837329,-3.98933 1.130665,0 1.87733,0.98134 1.87733,2.176 0,0.832 -0.234666,1.77067 -0.511999,2.41066 l 0.106666,0.0853 c 0.810666,-0.85333 2.495996,-2.41067 2.495996,-3.456 0,-1.06666 -1.151998,-2.06933 -2.986662,-2.06933 -3.370661,0 -6.165323,2.41067 -6.165323,5.84533 0,2.87999 1.962663,5.22666 4.906659,5.22666 z"
|
||||||
|
id="text1"
|
||||||
|
transform="matrix(0.58740671,0,0,0.58740671,12.90413,-25.337712)"
|
||||||
|
aria-label="yasec" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.8 KiB |
209
content/blog/css-only-code-blocks/index.rst
Normal file
|
|
@ -0,0 +1,209 @@
|
||||||
|
---
|
||||||
|
title: "Code listings with nice line wrapping and line numbers from plain CSS"
|
||||||
|
date: 2025-07-23T23:42:00+01:00
|
||||||
|
summary: >
|
||||||
|
Code listings in web pages are often a bit of a pain to use. Usually, they don't wrap on small screens. Also,
|
||||||
|
copy-pasting code from a code listing often copies the line numbers along with the code. Finally, many
|
||||||
|
implementations use heavyweight HTML and/or javascript, making them slow to render. For this blog, I wrote a little
|
||||||
|
CSS hack that renders nice, wrapping code blocks with line continuation markers in plain CSS without any JS.
|
||||||
|
---
|
||||||
|
|
||||||
|
Code listings in web pages are often a bit of a pain to use. Often, they don't wrap on small screens. Also, copy-pasting
|
||||||
|
code from a code listing often copies the line numbers along with the code. Finally, many implementations use
|
||||||
|
heavyweight HTML and/or javascript, making them slow to render (looking at you, gitlab).
|
||||||
|
|
||||||
|
For this blog, I wrote an implementation that renders HTML code listings entirely without JavaScript, renders line
|
||||||
|
numbers using plain CSS such that they don't get selected with the code, and that works with the browser to wrap in a
|
||||||
|
natural way while still supporting the little line continuation arrows that are used to show that a line was soft
|
||||||
|
wrapped in text editors.
|
||||||
|
|
||||||
|
This blog is rendered as a static site using Hugo_ from a pile of RestructuredText_ documents. RestructuredText renders
|
||||||
|
code listings using Pygments_ by default. Pygments hard-bakes the line numbers into the generated HTML, so I am using a
|
||||||
|
`monkey-patched`_ hook that changes the line number rendering to just a bunch of empty ``<span>`` elements. The resulting
|
||||||
|
HTML for a code block then looks like this:
|
||||||
|
|
||||||
|
.. code:: html
|
||||||
|
|
||||||
|
<pre class="code [language] literal-block">
|
||||||
|
<span class="lineno"></span>
|
||||||
|
<span class="line">
|
||||||
|
<span class="[syntax highlight token]">The </span><span class="[other syntax highlight token]">code!<span>
|
||||||
|
</span>
|
||||||
|
<!-- ... repeat once for each source line. -->
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
You can find the (rather short) source of the ``rst2html`` wrapper `below <#rst2html-wrapper>`_.
|
||||||
|
|
||||||
|
The CSS
|
||||||
|
-------
|
||||||
|
|
||||||
|
This modified HTML structure of the code listing gets accompanied by some CSS to make it flow nicely. Here is a listing
|
||||||
|
of the complete CSS controlling the listing. The only bit that isn't included here is the actual syntax styling rules
|
||||||
|
for the pygments tokens.
|
||||||
|
|
||||||
|
.. code:: css
|
||||||
|
|
||||||
|
/*****************************************************/
|
||||||
|
/* Code block formatting / syntax highlighting rules */
|
||||||
|
/*****************************************************/
|
||||||
|
|
||||||
|
.code {
|
||||||
|
font-family: "Fira Code";
|
||||||
|
font-size: 13px;
|
||||||
|
text-align: left; /* Override default content "justify" alignment */
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
overflow-x: auto;
|
||||||
|
display: grid;
|
||||||
|
align-items: start;
|
||||||
|
grid-template-columns: min-content 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code > .line {
|
||||||
|
padding-left: calc(2em + 5px);
|
||||||
|
text-indent: -2em;
|
||||||
|
padding-top: 2px;
|
||||||
|
min-width: 15em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make individual syntax tokens wrap anywhere */
|
||||||
|
.code > .line > span {
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We render line numbers in CSS! */
|
||||||
|
.code > .lineno {
|
||||||
|
counter-increment: lineno;
|
||||||
|
word-break: keep-all;
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 5px;
|
||||||
|
overflow: clip;
|
||||||
|
position: relative;
|
||||||
|
text-align: right;
|
||||||
|
color: var(--c-text-muted);
|
||||||
|
border-right: 1px solid var(--c-fg-highlight);
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We also handle line continuation markers in CSS. */
|
||||||
|
.code > .lineno::after {
|
||||||
|
position: absolute;
|
||||||
|
right: 5px;
|
||||||
|
content: "\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳";
|
||||||
|
white-space: pre;
|
||||||
|
color: var(--c-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert the actual line number */
|
||||||
|
.code > .lineno::before {
|
||||||
|
content: counter(lineno);
|
||||||
|
}
|
||||||
|
|
||||||
|
.code::before {
|
||||||
|
counter-reset: lineno;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code .hll {}
|
||||||
|
/* Following are about 50 lines that define the styling of each kind of pygments syntax highlight token. These lines
|
||||||
|
all look like the following: */
|
||||||
|
.code .c { color: var(--c-text); font-weight: 400 } /* Comment */
|
||||||
|
|
||||||
|
This CSS does a few things:
|
||||||
|
|
||||||
|
1. It renders the ``<pre>`` code listing element using a two-column CSS ``display: grid`` layout. The left column is
|
||||||
|
used for the line numbers, and the right column is used for the code lines.
|
||||||
|
2. It numbers the lines using a `CSS Counter`_. CSS counters are meant for things like numbering headings and such, but
|
||||||
|
they are a perfect fit for our purpose.
|
||||||
|
3. It inserts the counter value as the line number into the ``<span class="lineno">`` element's ``::before``
|
||||||
|
pseudo-element. A side effect of using the ``::before`` pseudo-element is that without doing anything extra, the
|
||||||
|
line numbers will remain outside of the normal text selection so they will neither be highlighted when selecting
|
||||||
|
listing content, nor will they be copied when copy/pasting the listing content.
|
||||||
|
4. It inserts a string of ``"\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳\a↳"`` into the line number span's
|
||||||
|
``::after`` pseudo-element. This string evaluates to a sequence of unicode arrows separated by line breaks, and
|
||||||
|
starting with an empty line. The ``::after`` pseudo-element is positioned using ``position: absolute``, and the
|
||||||
|
parent ``<span class="lineno">`` has ``position: relative`` set. This way, the arrow pseudo-element gets placed on
|
||||||
|
top of the lineno span without affecting the layout at all. By setting ``overflow: clip`` on the parent ``<span
|
||||||
|
class="lineno">``, the arrow pseudo-element gets cut off vertically wherever the parent lineno element naturally
|
||||||
|
ends.
|
||||||
|
|
||||||
|
The line number span is inserted into the parent ``<pre>`` element's CSS grid using ``align-self: stretch``, which
|
||||||
|
causes it to vertically stretch to fill the available space. Since the line number span only contains the line number,
|
||||||
|
its minimum height is a single line. As a result, it will stretch higher only when the corresponding code line in the
|
||||||
|
right grid column stretches vertically because of line wrapping. When that happens, part of the arrow pseudo-element
|
||||||
|
starts showing through from behind the ``overflow: clip`` of the line number span, and one arrow gets rendered for each
|
||||||
|
wrapped listing line.
|
||||||
|
|
||||||
|
When the page is too narrow, we don't want the code listing's lines to wrapp into a column of single characters. To
|
||||||
|
prevent that, we simply set a ``min-width`` on the ``<span class="line">`` in the right column, and set ``overflow-x:
|
||||||
|
auto`` on the listing ``<pre>``. This results in a horizontal scroll bar appearing whenever the listing gets too narrow.
|
||||||
|
|
||||||
|
You can try out the line wrapping by resizing this page!
|
||||||
|
|
||||||
|
rst2html wrapper
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Here is the python ``rst2html`` wrapper that monkey-patches code rendering. I made hugo invoke this while building the
|
||||||
|
page by simply overriding the ``PATH`` environment variable.
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# Based on https://gist.github.com/mastbaum/2655700 for the basic plugin scaffolding
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
|
import docutils.core
|
||||||
|
from docutils.transforms import Transform
|
||||||
|
from docutils.nodes import TextElement, Inline, Text
|
||||||
|
from docutils.parsers.rst import Directive, directives
|
||||||
|
from docutils.writers.html4css1 import Writer, HTMLTranslator
|
||||||
|
|
||||||
|
|
||||||
|
class UnfuckedHTMLTranslator(HTMLTranslator):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.in_literal_block = False
|
||||||
|
|
||||||
|
def visit_literal_block(self, node):
|
||||||
|
# Insert an empty "lineno" span before each line. We insert the line numbers using pure CSS in a ::before
|
||||||
|
# pseudo-element. This has the added advantage that the line numbers don't get included in text selection.
|
||||||
|
# These line number spans are also used to show line continuation markers when a line is wrapped.
|
||||||
|
self.in_literal_block = True
|
||||||
|
self.body.append(self.starttag(node, 'pre', CLASS='literal-block'))
|
||||||
|
self.body.append('<span class="lineno"></span><span class="line">')
|
||||||
|
|
||||||
|
def depart_literal_block(self, node):
|
||||||
|
self.in_literal_block = False
|
||||||
|
self.body.append('\n</span></pre>\n')
|
||||||
|
|
||||||
|
def visit_Text(self, node):
|
||||||
|
if self.in_literal_block:
|
||||||
|
for match in re.finditer('([^\n]*)(\n|$)', node.astext()):
|
||||||
|
text, end = match.groups()
|
||||||
|
|
||||||
|
if text:
|
||||||
|
super().visit_Text(Text(text))
|
||||||
|
|
||||||
|
if end == '\n':
|
||||||
|
if isinstance(node.parent, Inline):
|
||||||
|
self.depart_inline(node.parent)
|
||||||
|
self.body.append(f'</span>\n<span class="lineno"></span><span class="line">')
|
||||||
|
if isinstance(node.parent, Inline):
|
||||||
|
self.visit_inline(node.parent)
|
||||||
|
|
||||||
|
else:
|
||||||
|
super().visit_Text(node)
|
||||||
|
|
||||||
|
|
||||||
|
html_writer = Writer()
|
||||||
|
html_writer.translator_class = UnfuckedHTMLTranslator
|
||||||
|
docutils.core.publish_cmdline(writer=html_writer)
|
||||||
|
|
||||||
|
.. _Hugo: https://gohugo.io/
|
||||||
|
.. _RestructuredText: https://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html
|
||||||
|
.. _Pygments: https://pygments.org/
|
||||||
|
.. _`monkey-patched`: https://en.wikipedia.org/wiki/Monkey_patch
|
||||||
|
.. _`CSS Counter`: https://developer.mozilla.org/en-US/docs/Web/CSS/counter
|
||||||
100
content/blog/epa-sgd-crypto/index.rst
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
---
|
||||||
|
title: "75 Million Lives, Two Keys"
|
||||||
|
date: 2025-01-05T23:42:00+01:00
|
||||||
|
draft: true
|
||||||
|
---
|
||||||
|
|
||||||
|
2025 has begun. In this new year, with its new national healthcare record system, the country of Germany will start one
|
||||||
|
of the largest rollouts of a cryptographic system in history. While the system has received scrutiny as well as
|
||||||
|
resulting harsh criticism from a number of parties ranging from NGOs to everyday civilians, the system has received
|
||||||
|
surprisingly little attention from the academic applied cryptography crowd. Additionally, previous criticism of
|
||||||
|
the system has largely revolved around organizational issues. While valid, we belive that some cryptographic issues at
|
||||||
|
the core of the system have escaped attention unitl now. In particular, at the core of the system is a key escrow system
|
||||||
|
that contains several questionable design choices and that in its overall design seems out of place in 2025.
|
||||||
|
|
||||||
|
The aim of the system is to serve as a shared storage for all healthcare records of a person. In the system, a person's
|
||||||
|
entire patient file with all documentation on the treatment process including test results, images and other raw data
|
||||||
|
will be stored in something vaguely resembling cloud storage such that all healthcare providers that the person visits
|
||||||
|
can access the entire file. This centralized, synchronized storage eliminates the need for transferring this data
|
||||||
|
between hospitals and doctors offices by fax, mail or physical media as it was common practice until now. After a
|
||||||
|
development and testing phase lasting approximately five years, the German government decided to roll out the system to
|
||||||
|
everybody insured under Germany's mandatory national health insurance scheme, totalling approximately 75 million people,
|
||||||
|
on January 15th 2025.
|
||||||
|
|
||||||
|
In this article, we will give an overview of the system's cryptographic design before highlighting a few odd
|
||||||
|
design choices that could amount to a viable attack vector to the powerful adversaies
|
||||||
|
|
||||||
|
## Context and involved parties
|
||||||
|
|
||||||
|
Germany has a national, mandatory health insurance system. The system is open to any permanent resident of the country
|
||||||
|
irrespective of citizenship. The system is mandatory in that while residents can choose between a number of both
|
||||||
|
publically owned as well as private healthcare providers, it is not possible to opt out of the system. The public health
|
||||||
|
insurance providers cover approximately 90% of German residents. These providers are organized in an umbrella
|
||||||
|
organization named "GKV Spitzenverband". The resposibility of this umbrella organization largely revolves around
|
||||||
|
negotiating prices with pharmaceutical companies and with healthcare providers as a publically sanctioned cartel, but
|
||||||
|
also includes the specification and operation of shared IT infrastructure for billing and data exchange between
|
||||||
|
healthcare providers.
|
||||||
|
|
||||||
|
While GKV Spitzenverband is the party that ultimately holds responsibility for the regulatory administration of national
|
||||||
|
healthcare IT infrastructure, it has delegated large parts of both the technical specification of this infrastructure as
|
||||||
|
well as its day-to-day operation to Gematik GmbH, a state-owned limited liability corporation created specifically for
|
||||||
|
the purpose of developing and implementing national healthcare IT standards. The electronic healthcare record system we
|
||||||
|
describe in this article was standardized and implemented by Gematik GmbH under the direction of GKV Spitzenverband.
|
||||||
|
|
||||||
|
Healthcare providers in Germany need to be registered with GKV Spitzenverband to serve members of public health
|
||||||
|
insurance providers. Since these public providers constitute approximately 90% market share, the vast majority of
|
||||||
|
healthcare providers are registered this way.
|
||||||
|
|
||||||
|
Before the new national health record system, a number of healthcare IT processes have already been standardized and
|
||||||
|
implemented by the parties above. In particular, every insured person already owns a cryptographic smartcard that acts
|
||||||
|
as their proof of identity when accessing healthcare services. On the other side of such transactions, healthcare
|
||||||
|
providers are likewise identified by cryptographic smartcards. Until now, these cards were used to facilitate billing of
|
||||||
|
services from healthcare providers to insurers and to transfer prescriptions from prescribing doctors to pharmacies.
|
||||||
|
|
||||||
|
A central role in this existing infrastructure is assumed by VPN gateways that link healthcare providers to
|
||||||
|
the centrally-run backend infrastructure. Gematik GmbH calls these devices "Konnektor". They are specially-built
|
||||||
|
hardware devices that contain multiple smart cards to authenticate the VPN connection towards the backend, and besides
|
||||||
|
acting as a standard VPN gateway for client applications in the healthcare provider's network to tunnnel their backend
|
||||||
|
requests through, the Konnektors also perform cryptographic operations in some of Gematik GmbH's protocols, such as
|
||||||
|
authenticating certain requests using signatures.
|
||||||
|
|
||||||
|
## Design principles
|
||||||
|
|
||||||
|
The new health record system was built on top of the existing infrastructure described above. In particular, access to
|
||||||
|
health records is managed through keys stored in the patient's and the healthcare provider's existing smartcards, and
|
||||||
|
all backend communication is tunneled through the existing VPN. Access to the files is mediated through the healthcare
|
||||||
|
provider's existing patient management software. While in early drafts of the system, access to healthcare records
|
||||||
|
through the patient's smartcard was gated behind a PIN, the impracticality of making the entire patient populace
|
||||||
|
remember PINs led the implementors to scrap this provision, meaning that the patient's smartcard is all a healthcare
|
||||||
|
provider needs to access the patient's record.
|
||||||
|
|
||||||
|
A critical cornerstone in the system's design is that the system's designers decided that a lost smartcard should not
|
||||||
|
lead to any data loss. As a consequence of this decision, while some of the record's access keys are kept on the
|
||||||
|
patient smartcard, in contravention to conventional smartcard designs the same keys are kept accessible in a centralized
|
||||||
|
key escrow system named "Schlüsselgenerierungsdienst" and abbreviated as SGD. Furthermore, these keys are not generated
|
||||||
|
on the smartcard either -- instead, the key escrow system generates these access keys, one copy of which is then
|
||||||
|
transmitted and stored inside the smartcard.
|
||||||
|
|
||||||
|
The system supports re-issuing a smartcard to gain access to a healthcare record. Since the record's privacy pivots on
|
||||||
|
this process, the system incorporates some organziational countermeasures that aim to make it hard to gain access to a
|
||||||
|
re-issued copy of a patient smartcard without the patient's help or otherwise multiple colluding parties.
|
||||||
|
|
||||||
|
## Cryptographic design
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## The implied adversary model
|
||||||
|
|
||||||
|
While Gematik GmbH publishes detailed specifications of the systems they standardize, these specifications and some
|
||||||
|
associated implementation guidelines are about the extent of public information. Software implementations are being kept
|
||||||
|
secret, and while standardization results are available, a large fraction of design rationale is discussed behind closed
|
||||||
|
doors. From an academic perspective, the most glaring omission in Gematik GmbH's public documents is any definition of a
|
||||||
|
threat model or an adversary model. As a result of this, we will deduce an adversary model below by contextualizing the
|
||||||
|
published standards in the national healthcare setting. We will base our further analysis of the system on this
|
||||||
|
adversary model.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Previous reviews and audits of the system
|
||||||
|
|
||||||
|
[0] https://www.destatis.de/DE/Themen/Arbeit/Arbeitsmarkt/Qualitaet-Arbeit/Dimension-2/krankenversicherungsschutz.html
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
---
|
---
|
||||||
title: "Hardware Security Module Basics"
|
title: "Hardware Security Module Basics"
|
||||||
date: 2019-05-17T15:29:20+08:00
|
date: 2019-05-17T15:29:20+08:00
|
||||||
|
summary: >
|
||||||
|
I gave a short introduction into Hardware Security Modules at our university workgroup, including an overview on
|
||||||
|
interesting research directions.
|
||||||
---
|
---
|
||||||
|
|
||||||
Hardware Security Modules and Security Research and Cryptography
|
|
||||||
================================================================
|
|
||||||
|
|
||||||
On May 17 2019 I gave a short presentation on the fundamentals of hardware security modules at the weekly seminar of
|
On May 17 2019 I gave a short presentation on the fundamentals of hardware security modules at the weekly seminar of
|
||||||
Prof. Mori's security research working group at Waseda University. The motivation for this was that outside of low-level
|
Prof. Mori's security research working group at Waseda University. The motivation for this was that outside of low-level
|
||||||
hardware security people and people working in the financial industry HSMs are not thought about that often. In
|
hardware security people and people working in the financial industry HSMs are not thought about that often. In
|
||||||
|
|
@ -113,21 +113,26 @@ The core component of an HSM blueprint would be a suite of tamper detection mech
|
||||||
to improve on the current state of the art of membrane tamper switches plus temperature sensors plus PCB and printed
|
to improve on the current state of the art of membrane tamper switches plus temperature sensors plus PCB and printed
|
||||||
security meshes plus potting.
|
security meshes plus potting.
|
||||||
|
|
||||||
Improvements on existing techniques
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
Light sensors
|
|
||||||
~~~~~~~~~~~~~
|
|
||||||
**Advanced analog sensing**
|
|
||||||
**Self-test functionality**
|
|
||||||
|
|
||||||
Security meshes
|
|
||||||
~~~~~~~~~~~~~~~
|
|
||||||
**Analog sensing**
|
|
||||||
|
|
||||||
|
|
||||||
DIY or small lab mesh production
|
DIY or small lab mesh production
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
**Analog sensing** meshes are a proven technology where instead of just monitoring for continuity and shorts, analog
|
||||||
|
parameters of the mesh traces such as inductance and mutual capacitance are monitored. In 2019, `Immler et al. published
|
||||||
|
a paper <https://tches.iacr.org/index.php/TCHES/article/view/7334>`__ where took this principle and turned it all the
|
||||||
|
way up. They directly derived a cryptographic secret from the analog properties of their HSM's security mesh in an
|
||||||
|
attempt to built a `Physically Unclonable Function, or PUF
|
||||||
|
<https://en.wikipedia.org/wiki/Physical_unclonable_function>`__. The idea with PUFs is that they reproduce some entropy
|
||||||
|
that comes from random tolerances of their production process. The same PUF will always yield (approximately) the same
|
||||||
|
key, but since you cannot control these random production variations, in practice the resulting PUF cannot be cloned.
|
||||||
|
Note however, that its secrets can of course be copied if you find a way to read them out.
|
||||||
|
|
||||||
|
As Immler et al. demonstrated in their paper, you don't need any secret sauce to create an analog mesh sensing circuit.
|
||||||
|
All you need are a bunch of (admittedly, expensive) off-the-shelf analog ICs. The interesting bit here is that by
|
||||||
|
applying more advanced analog sensing, weaknesses of an otherwise coarse mesh desing could maybe be alleviated. That is,
|
||||||
|
instead of monitoring a very fine mesh for continuity, you could instead closely monitor inductance and capacitance of a
|
||||||
|
more coarse mesh. This trade-off between sensing circuit complexity (resp. cost) and mesh production capabilities may
|
||||||
|
allow someone with a poorly equipped lab to still make a decent HSM. The question is, how do you produce a "decent" mesh
|
||||||
|
given only basic tools? Here are some ideas.
|
||||||
|
|
||||||
**3D metal patterning techniques** refers to any technique for producing thin, patterned metal structures on a
|
**3D metal patterning techniques** refers to any technique for producing thin, patterned metal structures on a
|
||||||
three-dimensional plastic substrate. The basic process would consist of 3D-printing the polymer substrate, depositing a
|
three-dimensional plastic substrate. The basic process would consist of 3D-printing the polymer substrate, depositing a
|
||||||
thin metal layer on top and then patterning this metal layer. A good starting point here would be the recent work of
|
thin metal layer on top and then patterning this metal layer. A good starting point here would be the recent work of
|
||||||
44
content/blog/ihsm-worlds-first-diy-hsm/index.rst
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
---
|
||||||
|
title: "New Paper on Inertial Hardware Security Modules"
|
||||||
|
date: 2021-11-23T23:42:20+01:00
|
||||||
|
summary: >
|
||||||
|
Paper announcement: We have published a paper on how you can DIY a tamper-sensing hardware security module from any
|
||||||
|
single-board computer using a moving tamper-sensing mesh made from cheap PCBs.
|
||||||
|
---
|
||||||
|
|
||||||
|
World's First DIY HSM
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Last week, Prof. Dr. Björn Scheuermann and I have `published our first joint paper on Hardware Security Modules
|
||||||
|
<https://tches.iacr.org/index.php/TCHES/article/view/9290>`__. In our paper, we introduce Inertial Hardware Security
|
||||||
|
Modules (IHSMs), a new way of building high-security HSMs from basic components. I think the technology we demonstrate
|
||||||
|
in our paper might allow some neat applications where some civil organization deploys a service that no one, not even
|
||||||
|
they themselves, can snoop on. Anyone can built an IHSM without needing any fancy equipment, which makes me optimistic
|
||||||
|
that maybe the ideas of the `Cypherpunk movement <https://www.activism.net/cypherpunk/manifesto.html>`__ aren't obsolete
|
||||||
|
after all, despite even the word "crypto" having been co-opted by radical capitalist environmental destructionists.
|
||||||
|
|
||||||
|
An IHSM is basically an ultra-secure enclosure for something like a server or a raspberry pi that even someone with
|
||||||
|
unlimited resources would have a really hard time cracking without destroying all data stored in it. The principle of an
|
||||||
|
IHSM is the same as that of a `normal HSM`_. You have a payload that contains really secret data. There's really no way
|
||||||
|
to prevent an attacker with physical access to the thing from opening it given enough time and abrasive discs for their
|
||||||
|
angle grinder. So what you do instead is that you make it self-destruct its secrets within microseconds of anyone
|
||||||
|
tampering with it. Usually, such HSMs are used for storing credit card pins and other financial data. They're expensive
|
||||||
|
as fuck, all the while being about the same processing speed as a smartphone. Traditional HSMs use printed or
|
||||||
|
lithographically patterned conductive foils for their security mesh. These foils are not an off-the-shelf component and
|
||||||
|
are made in a completely custom manufacturing process. To create your own, you would have to re-engineer that entire
|
||||||
|
process and probably spend some serious money on production machines.
|
||||||
|
|
||||||
|
Inertial HSMs take the concept of traditional HSMs, but replace the usual tamper detection mesh with a few security mesh
|
||||||
|
PCBs. These PCBs are coarser than traditional meshes by orders of magnitude, and would alone not even be close to enough
|
||||||
|
to keep out even a moderately motivated attacker. IHSMs fix this issue by spinning the entire tamper detection mesh at
|
||||||
|
very high speed. To tamper with the mesh, an attacker would have to stop it. This, in turn, can be easily detected by
|
||||||
|
the mesh's alarm circuitry using a simple accelerometer as a rotation sensor.
|
||||||
|
|
||||||
|
In our paper, we have shown a working prototype of the core concepts one needs to build such an IHSM. To build an IHSM
|
||||||
|
you only need a basic electronics lab. I built the prototype in our paper at home during one of Germany's COVID
|
||||||
|
lockdowns. You can have a look at our code and CAD on `my git <https://git.jaseg.de/ihsm.git>`__. What is missing right
|
||||||
|
now is an integration of all of these fragments into something cohesive that an interested person with the right tools
|
||||||
|
could go out and build. We are planning to release this sort of documentation at some point, but right now we are
|
||||||
|
focusing our effort on the next iteration of the design instead. Stay tuned for updates ;)
|
||||||
|
|
||||||
|
.. _`normal HSM`: {{<ref "blog/hsm-basics/index.rst">}}
|
||||||
21
content/blog/jupyterlab-notebook-file-oneliner/index.rst
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
title: "Getting the .ipynb Notebook File Location From a Running Jupyter Lab Notebook"
|
||||||
|
date: 2025-06-29T23:42:00+01:00
|
||||||
|
summary: >
|
||||||
|
If you need to get the path of the ipynb file in a running #Jupyter notebook, this one-liner will do the trick. It
|
||||||
|
seems chatgpt is confused, and a bunch of other approaches on the web look fragile and/or unnecessarily complex to
|
||||||
|
me.
|
||||||
|
---
|
||||||
|
|
||||||
|
If you need to get the path of the ipynb file in a running #Jupyter notebook, this one-liner will do the trick. It seems
|
||||||
|
chatgpt is confused, and a bunch of other approaches on the web look fragile and/or unnecessarily complex to me.
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
import sys
|
||||||
|
Path(json.loads(Path(sys.argv[-1]).read_bytes())['jupyter_session'])
|
||||||
|
|
||||||
|
The way this works is that for each notebook, jupyter starts a python "kernel" process that actually runs the notebook's
|
||||||
|
code. That kernel gets a json file with info on the notebook's location on the disk passed through its command line.
|
||||||
|
Since we're running code in that exact python process, we can just grab that json file from sys.argv, and read it
|
||||||
|
ourselves.
|
||||||
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 292 KiB After Width: | Height: | Size: 292 KiB |
|
Before Width: | Height: | Size: 296 KiB After Width: | Height: | Size: 296 KiB |
|
Before Width: | Height: | Size: 296 KiB After Width: | Height: | Size: 296 KiB |
|
Before Width: | Height: | Size: 296 KiB After Width: | Height: | Size: 296 KiB |
|
Before Width: | Height: | Size: 296 KiB After Width: | Height: | Size: 296 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 193 KiB After Width: | Height: | Size: 193 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 189 KiB |
|
Before Width: | Height: | Size: 175 KiB After Width: | Height: | Size: 175 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 809 KiB After Width: | Height: | Size: 809 KiB |
|
|
@ -1,12 +1,16 @@
|
||||||
---
|
---
|
||||||
title: "Kicad Mesh Plugin"
|
title: "Kicad Mesh Plugin"
|
||||||
date: 2020-08-18T13:15:39+02:00
|
date: 2020-08-18T13:15:39+02:00
|
||||||
|
summary: >
|
||||||
|
I wrote a little KiCad plugin that you can use to create security meshes, heaters and other things where you need
|
||||||
|
one or more traces cover the entire surface of a PCB. The plugin supports arbitrary PCB shapes, cutouts, and can
|
||||||
|
route around existing footprints and traces on the PCB.
|
||||||
---
|
---
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/anim.webp" style="max-width: 20em">
|
<img src="images/anim.webp" style="max-width: 20em">
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
Tamper Detection Meshes
|
Tamper Detection Meshes
|
||||||
|
|
@ -38,7 +42,7 @@ stored on the card, things such as copying of a card can only be hindered by mak
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/modern_art.svg" style="max-width: 20em">
|
<img src="images/modern_art.svg" style="max-width: 20em">
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
@ -68,7 +72,7 @@ DIY Meshes
|
||||||
|
|
||||||
Throughout my studies in security research I have always had an interest in HSMs. I have taken apart my fair share of
|
Throughout my studies in security research I have always had an interest in HSMs. I have taken apart my fair share of
|
||||||
HSMs and at this point, to understand the technology more, I want to experiment with building my own HSM. In last year's
|
HSMs and at this point, to understand the technology more, I want to experiment with building my own HSM. In last year's
|
||||||
`HSM basics <{{<ref "posts/hsm-basics/index.rst">}}>`_ post I have lined out some ideas for a next generation design that
|
`HSM basics <{{<ref "blog/hsm-basics/index.rst">}}>`_ post I have lined out some ideas for a next generation design that
|
||||||
deviates from the bread-and-butter apporoach of using a mesh as the primary security feature. Before embarking on
|
deviates from the bread-and-butter apporoach of using a mesh as the primary security feature. Before embarking on
|
||||||
practical experiments with these ideas, I want to first take a stab at replicating the current state of the art as best
|
practical experiments with these ideas, I want to first take a stab at replicating the current state of the art as best
|
||||||
I can. State of the art meshes often use exotic substrates such as 3D plastic parts with traces chemically deposited on
|
I can. State of the art meshes often use exotic substrates such as 3D plastic parts with traces chemically deposited on
|
||||||
|
|
@ -93,7 +97,7 @@ usable for this task.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/kicad-mesh-outline.png" alt="KiCAD showing an irregular board shape with rounded corners and
|
<img src="images/kicad-mesh-outline.png" alt="KiCAD showing an irregular board shape with rounded corners and
|
||||||
indents. In the middle of the board there is a footprint for a 4-pin surface-mount pin header.">
|
indents. In the middle of the board there is a footprint for a 4-pin surface-mount pin header.">
|
||||||
<figcaption>The process starts out with the mesh shape being defined inside KiCAD. The mesh's outline is drawn
|
<figcaption>The process starts out with the mesh shape being defined inside KiCAD. The mesh's outline is drawn
|
||||||
|
|
@ -104,7 +108,7 @@ usable for this task.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/grid-vis-plain.svg" alt="A vizualization of the grid fitting process. Over the mesh's irregular
|
<img src="images/grid-vis-plain.svg" alt="A vizualization of the grid fitting process. Over the mesh's irregular
|
||||||
outline a grid is drawn. In this picture, all grid cells that are fully inside the grid are shown. Grid cells
|
outline a grid is drawn. In this picture, all grid cells that are fully inside the grid are shown. Grid cells
|
||||||
that overlap the mesh border are highlighted. Grid cells outside of the mesh border are not drawn.">
|
that overlap the mesh border are highlighted. Grid cells outside of the mesh border are not drawn.">
|
||||||
|
|
@ -125,25 +129,29 @@ means that on every step, the algorithm is choosing a new direction at random.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<div class="subfigure" data-pagefind-ignore>
|
||||||
<figure class="side-by-side">
|
<figure>
|
||||||
<img src="images/cells-0.svg" alt="a completely organized looking grid with spiral patterns all over.">
|
<img src="images/cells-0.svg" alt="a completely organized looking grid with spiral patterns all over.">
|
||||||
<figcaption>0%</figcaption>
|
<figcaption>0%</figcaption>
|
||||||
</figure><figure class="side-by-side">
|
</figure>
|
||||||
<img src="images/cells-25.svg">
|
<figure>
|
||||||
<figcaption>25%</figcaption>
|
<img src="images/cells-25.svg">
|
||||||
</figure><figure class="side-by-side">
|
<figcaption>25%</figcaption>
|
||||||
<img src="images/cells-50.svg">
|
</figure>
|
||||||
<figcaption>50%</figcaption>
|
<figure>
|
||||||
</figure><figure class="side-by-side">
|
<img src="images/cells-50.svg">
|
||||||
<img src="images/cells-75.svg">
|
<figcaption>50%</figcaption>
|
||||||
<figcaption>75%</figcaption>
|
</figure>
|
||||||
</figure><figure class="side-by-side">
|
<figure>
|
||||||
<img src="images/cells-100.svg" alt="a completely random looking grid with cells aggregating into ireggular
|
<img src="images/cells-75.svg">
|
||||||
areas that look like paint splotches.">
|
<figcaption>75%</figcaption>
|
||||||
<figcaption>100%</figcaption>
|
</figure>
|
||||||
</figure>
|
<figure>
|
||||||
</figure>
|
<img src="images/cells-100.svg" alt="a completely random looking grid with cells aggregating into ireggular
|
||||||
|
areas that look like paint splotches.">
|
||||||
|
<figcaption>100%</figcaption>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
|
||||||
After I have built this tree like you would do in a depth-first search, I draw my one or several mesh mesh traces into
|
After I have built this tree like you would do in a depth-first search, I draw my one or several mesh mesh traces into
|
||||||
it. The core observation here is that there is only 16 possible ways a cell can be connected: It has four neighbors,
|
it. The core observation here is that there is only 16 possible ways a cell can be connected: It has four neighbors,
|
||||||
|
|
@ -153,7 +161,7 @@ sides connected, a straight through, a 90 degree bend, and a "T"-junction—see
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/maze_tiles_plain.svg" style="max-width: 20em">
|
<img src="images/maze_tiles_plain.svg" style="max-width: 20em">
|
||||||
<figcaption>
|
<figcaption>
|
||||||
There are six possible tile types in our connectivity graph inside its square tiling. This graphic illustrates
|
There are six possible tile types in our connectivity graph inside its square tiling. This graphic illustrates
|
||||||
|
|
@ -165,7 +173,7 @@ After tiling the grid according to the key above, we get the result below.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/tiles-25-small.svg">
|
<img src="images/tiles-25-small.svg">
|
||||||
<figcaption>
|
<figcaption>
|
||||||
An auto-routed mesh with traces colored according to tile types.
|
An auto-routed mesh with traces colored according to tile types.
|
||||||
|
|
@ -174,7 +182,7 @@ After tiling the grid according to the key above, we get the result below.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/traces-25-small.svg">
|
<img src="images/traces-25-small.svg">
|
||||||
<figcaption>
|
<figcaption>
|
||||||
The same mesh, but with traces all black.
|
The same mesh, but with traces all black.
|
||||||
|
|
@ -185,7 +193,7 @@ Putting it all together got me the KiCAD plugin you can see in the screenshot be
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/kicad-mesh-settings2.png">
|
<img src="images/kicad-mesh-settings2.png">
|
||||||
<figcaption>
|
<figcaption>
|
||||||
The plugin settings window open.
|
The plugin settings window open.
|
||||||
|
|
@ -194,11 +202,11 @@ Putting it all together got me the KiCAD plugin you can see in the screenshot be
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/kicad-mesh-result-large.png">
|
<img src="images/kicad-mesh-result-large.png">
|
||||||
<figcaption>
|
<figcaption>
|
||||||
After runing the plugin, the generated mesh looks like this in pcbnew.
|
After runing the plugin, the generated mesh looks like this in pcbnew.
|
||||||
</figcaption>
|
</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
I am fairly happy with the result, but getting there was a medium pain. Especially KiCAD's plugin API is still very
|
I am fairly happy with the result, but getting there was a medium pain. Especially KiCAD's plugin API is still very
|
||||||
|
|
@ -214,7 +222,7 @@ making a copy of the board file first and treating mesh generation as a non-reve
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/grid-vis-plain.svg" alt="">
|
<img src="images/grid-vis-plain.svg" alt="">
|
||||||
<figcaption></figcaption>
|
<figcaption></figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
BIN
content/blog/kicoil-theory/header.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
40
content/blog/kicoil-theory/index.rst
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
---
|
||||||
|
title: "The KiCoil Planar Coil Generator"
|
||||||
|
date: 2025-12-31T13:15:39+02:00
|
||||||
|
summary: >
|
||||||
|
I wrote a layout tool generating planar coils that can handle spiral coils, toroidal coils, and hybrids in between
|
||||||
|
the two.
|
||||||
|
---
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<figure data-pagefind-ignore>
|
||||||
|
<img src="header.png" style="max-width: 20em">
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
A planar coil is a coil that is made from flat traces in some printing process like PCB or IC manufacturing, instead of
|
||||||
|
being wound from wire. A few weeks ago, I needed one such planar coil that
|
||||||
|
|
||||||
|
|
||||||
|
Project State
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Currently, circular coils are special cased. Their layouts are directly generated, without the use of polygon
|
||||||
|
offsetting. Windings are efficiently approximated using circular arcs. The circular coil layout code is solid, and
|
||||||
|
contains decent (albeit not infallible) parameter sanity checks. Its main limitation is that sometimes, clearances can
|
||||||
|
be violated a bit.
|
||||||
|
|
||||||
|
The arbitrary shape code path is less stable, and produces faulty output in some cases. The most common error is
|
||||||
|
crossing traces near the first vertex of the polygon when the polygon has highly convex or concave parts. I'm still
|
||||||
|
improving this code path, but as long as you check the output, any errors it produces should be easy to fix by hand.
|
||||||
|
|
||||||
|
If you would like to contribute, I'd welcome any ideas on the arbitrary shape code path. I think there is no single
|
||||||
|
optimal solution here, and a generic algorithm that can be adjusted to favor for instance shape accuracy versus winding
|
||||||
|
smoothness would be nice.
|
||||||
|
|
||||||
|
All project links are listed on `https://jaseg.de/projects/kicoil/ <https://jaseg.de/projects/kicoil/>`__. You can check
|
||||||
|
out the code on my git at `https://git.jaseg.de/kicoil.git <https://git.jaseg.de/kicoil.git>`__. Issues are tracked on
|
||||||
|
codeberg at `https://codeberg.org/jaseg/kicoil <https://codeberg.org/jaseg/kicoil>`__. The kicad addon can be installed
|
||||||
|
from the KiCad plugin manager, and you can install the standalone kicoil python package `from PyPI
|
||||||
|
<https://pypi.org/project/kicoil/>`__.
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 279 KiB After Width: | Height: | Size: 279 KiB |
|
Before Width: | Height: | Size: 285 KiB After Width: | Height: | Size: 285 KiB |
|
Before Width: | Height: | Size: 428 KiB After Width: | Height: | Size: 428 KiB |
|
Before Width: | Height: | Size: 287 KiB After Width: | Height: | Size: 287 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 332 KiB After Width: | Height: | Size: 332 KiB |
|
Before Width: | Height: | Size: 301 KiB After Width: | Height: | Size: 301 KiB |
|
Before Width: | Height: | Size: 271 KiB After Width: | Height: | Size: 271 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 278 KiB After Width: | Height: | Size: 278 KiB |
|
Before Width: | Height: | Size: 271 KiB After Width: | Height: | Size: 271 KiB |
|
Before Width: | Height: | Size: 250 KiB After Width: | Height: | Size: 250 KiB |
|
Before Width: | Height: | Size: 297 KiB After Width: | Height: | Size: 297 KiB |
|
Before Width: | Height: | Size: 435 KiB After Width: | Height: | Size: 435 KiB |
|
Before Width: | Height: | Size: 2.4 MiB After Width: | Height: | Size: 2.4 MiB |
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 1.8 MiB |
|
|
@ -1,6 +1,12 @@
|
||||||
---
|
---
|
||||||
title: "LED Characterization"
|
title: "LED Characterization"
|
||||||
date: 2018-05-02T11:18:38+02:00
|
date: 2018-05-02T11:18:38+02:00
|
||||||
|
summary: >
|
||||||
|
Recently, I have been working on a small driver for ambient lighting using 12V LED strips like you can get
|
||||||
|
inexpensively from China. I wanted to be able to just throw one of these somewhere, stick down some LED tape, hook
|
||||||
|
it up to a small transformer and be able to control it through Wifi. When I was writing the firmware, I noticed that
|
||||||
|
when fading between different colors, the colors look *all wrong*! This observation led me down a rabbit hole of
|
||||||
|
color perception and LED peculiarities.
|
||||||
---
|
---
|
||||||
|
|
||||||
Preface
|
Preface
|
||||||
|
|
@ -19,7 +25,7 @@ really important so you could dim it down a lot without flickering. I ended up u
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/rgb_cube.svg" alt="An illustration of the RGB color cube.">
|
<img src="images/rgb_cube.svg" alt="An illustration of the RGB color cube.">
|
||||||
<figcaption>An illustration of the RGB color cube.
|
<figcaption>An illustration of the RGB color cube.
|
||||||
<a href="https://commons.wikimedia.org/wiki/File:RGB_color_cube.svg">Picture</a> by
|
<a href="https://commons.wikimedia.org/wiki/File:RGB_color_cube.svg">Picture</a> by
|
||||||
|
|
@ -46,7 +52,7 @@ transformation.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/hsv_cylinder.png" alt="An illustration of the HSV color space as a cylinder.">
|
<img src="images/hsv_cylinder.png" alt="An illustration of the HSV color space as a cylinder.">
|
||||||
<figcaption>An illustration of the HSV color space as a cylinder.
|
<figcaption>An illustration of the HSV color space as a cylinder.
|
||||||
<a href="https://commons.wikimedia.org/wiki/File:HSV_color_solid_cylinder.png">Picture</a> by
|
<a href="https://commons.wikimedia.org/wiki/File:HSV_color_solid_cylinder.png">Picture</a> by
|
||||||
|
|
@ -67,7 +73,7 @@ particular in the blues and greens we loose *a lot* of colors to sRGB.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<video controls loop>
|
<video controls loop>
|
||||||
<source src="video/sRGB.mkv" type="video/h264">
|
<source src="video/sRGB.mkv" type="video/h264">
|
||||||
<source src="video/sRGB.webm" type="video/webm">
|
<source src="video/sRGB.webm" type="video/webm">
|
||||||
|
|
@ -98,19 +104,20 @@ over the problem, there are several sources for imperfections:
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<div class="subfigure" data-pagefind-ignore>
|
||||||
<figure class="side-by-side">
|
<figure>
|
||||||
<img src="images/driver_ringing_strong.jpg" alt="Strong ringing on the LED voltage waveform edge at about
|
<img src="images/driver_ringing_strong.jpg" alt="Strong ringing on the LED voltage waveform edge at about
|
||||||
100% overshoot during about 70% of the cycle time.">
|
100% overshoot during about 70% of the cycle time.">
|
||||||
<figcaption>The LED strip being at the end of a couple meters of wire caused extremely bad ringing at high
|
<figcaption>The LED strip being at the end of a couple meters of wire caused extremely bad ringing at high
|
||||||
driving frequencies.</figcaption>
|
driving frequencies.</figcaption>
|
||||||
</figure><figure class="side-by-side">
|
</figure>
|
||||||
|
<figure>
|
||||||
<img src="images/driver_ringing_weak.jpg" alt="Weak ringing on the LED voltage waveform edge at about 30%
|
<img src="images/driver_ringing_weak.jpg" alt="Weak ringing on the LED voltage waveform edge at about 30%
|
||||||
overshoot during about 20% of the cycle time.">
|
overshoot during about 20% of the cycle time.">
|
||||||
<figcaption>Adding a resistor in front of the MOSFET gate to slow the transition dampened the ringing
|
<figcaption>Adding a resistor in front of the MOSFET gate to slow the transition dampened the ringing
|
||||||
somewhat, but ultimately it cannot be eliminated entirely.</figcaption>
|
somewhat, but ultimately it cannot be eliminated entirely.</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
</figure>
|
</div>
|
||||||
|
|
||||||
These last two errors are tricky to compensate. What I needed for that was basically a model of the *perceived* colors
|
These last two errors are tricky to compensate. What I needed for that was basically a model of the *perceived* colors
|
||||||
of the LED tape's color channels. A way of doing his is to record the spectra of all color channels and then evaluate
|
of the LED tape's color channels. A way of doing his is to record the spectra of all color channels and then evaluate
|
||||||
|
|
@ -159,25 +166,27 @@ spectrum of the phosphor.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<div class="subfigure" data-pagefind-ignore>
|
||||||
<figure class="side-by-side">
|
<figure>
|
||||||
<img src="images/spectrograph_step1_parts.jpg">
|
<img src="images/spectrograph_step1_parts.jpg">
|
||||||
<figcaption>The ingredients. The cup of coffee and Madoka Magica DVD set are essential to the eventual
|
<figcaption>The ingredients. The cup of coffee and Madoka Magica DVD set are essential to the eventual
|
||||||
function of the appartus.</figcaption>
|
function of the appartus.</figcaption>
|
||||||
</figure><figure class="side-by-side">
|
</figure>
|
||||||
|
<figure>
|
||||||
<img src="images/spectrograph_step2.jpg">
|
<img src="images/spectrograph_step2.jpg">
|
||||||
<figcaption>Step 1: Cut to size and mark down all holes as described in <a
|
<figcaption>Step 1: Cut to size and mark down all holes as described in <a
|
||||||
href="http://www.candac.ca/candacweb/sites/default/files/BuildaSpectroscope.pdf">the manual</a></figcaption>
|
href="http://www.candac.ca/candacweb/sites/default/files/BuildaSpectroscope.pdf">the manual</a></figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
<figure class="side-by-side">
|
<figure>
|
||||||
<img src="images/spectrograph_step3.jpg">
|
<img src="images/spectrograph_step3.jpg">
|
||||||
<figcaption>Step 2: Cut out all holes</figcaption>
|
<figcaption>Step 2: Cut out all holes</figcaption>
|
||||||
</figure><figure class="side-by-side">
|
</figure>
|
||||||
|
<figure>
|
||||||
<img src="images/spectrograph_step4_complete.jpg">
|
<img src="images/spectrograph_step4_complete.jpg">
|
||||||
<figcaption>The finished result with the back side showing. The viewing window is on the bottom of the other
|
<figcaption>The finished result with the back side showing. The viewing window is on the bottom of the other
|
||||||
side.</figcaption>
|
side.</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
</figure>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
Now that I had a spectrograph, I needed a somewhat predictable way of measuring the spectrum it gave me.
|
Now that I had a spectrograph, I needed a somewhat predictable way of measuring the spectrum it gave me.
|
||||||
|
|
@ -192,7 +201,7 @@ different colors on their pictures. Some other sensor was needed.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/daylight_spectrum_dvd.jpg">
|
<img src="images/daylight_spectrum_dvd.jpg">
|
||||||
<figcaption>The daylight spectrum as seen using a DVD as a grating.
|
<figcaption>The daylight spectrum as seen using a DVD as a grating.
|
||||||
<a href="https://commons.wikimedia.org/wiki/File:SpectresSolaires-DVD.jpg">Picture</a> by
|
<a href="https://commons.wikimedia.org/wiki/File:SpectresSolaires-DVD.jpg">Picture</a> by
|
||||||
|
|
@ -232,7 +241,7 @@ trimpot on the virtual ground both amplifers use as a reference so I could trim
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/preamp_schematic.jpg" alt="A drawing of the photodiode preamplifier's schematic">
|
<img src="images/preamp_schematic.jpg" alt="A drawing of the photodiode preamplifier's schematic">
|
||||||
<figcaption>The photodiode preamplifier schematic. Schematic drawn with an unlicensed copy of
|
<figcaption>The photodiode preamplifier schematic. Schematic drawn with an unlicensed copy of
|
||||||
DaveCAD.</figcaption>
|
DaveCAD.</figcaption>
|
||||||
|
|
@ -252,15 +261,16 @@ here.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<div class="subfigure" data-pagefind-ignore>
|
||||||
<figure class="side-by-side">
|
<figure>
|
||||||
<img src="images/preamp_front.jpg">
|
<img src="images/preamp_front.jpg">
|
||||||
<figcaption>The front side of the preamplifier board.</figcaption>
|
<figcaption>The front side of the preamplifier board.</figcaption>
|
||||||
</figure><figure class="side-by-side">
|
</figure>
|
||||||
|
<figure>
|
||||||
<img src="images/preamp_back.jpg">
|
<img src="images/preamp_back.jpg">
|
||||||
<figcaption>The wiring of the photodiode preamp.</figcaption>
|
<figcaption>The wiring of the photodiode preamp.</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
</figure>
|
</div>
|
||||||
|
|
||||||
Given a way to measure intensity what remains missing is a way to scan a single photodiode across the spectrum.
|
Given a way to measure intensity what remains missing is a way to scan a single photodiode across the spectrum.
|
||||||
|
|
||||||
|
|
@ -286,7 +296,7 @@ The whole unit with photodiode preamplifier, linear stage, photodiode and steppe
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/electronics_whole.jpg" alt="The complete electronics setup of the spectrograph. In the back
|
<img src="images/electronics_whole.jpg" alt="The complete electronics setup of the spectrograph. In the back
|
||||||
there is the DVD drive stepper stage. In front of it, mounted on a piece of wood are a small USB-to-12V
|
there is the DVD drive stepper stage. In front of it, mounted on a piece of wood are a small USB-to-12V
|
||||||
switching-regulator module to power the stepper motor in the top left, below on the bottom left is the
|
switching-regulator module to power the stepper motor in the top left, below on the bottom left is the
|
||||||
|
|
@ -334,7 +344,7 @@ begin.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/raw_plot_cheap_rgb.svg" alt="A plot with three wide peaks, two large peaks on both sides and
|
<img src="images/raw_plot_cheap_rgb.svg" alt="A plot with three wide peaks, two large peaks on both sides and
|
||||||
one smaller one in the middle. The middle one overlaps the two on the sides. The large ones are about 2.5V in
|
one smaller one in the middle. The middle one overlaps the two on the sides. The large ones are about 2.5V in
|
||||||
amplitude. Overall, the plot is about 300 stepper steps wide with each peak being around 130 steps wide.">
|
amplitude. Overall, the plot is about 300 stepper steps wide with each peak being around 130 steps wide.">
|
||||||
|
|
@ -371,7 +381,7 @@ of the blue peak towards red.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/photodiode_sensitivity.svg" alt="A plot of photodiode sensitivity against wavelength relative
|
<img src="images/photodiode_sensitivity.svg" alt="A plot of photodiode sensitivity against wavelength relative
|
||||||
to peak sensitivity at 820nm. The sensitivity rises from 20% at 380nm approximately linearly to 80% at 620nm,
|
to peak sensitivity at 820nm. The sensitivity rises from 20% at 380nm approximately linearly to 80% at 620nm,
|
||||||
then the rise rolls off.">
|
then the rise rolls off.">
|
||||||
|
|
@ -390,7 +400,7 @@ wavelength in nanometers.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/processed_plot_cheap_rgb.svg" alt="A plot with three wide peaks, all three of different
|
<img src="images/processed_plot_cheap_rgb.svg" alt="A plot with three wide peaks, all three of different
|
||||||
heights. The leftmost peak is highest at 6nA, the middle peak lowest at 1.6nA and the rightmost peak in between
|
heights. The leftmost peak is highest at 6nA, the middle peak lowest at 1.6nA and the rightmost peak in between
|
||||||
at 4nA. The middle one overlaps the two on the sides. Overall, the plot spans about 300nm on its x axis with
|
at 4nA. The middle one overlaps the two on the sides. Overall, the plot spans about 300nm on its x axis with
|
||||||
|
|
@ -424,7 +434,7 @@ models can be found in the `project repo`_.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<video controls loop>
|
<video controls loop>
|
||||||
<source src="video/led_within_srgb_scale=1.0.mkv" type="video/h264">
|
<source src="video/led_within_srgb_scale=1.0.mkv" type="video/h264">
|
||||||
<source src="video/led_within_srgb_scale=1.0.webm" type="video/webm">
|
<source src="video/led_within_srgb_scale=1.0.webm" type="video/webm">
|
||||||
|
|
@ -479,9 +489,9 @@ can view the Jupyter notebook most of the analysis above `here <http://nbviewer.
|
||||||
|
|
||||||
.. _`on Github`: https://github.com/jaseg/esp_led_drv/blob/master/user/led_controller.c
|
.. _`on Github`: https://github.com/jaseg/esp_led_drv/blob/master/user/led_controller.c
|
||||||
.. _`project repo`: https://github.com/jaseg/led_drv
|
.. _`project repo`: https://github.com/jaseg/led_drv
|
||||||
.. _`Wifi LED driver`: {{<ref "posts/wifi-led-driver/index.rst">}}
|
.. _`Wifi LED driver`: {{<ref "blog/wifi-led-driver/index.rst">}}
|
||||||
.. _`small driver`: {{<ref "posts/wifi-led-driver/index.rst">}}
|
.. _`small driver`: {{<ref "blog/wifi-led-driver/index.rst">}}
|
||||||
.. _`multichannel LED driver`: {{<ref "posts/multichannel-led-driver/index.rst">}}
|
.. _`multichannel LED driver`: {{<ref "blog/multichannel-led-driver/index.rst">}}
|
||||||
.. _`sRGB`: https://en.wikipedia.org/wiki/SRGB
|
.. _`sRGB`: https://en.wikipedia.org/wiki/SRGB
|
||||||
.. _`CC BY-SA 3.0`: https://creativecommons.org/licenses/by-sa/3.0
|
.. _`CC BY-SA 3.0`: https://creativecommons.org/licenses/by-sa/3.0
|
||||||
.. _`Color spaces`: https://en.wikipedia.org/wiki/Color_space
|
.. _`Color spaces`: https://en.wikipedia.org/wiki/Color_space
|
||||||
26
content/blog/make-cgit-serve-pdfs-directly/index.rst
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
title: "How to make cgit serve PDF files as direct downloads"
|
||||||
|
date: 2025-11-17T23:42:00+01:00
|
||||||
|
summary: >
|
||||||
|
cgit is great, but by default when you click on a PDF file in a repository content listing it will show you a
|
||||||
|
hexdump of the file. You can access the actual file by clicking the "plain" link on top of the listing, but that's
|
||||||
|
not only annoying, for large PDF files rendering the hexdump can also hang browser tabs.
|
||||||
|
---
|
||||||
|
|
||||||
|
cgit is great, but by default when you click on a PDF file in a repository content listing it will show you a
|
||||||
|
hexdump of the file. You can access the actual file by clicking the "plain" link on top of the listing, but that's
|
||||||
|
not only annoying, for large PDF files rendering the hexdump can also hang browser tabs.
|
||||||
|
|
||||||
|
I found a quick and easy solution to this problem, which I'm documenting here because it seems nobody on the
|
||||||
|
internet has really done this before, and the usual AI assistants (ChatGPT and Claude) are both deeply confused.
|
||||||
|
|
||||||
|
You just add a simple rewrite rule to your nginx config that 302-redirects requests to ``/tree/.../foobar.pdf`` to
|
||||||
|
``/plain/.../foobar.pdf``. Here's the rule, make sure you put them in your nginx config *before* the location directive
|
||||||
|
proxying requests to cgit.
|
||||||
|
|
||||||
|
.. code:: nginx
|
||||||
|
|
||||||
|
location ~ ^/([^/]+)/tree/(.*\.pdf)$ {
|
||||||
|
return 302 /$1/plain/$2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 856 KiB After Width: | Height: | Size: 856 KiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 279 KiB After Width: | Height: | Size: 279 KiB |
|
Before Width: | Height: | Size: 285 KiB After Width: | Height: | Size: 285 KiB |
|
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.9 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 354 KiB After Width: | Height: | Size: 354 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 820 KiB After Width: | Height: | Size: 820 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
|
@ -1,6 +1,10 @@
|
||||||
---
|
---
|
||||||
title: "32-Channel LED tape driver"
|
title: "32-Channel LED tape driver"
|
||||||
date: 2018-05-02T11:31:14+02:00
|
date: 2018-05-02T11:31:14+02:00
|
||||||
|
summary: >
|
||||||
|
Together, a friend and I outfitted the small staircase at Berlin's Chaos Computer Club with nice, shiny RGB-WW LED
|
||||||
|
tape for ambient lighting. For this installation, I made a 32-channel LED driver that achieves high dynamic range on
|
||||||
|
all 32 channels using a cheap microcontroller by using Binary Code Modulation.
|
||||||
---
|
---
|
||||||
|
|
||||||
Theoretical basics
|
Theoretical basics
|
||||||
|
|
@ -40,7 +44,7 @@ good timing.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/pwm_schema.jpg" alt="A visualization of PWM at different duty cycles.">
|
<img src="images/pwm_schema.jpg" alt="A visualization of PWM at different duty cycles.">
|
||||||
<figcaption>Waveforms of two PWM cycles at different duty cycles.</figcaption>
|
<figcaption>Waveforms of two PWM cycles at different duty cycles.</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
@ -96,7 +100,7 @@ on.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/bcm_schema.jpg" alt="A visualization of BCM at different duty cycles.">
|
<img src="images/bcm_schema.jpg" alt="A visualization of BCM at different duty cycles.">
|
||||||
<figcaption>Waveforms of a single 4-bit BCM cycle at different duty cycles. This BCM can produce 16 different
|
<figcaption>Waveforms of a single 4-bit BCM cycle at different duty cycles. This BCM can produce 16 different
|
||||||
levels.</figcaption>
|
levels.</figcaption>
|
||||||
|
|
@ -144,7 +148,7 @@ period, one pulse will reset the shift register and one will strobe the freshly-
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/olsndot_output_schematic.jpg" alt="From left to right, we see the STM32, one of the shift
|
<img src="images/olsndot_output_schematic.jpg" alt="From left to right, we see the STM32, one of the shift
|
||||||
registers, and the LEDs and MOSFETs. The LED tape is driven to ground by the MOSFETs, which are in turn directly
|
registers, and the LEDs and MOSFETs. The LED tape is driven to ground by the MOSFETs, which are in turn directly
|
||||||
driven from the shift register outputs. The shift register is wired up to the STM32 with its clock and data
|
driven from the shift register outputs. The shift register is wired up to the STM32 with its clock and data
|
||||||
|
|
@ -199,7 +203,7 @@ voltrage we saw on our oscilloscope on the LED tape.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/driver_ringing_strong.jpg" alt="Strong ringing on the LED voltage waveform edge at about
|
<img src="images/driver_ringing_strong.jpg" alt="Strong ringing on the LED voltage waveform edge at about
|
||||||
100% overshoot during about 70% of the cycle time.">
|
100% overshoot during about 70% of the cycle time.">
|
||||||
<figcaption>Bad ringing on the LED output voltage caused by wiring inductance. Note that the effect on the
|
<figcaption>Bad ringing on the LED output voltage caused by wiring inductance. Note that the effect on the
|
||||||
|
|
@ -215,7 +219,7 @@ likely culprit. The figure below is the schematic used for the simulations.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/driver_output_ltspice_schematic.jpg" alt="The LTSpice schematic of one output of the driver,
|
<img src="images/driver_output_ltspice_schematic.jpg" alt="The LTSpice schematic of one output of the driver,
|
||||||
taking into account the shift register's output ESR and the wiring ESL.">
|
taking into account the shift register's output ESR and the wiring ESL.">
|
||||||
<figcaption>The schematic of the simulation in LTSpice</figcaption>
|
<figcaption>The schematic of the simulation in LTSpice</figcaption>
|
||||||
|
|
@ -228,7 +232,7 @@ driver.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/overshoot_sim_r0.svg" alt="The result of the LTSpice simulation of our driver output. The LED
|
<img src="images/overshoot_sim_r0.svg" alt="The result of the LTSpice simulation of our driver output. The LED
|
||||||
current shows similar ringing to what we measured using the oscilloscope. Interestingly, the gate voltage shows
|
current shows similar ringing to what we measured using the oscilloscope. Interestingly, the gate voltage shows
|
||||||
strong ringing, too.">
|
strong ringing, too.">
|
||||||
|
|
@ -246,7 +250,7 @@ since the estimated ESL and stray capacitance of the wiring is probably way off.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/driver_ringing_weak.jpg" alt="Weak ringing on the LED voltage waveform edge at about 30%
|
<img src="images/driver_ringing_weak.jpg" alt="Weak ringing on the LED voltage waveform edge at about 30%
|
||||||
overshoot during about 20% of the cycle time.">
|
overshoot during about 20% of the cycle time.">
|
||||||
<figcaption>Adding a resistor in front of the MOSFET gate to slow the transition damped the ringing somewhat,
|
<figcaption>Adding a resistor in front of the MOSFET gate to slow the transition damped the ringing somewhat,
|
||||||
|
|
@ -257,7 +261,7 @@ since the estimated ESL and stray capacitance of the wiring is probably way off.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/overshoot_sim_r100.svg" alt="The result of the LTSpice simulation of our driver output with an
|
<img src="images/overshoot_sim_r100.svg" alt="The result of the LTSpice simulation of our driver output with an
|
||||||
extra 100 Ohms between shift register output and MOSFET gate. Similar to the oscilloscope measurement the
|
extra 100 Ohms between shift register output and MOSFET gate. Similar to the oscilloscope measurement the
|
||||||
ringing is much reduced in its amplitude.">
|
ringing is much reduced in its amplitude.">
|
||||||
|
|
@ -273,7 +277,7 @@ cycle of the LED current is not at all equal to the 50% duty cycle of the excita
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/asymmetric_iled.svg" alt="The result of an LTSpice simulation of the LED duty cycle without and
|
<img src="images/asymmetric_iled.svg" alt="The result of an LTSpice simulation of the LED duty cycle without and
|
||||||
with damping. Dampening widens the LED current waveform from 50% duty cycle with sharp edges to about 80% duty
|
with damping. Dampening widens the LED current waveform from 50% duty cycle with sharp edges to about 80% duty
|
||||||
cycle with soft edges.">
|
cycle with soft edges.">
|
||||||
|
|
@ -283,7 +287,7 @@ cycle of the LED current is not at all equal to the 50% duty cycle of the excita
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/asymmetric_vgate.svg" alt="The gate voltages in the spice simulation above. The undamped
|
<img src="images/asymmetric_vgate.svg" alt="The gate voltages in the spice simulation above. The undamped
|
||||||
response shows sharp edges with the miller plateau being a barely noticeable step, but with strong ringing on
|
response shows sharp edges with the miller plateau being a barely noticeable step, but with strong ringing on
|
||||||
the trailing edge. The damped response shows RC-like slow-edges, but has wide miller plateaus on both edges
|
the trailing edge. The damped response shows RC-like slow-edges, but has wide miller plateaus on both edges
|
||||||
|
|
@ -327,7 +331,7 @@ sensitive owing to their physically large die area.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/linearization_setup.jpg" alt="The led measurement setup consists of several PCBs and a
|
<img src="images/linearization_setup.jpg" alt="The led measurement setup consists of several PCBs and a
|
||||||
breadboard linked with a bunch of wires and a big tin can to shield the LEDs and the photodiode. A large sub-D
|
breadboard linked with a bunch of wires and a big tin can to shield the LEDs and the photodiode. A large sub-D
|
||||||
connector is put into the top of the tin can as a feed-through for the LED tape's control signals and the
|
connector is put into the top of the tin can as a feed-through for the LED tape's control signals and the
|
||||||
|
|
@ -356,7 +360,7 @@ photocurrents for a certain BCM setpoint just as our retinas would do.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<figure data-pagefind-ignore>
|
||||||
<img src="images/driver_linearity_raw.svg" alt="">
|
<img src="images/driver_linearity_raw.svg" alt="">
|
||||||
<figcaption>
|
<figcaption>
|
||||||
A plot of the measured brightness of our LED tape for each BCM period. The brightness values are normalized
|
A plot of the measured brightness of our LED tape for each BCM period. The brightness values are normalized
|
||||||
|
|
@ -376,15 +380,16 @@ the resulting brightness curve below.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<div class="subfigure" data-pagefind-ignore>
|
||||||
<figure class="side-by-side">
|
<figure>
|
||||||
<img src="images/uncorrected_brightness_sim.svg" alt="">
|
<img src="images/uncorrected_brightness_sim.svg" alt="">
|
||||||
<figcaption>
|
<figcaption>
|
||||||
Calculated brightness curve for the uncorrected BCM setup. As you can see, at low setpoints the result
|
Calculated brightness curve for the uncorrected BCM setup. As you can see, at low setpoints the result
|
||||||
is about as smooth as sandpaper, which is well in line with our observations. At high setpoints the
|
is about as smooth as sandpaper, which is well in line with our observations. At high setpoints the
|
||||||
offset gets swamped out and the nonlinearity in the low bits is not visible anymore.
|
offset gets swamped out and the nonlinearity in the low bits is not visible anymore.
|
||||||
</figcaption>
|
</figcaption>
|
||||||
</figure><figure class="side-by-side">
|
</figure>
|
||||||
|
<figure>
|
||||||
<img src="images/corrected_brightness_sim.svg" alt="">
|
<img src="images/corrected_brightness_sim.svg" alt="">
|
||||||
<figcaption>
|
<figcaption>
|
||||||
Brightness curve for the corrected BCM setup extrapolated using actual measurements. Looks as buttery
|
Brightness curve for the corrected BCM setup extrapolated using actual measurements. Looks as buttery
|
||||||
|
|
@ -392,7 +397,7 @@ the resulting brightness curve below.
|
||||||
</figcaption>
|
</figcaption>
|
||||||
</figcaption>
|
</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
</figure>
|
</div>
|
||||||
|
|
||||||
.. _BPW34: http://www.vishay.com/docs/81521/bpw34.pdf
|
.. _BPW34: http://www.vishay.com/docs/81521/bpw34.pdf
|
||||||
.. _MCP6002: http://ww1.microchip.com/downloads/en/DeviceDoc/21733j.pdf
|
.. _MCP6002: http://ww1.microchip.com/downloads/en/DeviceDoc/21733j.pdf
|
||||||
|
|
@ -431,19 +436,20 @@ Conclusion
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<figure>
|
<div class="subfigure" data-pagefind-ignore>
|
||||||
<figure class="side-by-side">
|
<figure>
|
||||||
<a href="images/olsndot_schematic.png">
|
<a href="images/olsndot_schematic.png">
|
||||||
<img src="images/olsndot_schematic.png" alt="A picture of the LED driver schematic">
|
<img src="images/olsndot_schematic.png" alt="A picture of the LED driver schematic">
|
||||||
</a>
|
</a>
|
||||||
<figcaption>The LED driver <a href="images/olsndot_schematic.png">schematic</a></figcaption>
|
<figcaption>The LED driver <a href="images/olsndot_schematic.png">schematic</a></figcaption>
|
||||||
</figure><figure class="side-by-side">
|
</figure>
|
||||||
|
<figure>
|
||||||
<a href="images/olsndot_pcb.png">
|
<a href="images/olsndot_pcb.png">
|
||||||
<img src="images/olsndot_pcb.png" alt="A picture of the LED driver PCB layout">
|
<img src="images/olsndot_pcb.png" alt="A picture of the LED driver PCB layout">
|
||||||
</a>
|
</a>
|
||||||
<figcaption>The LED driver <a href="images/olsndot_pcb.png">PCB layout</a></figcaption>
|
<figcaption>The LED driver <a href="images/olsndot_pcb.png">PCB layout</a></figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
</figure>
|
</div>
|
||||||
|
|
||||||
Putting some thought into the control circuitry and software, you can easily control large numbers of channels of LEDs
|
Putting some thought into the control circuitry and software, you can easily control large numbers of channels of LEDs
|
||||||
using extremely inexpensive driving hardware without any compromises on dynamic range. The design we settled on can
|
using extremely inexpensive driving hardware without any compromises on dynamic range. The design we settled on can
|
||||||
18
content/blog/note-git-server-move.rst
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
title: "Housekeeping note: git.jaseg.de has moved"
|
||||||
|
date: 2026-05-30T10:00:00+02:00
|
||||||
|
summary: >
|
||||||
|
A small note: As part of moving the servers and website to a new, more suitable host for my Ashen and Yanartas
|
||||||
|
projects as well as the creation of yasec, my freelance consulting business, I've moved git.jaseg.de from a custom
|
||||||
|
cgit/gitolite setup to a forgejo instance. This may have broken some links, especially deep links into the old cgit.
|
||||||
|
If you notice any broken links, please reach out through email.
|
||||||
|
---
|
||||||
|
|
||||||
|
A small note: As part of moving the servers and website to a new, more suitable host for my Ashen_ and Yanartas_
|
||||||
|
projects as well as the creation of yasec_, my freelance consulting business, I've moved `git.jaseg.de
|
||||||
|
<https://git.jaseg.de/>`__ from a custom cgit/gitolite setup to a forgejo instance. This may have broken some links,
|
||||||
|
especially deep links into the old cgit. If you notice any broken links, please reach out through email.
|
||||||
|
|
||||||
|
.. _Ashen: https://yasec.de/projects/ashen/
|
||||||
|
.. _Yanartas: https://yasec.de/projects/yanartas/
|
||||||
|
.. _yasec: https://yasec.de/
|
||||||
BIN
content/blog/paper-sampling-mesh-monitor/fig_edge_risetime.pdf
Normal file
BIN
content/blog/paper-sampling-mesh-monitor/fig_edge_risetime.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
104
content/blog/paper-sampling-mesh-monitor/index.rst
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
---
|
||||||
|
title: "New paper: Monitoring Tamper-Sensing Meshes Using Low-Cost, Embedded Time-Domain Reflectometry"
|
||||||
|
date: 2025-10-20T23:42:00+01:00
|
||||||
|
summary: >
|
||||||
|
I've got a new paper accepted at CHES, to be published in TCHES 2026/1 around beginning of December and out `on
|
||||||
|
eprint now <https://eprint.iacr.org/2025/1962>`__. The topic of the paper is a way of monitoring a tamper-sensing
|
||||||
|
mesh through time-domain reflectometry using very cheap components. The end result is a circuit that costs about
|
||||||
|
10 € in parts that is able to measure TDR responses with a few hundred picoseconds of resolution.
|
||||||
|
---
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<figure data-pagefind-ignore>
|
||||||
|
<img src="pic_board_setup_2_small.jpg" alt="A PCB with several chips sitting on a table with another PCB
|
||||||
|
with only traces on it plugged in through a board-edge connector. The first PCB looks not very complex.">
|
||||||
|
<figcaption>
|
||||||
|
The final setup. On the right is the measurement board, and on the left is the mesh test specimen plugged
|
||||||
|
in. In a real application, you would integrate both into your target circuit.
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
I've got a new paper accepted at CHES, to be published in TCHES 2026/1 around beginning of December and out
|
||||||
|
`on eprint now <https://eprint.iacr.org/2025/1962>`__. The topic of the paper is a way of monitoring a tamper-sensing
|
||||||
|
mesh through time-domain reflectometry using very cheap components. The end result is a circuit that costs about 10 € in
|
||||||
|
parts that is able to measure TDR responses with a few hundred picoseconds of resolution.
|
||||||
|
|
||||||
|
Tamper-Sensing meshes are squiggly circuit traces that are used to tamper-proof high-security devices like hardware
|
||||||
|
security modules, ATM pin pads and countertop card payment terminals. Any area where you would like to prevent an
|
||||||
|
attacker from drilling or sawing through in a physical attack, you completely cover with one or more such circuit traces
|
||||||
|
in a meandering pattern. I've written up some work on a KiCad plugin for creating these meshes `in another post
|
||||||
|
<{{< ref "blog/kicad-mesh-plugin" >}}>`__.
|
||||||
|
|
||||||
|
Up to now, the state of the art in monitoring these security meshes has mostly been finding ways to precisely monitor
|
||||||
|
their ohmic resistance in the analog domain. This has the disadvantage of both being fairly complex in circuitry and of
|
||||||
|
presenting a steep trade-off between sensitivity and false-positive rate since all you get out of the whole mesh is a
|
||||||
|
single analog measurement containing maybe 12 to 16 bits of entropy. There have been a few papers on using more advanced
|
||||||
|
RF techniques, but they all either required really expensive circuitry and/or highly customized meshes that for instance
|
||||||
|
couldn't easily be fitted into arbitrary shapes.
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<figure data-pagefind-ignore>
|
||||||
|
<img src="fig_edge_risetime.png" alt="Four plots showing edge response for four different chips: 74LVC2G157,
|
||||||
|
MAX3748, TDP0604 and PI3HDX12211. The first two are fairly slow at about 1 ns risetime, while the last two are
|
||||||
|
very fast at around 300 ps risetime.">
|
||||||
|
<figcaption>
|
||||||
|
The sampling edges as measured by the board itself. As you can see, using a cheap microcontroller and some
|
||||||
|
cheap display signal redriver ICs along with commodity RF schottkies you can get pretty spicy edges on a
|
||||||
|
budget. <a href="fig_edge_risetime.pdf">Link to full resolution.</a>
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
In this paper, I wrote up a method using the high-resolution timer of an inexpensive `STM32G4-series microcontroller
|
||||||
|
<https://www.st.com/resource/en/datasheet/stm32g474cb.pdf>`__ together with a DisplayPort/HDMI "redriver" chips meant for
|
||||||
|
amplifying high-speed display signals to create fast pulse edges. I characterized several chips, with the best
|
||||||
|
performers being TI's `TDP0604 <https://www.ti.com/product/TDP0604>`__ and Diodes' `PI3HDX12211
|
||||||
|
<https://www.diodes.com/part/view/PI3HDX12211>`__, coming in at 2 to 5 € depending on where and how much you buy. The
|
||||||
|
fast edges generated by these drivers are then fed to a set of four-diode sampling gates using cheap RF schottky diodes
|
||||||
|
to create a really cheap but fast time-domain reflectometer. Using this TDRD circuit, a security mesh can be monitored
|
||||||
|
much more precisely than before, since the circuit creates a sort of fingerprint of the mesh's trace along its length.
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<div class="subfigure" data-pagefind-ignore>
|
||||||
|
<figure>
|
||||||
|
<img src="pic_74lvc_small.jpg" alt="">
|
||||||
|
<figcaption>
|
||||||
|
74LVC2G157
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
<figure>
|
||||||
|
<img src="pic_max3748_small.jpg" alt="">
|
||||||
|
<figcaption>
|
||||||
|
MAX3748
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
<figure>
|
||||||
|
<img src="pic_tdp0604_small.jpg" alt="">
|
||||||
|
<figcaption>
|
||||||
|
TDP0604
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
<figure>
|
||||||
|
<img src="pic_pi3hdx_small.jpg" alt="">
|
||||||
|
<figcaption>
|
||||||
|
PI3HDX12211
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
One of the fun highlights of this project to me was micro-soldering test boards using different redriver ICs. Above, you
|
||||||
|
can see the result of that soldering work. I was really happy with my cheap aliexpress microscope and with my fancy
|
||||||
|
titanium tweezers!
|
||||||
|
|
||||||
|
Have a look into the paper, where I wrote up details on the circuitry as well as a whole bunch of (>1000!) measurements
|
||||||
|
characterizing the system. As it turns out, it's really sensitive to attacks while being reasonably robust to
|
||||||
|
environmental disturbances. In fact, it's so sensitive that the circuit can distinguish multiple identical (!) copies of
|
||||||
|
the same mesh produces by JLCPCB from their manufacturing tolerances such as FR-4 fiber weave alignment.
|
||||||
|
|
||||||
|
You can find a preprint of the paper `on eprint <https://eprint.iacr.org/2025/1962>`__, and I'll update this post with a
|
||||||
|
link to the published version of the paper when it becomes available. The eprint is identical to the published version
|
||||||
|
as of now.
|
||||||
|
|
||||||
|
The source code of the project is available at `https://git.jaseg.de/sampling-mesh-monitor.git <https://git.jaseg.de/sampling-mesh-monitor.git>`__.
|
||||||