Thomas Habets
blog.habets.se · Personal blog · on HN since 2013
Thomas Habets writes about systems programming, Go, C, Rust, Linux networking, and security tooling like SSH and GPG with Yubikeys.
What HN saysCommenters cite his posts on Go's rough edges and undefined behavior in C, and his static linking article, in technical debates.
31HN people shared it
17linked it in comments
17stories submitted
1.3Kstory points
3 months agolast shared
2013people per year2026
Most-shared posts
- 1Go is still not good4 people · 646 points · first shared 2025 · 837 comments on HN
- 2Everything in C is undefined behavior3 people · 58 points · first shared 2026 · 25 comments on HN
- 3GPG and SSH with Yubikey NEO3 people · first shared 2013
- 4Io_uring, kTLS and Rust for zero syscall HTTPS server2 people · 496 points · first shared 2025 · 166 comments on HN
- 5Rob Pike is wrong on bloat2 people · 5 points · first shared 2025 · 1 comments on HN
- 6BPF: The Future of Configs (2020)2 people · 4 points · first shared 2020 · discussion on HN
- 7SSH over Bluetooth – Cleanly2 people · 3 points · first shared 2022 · discussion on HN
- 8You cannot sell AI written software2 people · 2 points · first shared 2026 · 3 comments on HN
- 9Seccomp – Unsafe at any speed (2022)2 people · 1 points · first shared 2022 · discussion on HN
- 10Gettimeofday() should never be used to measure time (2010)2 people · 1 points · first shared 2020 · discussion on HN
- 11TCP MD52 people · first shared 2020
- 12OpenSSH certificates2 people · first shared 2017
- 13The uselessness of bash2 people · first shared 2021
- 14GPG and SSH with Yubikey NEO2 people · first shared 2018
- 15Windows SSH client with TPM2 people · first shared 2021
What HN people wrote when they linked it
thomashabets2 · 2026-07-10
I'd say yes we are ready. gettimeofday() should never be used to measure time[1], but at least with a negative leap second it's monotonic.
We'll just get some poorly coded stuff claim that an operation took 1100ms instead of 100ms. Not great, but not -900ms.
Well, I say that, but per my link here F5 load balancers at least used to keep track of TCP connections using gettimeofday. And it's annoying that libpcap delivers metadata in wallclock time.
[1] https://blog.habets.se/2010/09/gettimeofday-should-never-be-used-to-me…
FooBarWidget · 2026-08-11
Just look at this: https://blog.habets.se/2026/05/Everything-in-C-is-undefined-behavior.h…
This is undefined behavior!
const int* magic_intp = (const int*)bytes;
Heck even something trivial like this is UB:
bool bar(char ch) { return isxdigit(ch); }
The only safe thing to do is memcpy, but that's super useless. As soon as you try to interpret or manipulate the byte-level data in any way, there are UB traps everywhere you go.
anthk · 2026-01-03
Except for static linking and DNS queries.
https://blog.habets.se/2023/04/Linking-statically.html
ViewTrick1002 · 2025-09-24
The question is, what is simplicity?
Go tries to hide the issues, until a data loss happens because it has had trouble dealing with non-UTF8 filenames and Strings are by convention UTF8 but not truly and some functions expect UTF8 while others can work with any collection of bytes.
https://blog.habets.se/2025/07/Go-is-still-not-good.html
Or the Go time library which is a monster of special cases after they realized they needed monotonic clocks [1] but had to squeeze it into the existing API.
https://pkg.go.dev/time
Rust is on the other end of the spectrum. Explicit over implicit, but you can implicitly assume stuff works by panicking on these unexpected errors. Making the problem easy to fix if you stumble upon it after years of added cruft and changing requirements.
[1]: https://github.com/golang/go/issues/12914
digianarchist · 2025-09-22
I'm surprised this wasn't in the recent post submitted here: https://blog.habets.se/2025/07/Go-is-still-not-good.html
It's a one of a few rough edges in Go.
redninja83 · 2022-08-27
Its possible to do, and once set up its a reasonably smooth process.
- Init Your TPM
- Create a key+cert on your TPM using certutil.exe
- Grab your public key
- Use WinCryptSSH (https://github.com/buptczq/WinCryptSSHAgent) as your SSH agent and away you go
These are very simplified steps, but there are howtos floating around (eg https://blog.habets.se/2016/10/Windows-SSH-client-with-TPM.html)
michaelt · 2020-11-24
Will this be virtualisable so multiple VMs sharing a host will see separate, independent devices?
On desktops and laptops, will this device have a hardwired user-presence sensor, like Yubikeys do?
Would this device be performance-oriented enough to, for example, terminate SSL? I gather TPMs can, but only unhelpfully slowly [1]
Would it be performance-oriented enough to perform disk encryption? What about memory encryption?
[1] https://blog.habets.se/2012/02/Benchmarking-TPM-backend-SSL.html
berdario · 2020-07-30
Also, since it might be unfamiliar to many, here's another article that puts forward a criticism of Bitcoin, many of which are for ethical issues:
https://blog.habets.se/2017/11/Why-bitcoin-is-terrible.html
It's about bitcoin, and not everything applies to other cryptocurrencies, but most of these arguments do apply.
castratikron · 2020-02-07
Why disable the TPM? One cool thing you can do is store your SSH private key inside:
https://blog.habets.se/2013/11/TPM-chip-protecting-SSH-keys-properly.h…
floatboth · 2018-05-08
No need to touch SSH itself, PAM is a thing (unless you're on OpenBSD). Here's an example of pam-u2f with OpenSSH:
https://aprilmacdonald.com/two-factor-ssh-authentication-with-u2f-hard…
I actually use a Yubikey for SSH in a different way: with gpg-agent. E.g. https://blog.habets.se/2013/02/GPG-and-SSH-with-Yubikey-NEO.html
lwf · 2017-01-22
This has actually been a feature in OpenSSH since 5.4, see https://blog.habets.se/2011/07/OpenSSH-certificates.html or the CERTIFICATES section of `ssh-keygen(1)`.
Freaky · 2016-01-14
You can use a Yubikey NEO to handle key authentication on your computer's behalf:
https://blog.habets.se/2013/02/GPG-and-SSH-with-Yubikey-NEO
jamoes · 2015-01-07
Does using the Yubikey in this manner protect your keys even if your machine has malware on it? I read through this tutorial [1], and they say you need read/write access to the device, so it seems to me like malware could access your keys while the smartcard is plugged in. If this is the case, I'm not sure how this setup is any more secure than simply keeping your keys on a USB flash drive and plugging it in whenever you need to use ssh.
[1] https://blog.habets.se/2013/02/GPG-and-SSH-with-Yubikey-NEO
thomashabets · 2013-12-05
Yes, you either generate the key on the TPM chip (for SSH authentication, that would be one per user), or you generate it in software and "import" it.
I've clarified how it works here:
http://blog.habets.se/2013/12/How-TPM-protected-SSH-keys-work
zokier · 2013-09-14
https://blog.habets.se/2011/07/OpenSSH-certificates hopefully explains how to set up CA for SSH
pizza234 · 2022-10-18
> I disagree. Bash basically cannot be used correctly. It's like gets() in C; a knife with a blade but no handle. Unsafe at any speed.
> C++ can be used correctly. It's easier since C++11, with smart pointers and stuff. I'm not going to argue that writing solid C++ is easy, but it IS possible.
It seems this conflates two different aspects of programming languages - complexity and (memory) safety.
The analogy with Bash was in relation to the language complexity. By reducing the language features to a restricted, well-known (by the given team) scope, it's possible to use the language effectively. A very good example of this is the Doom 3 source code.
In relation to memory safety, Google hasn't been able to develop a safe enough Bluetooth stack, which has been a dumpster fire. Due to the small support windows of Android, as of today, a huge amount of devices with older Android versions are either in the garbage, or are extremely unsafe. If Google, with their engineering practices, can't develop a safe Bluetooth stack in an unsafe language, realistically, nobody can.
> https://blog.habets.se/2021/06/The-uselessness-of-bash.html
The topic in the post is very interesting (pipes error handling are no doubt a rough area of Bash), but the post takes the choice of being a rant rather than an informative research. The central thesis that "functionality of language X is broken in a 1-line program, but it works in a 83-lines program in language Y" doesn't have any meaningful…
mattbee · 2021-10-05
13 years ago I wrote a nice reference implementation for BGP "client" use - I just treated it as an API onto Cisco routers: https://github.com/BytemarkHosting/bgpfeeder is 1300 lines of Ruby, one file, no dependencies, and quite verbose.
At the time I was running a hosting company & wanted to feed updates to our IP lists from a web-based database into our routers (e.g. a customer wants a new IP to their servers, or moves their VPS images between physical hosts). But I couldn't understand how to get tight control of quagga, or the Ciscos and wondered how how to speak it directly?
It took about a week poring over the RFCs and the Net::BGP Perl module, but I can go back to it now for some useful revision. It brought a lot of disparate BGP knowledge together in one place, and re-expressed it in a language I still know. So if you know Ruby and are curious about BGP it might help you see what you can do with it.
Though if you want to use BGP to control your network devices today, you'd use https://github.com/Exa-Networks/exabgp instead. It can pull every trick you could possibly want with BGP - e.g. DDoS mitigation, anycast, and generally letting you mess with BGP via JSON. There are lots of extensions to BGP, and I only cared about the ones to send v4 & v6 routes around. Also I only wanted to write one file :)
PS, there is one horror in BGP implementation and that is TCP-MD5. i.e. to authenticate to a peer, you sign every packet of your TCP connection with a little…