<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en_CA"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://mcpherrin.ca/feed.xml" rel="self" type="application/atom+xml" /><link href="https://mcpherrin.ca/" rel="alternate" type="text/html" hreflang="en_CA" /><updated>2026-09-08T03:51:32+00:00</updated><id>https://mcpherrin.ca/feed.xml</id><title type="html">Matthew McPherrin</title><subtitle>Matthew McPherrin&apos;s Website</subtitle><author><name>Matthew McPherrin</name></author><entry><title type="html">I’ve factored the RSA keys of a Certificate Authority…</title><link href="https://mcpherrin.ca/2026/09/07/rsa.html" rel="alternate" type="text/html" title="I’ve factored the RSA keys of a Certificate Authority…" /><published>2026-09-07T00:00:00+00:00</published><updated>2026-09-07T00:00:00+00:00</updated><id>https://mcpherrin.ca/2026/09/07/rsa</id><content type="html" xml:base="https://mcpherrin.ca/2026/09/07/rsa.html"><![CDATA[<p><em>… from the 90s.</em></p>

<p>I’ve been thinking about the security of RSA lately. RSA’s cryptography relies
on the difficulty of factoring a large semiprime number, but what “large” means
is an interesting question. The Web PKI deprecated 1024-bit RSA over a decade
ago, and while I don’t know of anyone factoring a key of that size, it’s within
the realm of possibility for a government or other organization with a large
number of computers. Just a few days ago, someone factored the 862-bit
<a href="https://en.wikipedia.org/wiki/RSA_numbers#RSA-260">RSA-260</a> key from the RSA
factoring challenge. That’s the largest factorization I’m aware of. Today, the
world uses RSA of at least 2048 bits, but even that will be deprecated soon
with the risk of quantum computers in the future.</p>

<p>This led me to wonder: small RSA keys can be factored on even a modest desktop
computer. And in the early days of the Web PKI, there were no standards, and no
minimum requirements. Netscape shipped SSL support in 1994, and IE shortly
afterwards. This was still the era of export restrictions on cryptography. Are
there any keys small enough that I can factor? I don’t have any good reason to
do that, but it seems like fun.</p>

<p>The spoiler is of course, yes, but first we need to find a key to crack.</p>

<p>Fortunately, root certificates were shipped with browser installers, and
there are archives of both
<a href="https://archive.org/details/internet-explorer_202104">Internet Explorer</a> and
<a href="https://archive.org/details/netscape-browser-collection">Netscape</a> on
archive.org. The archives aren’t comprehensive, but they should provide good
coverage of old root CAs. I downloaded both collections and set Claude Code on
extracting all the roots. I’ve hosted a Claude-generated webpage with <a href="https://mcpherrinm.github.io/ancientroots/">all
those old-timey, ancient roots</a>.
While I haven’t verified this LLM output is entirely trustworthy, it looks
pretty plausible.</p>

<p>Using the filters on that site, we can find what small keys are trusted for SSL.</p>

<p><img src="/assets/rsa/filtered.png" alt="A table of old roots, filtered to 512-bit RSA roots trusted for SSL, showing the E-Certify RSA 512 Gold root shipped in Netscape 4.51" /></p>

<p>Aha! We have a target. Back in March 1999, Netscape 4.51 shipped a 512-bit RSA
certificate authority trusted for SSL, and another for S/MIME. These two roots
were both from the long-defunct Canadian certificate authority called
<a href="https://web.archive.org/web/20000229163244/http://www.e-certify.com/">E-Certify</a>.</p>

<p>Later that year, the 512-bit
<a href="https://en.wikipedia.org/wiki/RSA_numbers#RSA-155">RSA-155</a> was factored, so
even in its era this was too weak and probably shouldn’t have shipped in the
first place.</p>

<p>The E-Certify 512-bit roots were removed by Netscape in 2002. Unfortunately,
Internet Explorer seems to have never shipped any 512-bit roots for SSL, so our
fun will be limited to Netscape from a relatively small time frame.</p>

<p>Factoring the public keys in the root certificates will give me the two primes
that I need to reconstruct the private key. I ran
<a href="https://cado-nfs.gitlabpages.inria.fr/">CADO-NFS</a> on my Ryzen 9 5950X desktop;
it took 32 hours to factor <code class="language-plaintext highlighter-rouge">E-Certify RSA 512 Gold Server</code> for SSL, and another
29 hours for <code class="language-plaintext highlighter-rouge">E-Certify RSA 512 Gold Client</code> for S/MIME. You can get the
resulting private keys below.</p>

<p>Assuming you’re somehow running Netscape 4.51 with a clock set before E-Certify
roots expired on 2003-10-16, you can use these private keys to issue
certificates. This describes zero people on the planet… except for this VM I
set up.</p>

<p>Verifying that the issued certificates would work in Netscape 4.51 was an
adventure in itself, as there is zero overlap in TLS capability between
Netscape 4.51 and any modern TLS stack. So it was back to Claude Code to make a
custom old-timey TLS server in Go. This site is <a href="https://e-certify.fly.dev/">publicly hosted at
e-certify.fly.dev</a>, which you are welcome to try
out with your own copy of Netscape, but it won’t load in any modern browser.</p>

<p><img src="/assets/rsa/netscape-cert-viewer.png" alt="Netscape 4.51 certificate viewer showing a certificate for e-certify.fly.dev issued by E-Certify RSA 512 Gold Server" /></p>

<p>Or, if you’d like to host your own website using these old-timey keys, the keys
and tools are all in the repo at
<a href="https://github.com/mcpherrinm/ancientroots">https://github.com/mcpherrinm/ancientroots</a>.
Or do worse, like MitM the SSL of all those Netscape 4.51 users with their
clocks set to 25 years ago…</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>C=CA, O=E-Certify, OU=RSA Gold Server, CN=E-Certify RSA 512 Gold Server
-----BEGIN CERTIFICATE-----
MIIByjCCAXSgAwIBAgIBATANBgkqhkiG9w0BAQQFADBjMQswCQYDVQQGEwJDQTES
MBAGA1UEChMJRS1DZXJ0aWZ5MRgwFgYDVQQLEw9SU0EgR29sZCBTZXJ2ZXIxJjAk
BgNVBAMTHUUtQ2VydGlmeSBSU0EgNTEyIEdvbGQgU2VydmVyMB4XDTk4MTAxNjEz
Mzc1M1oXDTAzMTAxNjEzMzc1M1owYzELMAkGA1UEBhMCQ0ExEjAQBgNVBAoTCUUt
Q2VydGlmeTEYMBYGA1UECxMPUlNBIEdvbGQgU2VydmVyMSYwJAYDVQQDEx1FLUNl
cnRpZnkgUlNBIDUxMiBHb2xkIFNlcnZlcjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgC
QQDNVQ93Ev7zgNaJAR1Z7gCydU6mky1e/B4EbY1NsdtfsitU9cELqg5uRJDPA40n
CDPeOyil1lJ5N8hekcqJAkkXAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
KoZIhvcNAQEEBQADQQB09SV6OeeDEP8Je3DOLNZ24U98NHqIBTDyB4sRpDmNdHum
+3rm4AYtznBxG5hEShO89bcWi3yJtBITGuTRDnMq
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBAM1VD3cS/vOA1okBHVnuALJ1TqaTLV78HgRtjU2x21+yK1T1wQuq
Dm5EkM8DjScIM947KKXWUnk3yF6RyokCSRcCAwEAAQJAWZ2FOWf+A9K4T2VAJS69
+SU/pW3YwHrysuYJZN56K0Iz+Hqd1hBhCeJ3/T+/cvXq+ctD0x3uOxU1rDSeCoMO
KQIhAPdbc1wTm3twWDYi1iXmRBXz97MYxRFld/KFr8x5+tK9AiEA1IG09a+oVg6j
NMDj6GD7spaD4q9t1wk/Nyq/MTLPkmMCIEzzYjvuzZvlI0wUIlLAA8Zgk1pgBk6X
Jm2IMVyHRgRxAiEAjZKgCTHuVu7HgiSjcTPzW0X1NTckWSc66zjaSR+Ns/sCICxT
yXoTXWQCWL6BMpf2no7IlvoEnBIrED2Frq3PxlEA
-----END RSA PRIVATE KEY-----
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>C=CA, O=E-Certify, OU=RSA Gold Client, CN=E-Certify RSA 512 Gold Client
-----BEGIN CERTIFICATE-----
MIIByjCCAXSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADBjMQswCQYDVQQGEwJDQTES
MBAGA1UEChMJRS1DZXJ0aWZ5MRgwFgYDVQQLEw9SU0EgR29sZCBDbGllbnQxJjAk
BgNVBAMTHUUtQ2VydGlmeSBSU0EgNTEyIEdvbGQgQ2xpZW50MB4XDTk4MTAxNjEz
MzQwOFoXDTAzMTAxNjEzMzQwOFowYzELMAkGA1UEBhMCQ0ExEjAQBgNVBAoTCUUt
Q2VydGlmeTEYMBYGA1UECxMPUlNBIEdvbGQgQ2xpZW50MSYwJAYDVQQDEx1FLUNl
cnRpZnkgUlNBIDUxMiBHb2xkIENsaWVudDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgC
QQBwCcT1iYlNyKPywB/kffD8esiCzGYJxSnTXQjU6ej/XxnA+9yqjzAMPtqFd094
wM89Vsmz9YOWSO6Qn6wOAs45AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
KoZIhvcNAQEEBQADQQAdktdM5AzW+0o96eHCHwD3UfzxPvjKxPEjiI/QTn+njHt/
BEJb9yZatONRckglVc9v8P8Dy8HZGQD0+Pn0uxhW
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIBOQIBAAJAcAnE9YmJTcij8sAf5H3w/HrIgsxmCcUp010I1Ono/18ZwPvcqo8w
DD7ahXdPeMDPPVbJs/WDlkjukJ+sDgLOOQIDAQABAkASXZeaxFPsm0I8zb+snfR9
/saVolnrqhVEH5EODdXy3nSm6fpdrsDwQDDg52biXjIUizQYdd3OourOn0/PyyiB
AiEAyW4gFFgM0dJ+Y//vrIyQutLeH/5c/Vq3Lbcxv7R908kCIQCOZAAv8OCG/2oH
yKaYj/EoxcFZ9csVh/kjicO/JIX+8QIhAMEzAkvhBDLALYAmvDCJBkxa8rhHFdPf
jbCodGwGZ2WZAiB//XmBnlZkYl/PoVfGmNRgHun+0AZ9UxzqCeJvBQiBMQIgHWlr
0Sh1a8K2pQP2ktgmL3RH5+1Qd2wLx/hhGWtwPvU=
-----END RSA PRIVATE KEY-----
</code></pre></div></div>

<p>As a bonus, Internet Explorer 3.02 shipped a code signing CA called OU=Test
VeriSign Commercial Software Publisher CA. I’m not sure what that’s for, but
it’s just as easily factored. There are a few other test-looking 512-bit RSA keys
in the <a href="https://mcpherrinm.github.io/ancientroots/">ancient roots</a> repo, so you
should try factoring some more of them, or seeing what they could be used for!</p>

<p>Steve Weis factored this one in about an hour using a GPU cluster.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>L=Internet, O=VeriSign, Inc., OU=Test VeriSign Commercial Software Publisher CA
-----BEGIN CERTIFICATE-----
MIIByDCCAXKgAwIBAgIQIsTi2AgEp+1OkpqVLROnazANBgkqhkiG9w0BAQQFADBl
MREwDwYDVQQHEwhJbnRlcm5ldDEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1
BgNVBAsTLlRlc3QgVmVyaVNpZ24gQ29tbWVyY2lhbCBTb2Z0d2FyZSBQdWJsaXNo
ZXIgQ0EwHhcNOTYwNTAyMTcwMTUyWhcNOTcwNTAyMTcwMTUyWjBlMREwDwYDVQQH
EwhJbnRlcm5ldDEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLlRl
c3QgVmVyaVNpZ24gQ29tbWVyY2lhbCBTb2Z0d2FyZSBQdWJsaXNoZXIgQ0EwXDAN
BgkqhkiG9w0BAQEFAANLADBIAkEA1XqTpg1hQWq6IKvBXLor12GBTH6y4BHyOJjy
MJISn0ZWBqkbZiEfoWgaWXhEwrvxMWonLA2vYFHijofFG4YIjwIDAQABMA0GCSqG
SIb3DQEBBAUAA0EAKxuR/KPJPDNJgw0ORqqM7SlvIeqnVP71OEFytqPaZw/3TPEi
9oK6PzBvPdLBZlnjRd/hf58FW2+/PXxsFl78Mg==
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIBOwIBAAJBANV6k6YNYUFquiCrwVy6K9dhgUx+suAR8jiY8jCSEp9GVgapG2Yh
H6FoGll4RMK78TFqJywNr2BR4o6HxRuGCI8CAwEAAQJAYM8tlegLarcToS1CiuKC
bzHwiNgMFkENL01sx0n21/MhmA6pBiSwVn3Pu6yvx6EMB1zbCsaBHs/VTyofMbRW
QQIhAOqdAX3bVZwAlZ5FDWyfGwgE0FXEIQ85kjcihrFeDs49AiEA6PBfC0YuNMSa
M135mH+MEY1GEmQe9xHcXpiYAPazCrsCIQDDtuw6oJEfDYHCwRn8xhGXs+RT18Q4
Xi9yXRP9vFgfhQIhAIYUTfD0XYZcIBIvJosj56D2u328iaJXcow0s1Hirp4fAiAG
bza0Qcc27d/0OzKOqep3JrDl/L5HidTj2XEqEXmnXw==
-----END RSA PRIVATE KEY-----
</code></pre></div></div>

<p>And finally, SSL Labs thinks my test site is great.</p>

<p><img src="/assets/rsa/ssl-labs.png" alt="SSL Labs report giving e-certify.fly.dev an F rating, with many issues" /></p>]]></content><author><name>Matthew McPherrin</name></author><summary type="html"><![CDATA[… from the 90s.]]></summary></entry><entry><title type="html">CT: Managing uptime as a CA</title><link href="https://mcpherrin.ca/2025/10/20/ct-uptime.html" rel="alternate" type="text/html" title="CT: Managing uptime as a CA" /><published>2025-10-20T00:00:00+00:00</published><updated>2025-10-20T00:00:00+00:00</updated><id>https://mcpherrin.ca/2025/10/20/ct-uptime</id><content type="html" xml:base="https://mcpherrin.ca/2025/10/20/ct-uptime.html"><![CDATA[<p>This talk was given at the transparency.dev summit 2025.</p>

<p>As a Certificate Authority, Let’s Encrypt needs to submit pre-certificates to CT logs to get SCTs for embedding in
certificates. This adds an external dependency on our issuance process, which was historically one of the big concerns
CAs have had about CT. In this talk, we’ll discuss how we’ve managed that availability risk through the different
submission algorithms we’ve used, and what the real world impact CT has had on our certificate issuance process. Looking
forward, our new Static CT logs provide different tradeoffs on latency and reliability, which will make the Let’s
Encrypt CA more reliable overall, and how operating CT logs helps us keep our CA running.</p>

<p>A <a href="https://www.youtube.com/watch?v=GrQN7c9EPhA">talk recording is on Youtube</a>.</p>]]></content><author><name>Matthew McPherrin</name></author><summary type="html"><![CDATA[This talk was given at the transparency.dev summit 2025.]]></summary></entry><entry><title type="html">Ten Years as a Free, Open, and Automated Certificate Authority</title><link href="https://mcpherrin.ca/2025/03/25/srecon.html" rel="alternate" type="text/html" title="Ten Years as a Free, Open, and Automated Certificate Authority" /><published>2025-03-25T00:00:00+00:00</published><updated>2025-03-25T00:00:00+00:00</updated><id>https://mcpherrin.ca/2025/03/25/srecon</id><content type="html" xml:base="https://mcpherrin.ca/2025/03/25/srecon.html"><![CDATA[<p>This talk was given at SRECon25 Americas.</p>

<p>Ubiquitous HTTPS is an essential part of a secure and privacy-respecting Internet. To that end, the public benefit
certificate authority Let’s Encrypt has been issuing TLS certificates free of cost in a reliable, automated, and
trustworthy manner for ten years. In that time, we’ve grown to servicing over 500,000,000 websites.</p>

<p>In this talk we’ll dive into the history of Let’s Encrypt and share helpful context for those managing TLS certificates,
as well as information about upcoming changes to Let’s Encrypt and guidance for the future. We’ll also cover how we have
strived to make the working lives of SREs around the world easier, and how the SRE community has helped us in return.</p>

<p>Slides and recording are linked on <a href="https://www.usenix.org/conference/srecon25americas/presentation/mcpherrin">https://www.usenix.org/conference/srecon25americas/presentation/mcpherrin</a></p>]]></content><author><name>Matthew McPherrin</name></author><summary type="html"><![CDATA[This talk was given at SRECon25 Americas.]]></summary></entry><entry><title type="html">Shining a new light on Certificate Transparency</title><link href="https://mcpherrin.ca/2024/10/10/shining-ct.html" rel="alternate" type="text/html" title="Shining a new light on Certificate Transparency" /><published>2024-10-10T00:00:00+00:00</published><updated>2024-10-10T00:00:00+00:00</updated><id>https://mcpherrin.ca/2024/10/10/shining-ct</id><content type="html" xml:base="https://mcpherrin.ca/2024/10/10/shining-ct.html"><![CDATA[<p>This talk was given at the transparency.dev summit 2024.</p>

<p>Let’s Encrypt operates one of the largest Certificate Authorities, along with Certificate Transparency logs. This talk
discusses our experiences both as a submitter to CT as well as a log operator. We are excited about the new Sunlight log
implementation, and will cover why we think Sunlight will be a good fit for us and for the larger CT ecosystem.</p>

<p>Slides and recording are linked on <a href="https://transparency.dev/summit2024/letsencrypt.html">https://transparency.dev/summit2024/letsencrypt.html</a></p>]]></content><author><name>Matthew McPherrin</name></author><summary type="html"><![CDATA[This talk was given at the transparency.dev summit 2024.]]></summary></entry><entry><title type="html">Web PKI Revocation is Broken (but we can fix it!)</title><link href="https://mcpherrin.ca/2023/10/21/bsides-revocation.html" rel="alternate" type="text/html" title="Web PKI Revocation is Broken (but we can fix it!)" /><published>2023-10-21T00:00:00+00:00</published><updated>2023-10-21T00:00:00+00:00</updated><id>https://mcpherrin.ca/2023/10/21/bsides-revocation</id><content type="html" xml:base="https://mcpherrin.ca/2023/10/21/bsides-revocation.html"><![CDATA[<p>The web public key infrastructure is used to secure HTTPS connections between
browsers and websites using certificates. Today, when something goes wrong,
browsers can’t reliably find out those certificates have been revoked. We
examine past and future solutions to this problem, and how we can make progress
on fixing revocation.</p>

<p>This talk covers the history of the protocols used to communicate web PKI
revocation, including CRLs and OCSP, and discusses why they have been ineffective.
Then goes over future improvements that are ongoing now to make certificate
lifetimes shorter, revive CRLs with new distribution and compression
mechanisms. It discusses why new solutions might work where previous attempts
like OCSP stapling failed.</p>

<p>The talk was given at the Cryptography and Privacy Village at DEFCON31, and
then at BSides Toronto 2023.</p>

<p>The BSides recording is available
<a href="https://www.youtube.com/watch?v=4TbtL73ibh0">on youtube</a>
and embedded below.</p>

<iframe width="560" height="315" frameborder="0" src="https://www.youtube-nocookie.com/embed/4TbtL73ibh0?si=cK-jDxTn3zj7Jqsl" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="">
</iframe>]]></content><author><name>Matthew McPherrin</name></author><summary type="html"><![CDATA[The web public key infrastructure is used to secure HTTPS connections between browsers and websites using certificates. Today, when something goes wrong, browsers can’t reliably find out those certificates have been revoked. We examine past and future solutions to this problem, and how we can make progress on fixing revocation.]]></summary></entry><entry><title type="html">The S in HTTPS</title><link href="https://mcpherrin.ca/2023/09/29/s-in-https.html" rel="alternate" type="text/html" title="The S in HTTPS" /><published>2023-09-29T00:00:00+00:00</published><updated>2023-09-29T00:00:00+00:00</updated><id>https://mcpherrin.ca/2023/09/29/s-in-https</id><content type="html" xml:base="https://mcpherrin.ca/2023/09/29/s-in-https.html"><![CDATA[<p>I gave a talk for the <a href="https://infrastructureclub.co.uk/">Infrastructure Club</a>,
introducing how we communicate securely online.</p>

<p>You can find the talk on the 
<a href="https://www.youtube.com/watch?v=ZxOBz7QNneI">Infrastructure Club YouTube Channel</a> and embedded below.</p>

<iframe width="560" height="315" frameborder="0" src="https://www.youtube-nocookie.com/embed/ZxOBz7QNneI?si=svPqaRAJg7P3mOoq" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="">
</iframe>

<p>The <a href="https://docs.google.com/presentation/d/e/2PACX-1vRJhuLxyLnDsLvFZlFkkUajB6_GwXyQctFwxe5Nx9PQO_Xw6WZFBtoJ-MsHVAKF1pSHp4fBOyEKz4cq/pub?start=false&amp;loop=false&amp;delayms=3000">slide deck is linked here</a> and embedded below.</p>

<iframe width="560" height="351" frameborder="0" src="https://docs.google.com/presentation/d/e/2PACX-1vRJhuLxyLnDsLvFZlFkkUajB6_GwXyQctFwxe5Nx9PQO_Xw6WZFBtoJ-MsHVAKF1pSHp4fBOyEKz4cq/embed?start=false&amp;loop=false&amp;delayms=3000" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true">
</iframe>]]></content><author><name>Matthew McPherrin</name></author><summary type="html"><![CDATA[I gave a talk for the Infrastructure Club, introducing how we communicate securely online.]]></summary></entry><entry><title type="html">Operationalizing SPIRE at Square</title><link href="https://mcpherrin.ca/2020/05/04/spiffe-square.html" rel="alternate" type="text/html" title="Operationalizing SPIRE at Square" /><published>2020-05-04T00:00:00+00:00</published><updated>2020-05-04T00:00:00+00:00</updated><id>https://mcpherrin.ca/2020/05/04/spiffe-square</id><content type="html" xml:base="https://mcpherrin.ca/2020/05/04/spiffe-square.html"><![CDATA[<p>At the Spring 2020 SPIFFE community day, I gave a talk about my work to take
our SPIRE deployment from a prototype to production software we relied on.</p>

<p>You can watch the talk
<a href="https://www.youtube.com/watch?v=KP9rME3zw6g&amp;list=PLAtJVtsZ0KWZSRIsOfK4CQeVKNqNKe0_7&amp;index=1">on youtube</a>
and embedded below.</p>

<iframe width="560" height="315" frameborder="0" src="https://www.youtube-nocookie.com/embed/KP9rME3zw6g?si=tVnCu9eEWmkokA3B" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="">
</iframe>

<p>As well, I previously talked at a 2019 community day.</p>

<p>That talk is also <a href="https://www.youtube.com/watch?v=H5IlmYmEDKk&amp;t=2585s">on youtube</a></p>]]></content><author><name>Matthew McPherrin</name></author><summary type="html"><![CDATA[At the Spring 2020 SPIFFE community day, I gave a talk about my work to take our SPIRE deployment from a prototype to production software we relied on.]]></summary></entry><entry><title type="html">Colliding the sum checksum</title><link href="https://mcpherrin.ca/2019/11/23/sum-collisions.html" rel="alternate" type="text/html" title="Colliding the sum checksum" /><published>2019-11-23T00:00:00+00:00</published><updated>2019-11-23T00:00:00+00:00</updated><id>https://mcpherrin.ca/2019/11/23/sum-collisions</id><content type="html" xml:base="https://mcpherrin.ca/2019/11/23/sum-collisions.html"><![CDATA[<p>The <code class="language-plaintext highlighter-rouge">sum</code> command-line tool is a simple checksum utility included in BSD and
GNU Coreutils.  It is not a cryptographically secure hash, and so I wrote a
tool to set the <code class="language-plaintext highlighter-rouge">sum</code> of a file to an arbitrary value.</p>

<p>You can find that tool and associated code from this post on my github account
<a href="https://github.com/mcpherrinm/sumcoll/">in the sumcoll repository</a></p>

<h2 id="usage">Usage</h2>

<p>Sum takes file(s) on the command line and prints a checksum value in decimal,
along with a count of 1024-byte blocks.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">echo </span>abcdef <span class="o">&gt;</span> file
<span class="nv">$ </span><span class="nb">sum </span>file
33901     1
</code></pre></div></div>

<h2 id="backstory">Backstory</h2>
<p>Some years ago I was asked to include the BSD sums of a homework assignment, to
verify I had not modified the code after the assignment deadline.  The sums of
the files were included with a written portion submitted on paper in class, and
the code was graded later.</p>

<h2 id="security">Security</h2>
<p>Using a non-cryptographically secure hash for this task is totally insecure, as
a malicious student could find another file which has the same checksum as what
was submitted on the paper handout.  The property needed to prevent that is
called <strong>Second Preimage Resistance</strong>.  The malicious student gets to pick <code class="language-plaintext highlighter-rouge">m1</code>
before the assignment deadline, and then afterwards, if they can find <code class="language-plaintext highlighter-rouge">m2</code> such
that <code class="language-plaintext highlighter-rouge">hash(m1) = hash(m2)</code>, they can submit <code class="language-plaintext highlighter-rouge">m2</code>, a second preimage, without
detection.  Whether <code class="language-plaintext highlighter-rouge">m2</code> will get them more marks is left as an exercise to the
student.</p>

<p>Even with no knowledge of the algorithm used, we can tell it’s not secure.  We
can observe the output of the <code class="language-plaintext highlighter-rouge">sum</code> utility is a 16-bit number (printed in
decimal usually), along with a count of how many 1024 byte blocks are in the
input.  The output being only 16 bits is simply not large enough, and we can
use brute force to find collisions: If we sum <code class="language-plaintext highlighter-rouge">2^16 + 1</code> files, we are
guaranteed to find a collision.  That’s not quite the 2nd preimage we want,
but it’s illustrative of how a small checksum value cannot be cryptographically
secure.</p>

<h2 id="the-algorithm">The Algorithm</h2>
<p>There’s no need to blindly brute-force, as we can examine how <code class="language-plaintext highlighter-rouge">sum</code> works and be a
bit more intelligent about how we attack it.  The algorithm is very simple:
Each byte is added into a 16 bit counter, and the counter is rotated right
between each addition.  Or, in Python:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">rotate_right_16bit</span><span class="p">(</span><span class="n">data</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
  <span class="k">return</span> <span class="p">(</span><span class="n">data</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">|</span> <span class="p">((</span><span class="n">data</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">15</span><span class="p">)</span>
<span class="k">for</span> <span class="n">byte</span> <span class="ow">in</span> <span class="n">data</span><span class="p">:</span>
    <span class="nb">sum</span> <span class="o">=</span> <span class="n">rotate_right_16bit</span><span class="p">(</span><span class="nb">sum</span><span class="p">)</span> <span class="o">+</span> <span class="n">byte</span>
    <span class="nb">sum</span> <span class="o">=</span> <span class="nb">sum</span> <span class="o">&amp;</span> <span class="mh">0xffff</span> <span class="c1"># clamp to 16 bits
</span></code></pre></div></div>

<h2 id="going-backwards">Going Backwards</h2>
<p>From looking at this algorithm, the first thing to notice is that all the
operations are reversible:  We can subtract and rotate left to go backwards.
That lets us add or change characters at any point in the file, and easily work
backwards to find out what the intermediate value of the checksum we need to
get our final goal value.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">rotate_left_16bit</span><span class="p">(</span><span class="n">data</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
  <span class="k">return</span> <span class="p">(</span><span class="mh">0xffff</span> <span class="o">&amp;</span> <span class="p">(</span><span class="n">data</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span><span class="p">))</span> <span class="o">|</span> <span class="p">(</span><span class="n">data</span> <span class="o">&gt;&gt;</span> <span class="mi">15</span><span class="p">)</span>
<span class="k">for</span> <span class="n">byte</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">suffix</span><span class="p">):</span>
  <span class="nb">sum</span> <span class="o">=</span> <span class="n">rotate_left_16bit</span><span class="p">((</span><span class="nb">sum</span> <span class="o">-</span> <span class="n">byte</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xffff</span><span class="p">)</span>
</code></pre></div></div>

<h2 id="making-changes">Making Changes</h2>
<p>The tool we’re writing is going to insert bytes at a particular offset into the
file.  We’ll put the extra inserted characters in a comment, string, or some
location that can be modified.  We’ll compute the sum over a prefix up to the
insertion point, and use the backwards sum computation to approach that same
point from the opposite direction.</p>

<p>Our task now is to find a set of characters that will, when inserted after the
prefix, cause the sum to that point to equal the backwards sum.  This is likely
brute-forceable, but because we can go backwards, we can do a bit better.</p>

<h2 id="meet-in-the-middle">Meet In The Middle</h2>
<p>The strategy we’ll take for our tool is going to take advantage of the fact
that the set of possible hashes is small, and that we can go backwards.</p>

<p>We’ll alternate extending prefix and suffix strings by an extra character and
then checking if the resulting hash is in the opposite set.  That is, we add to
the end of the prefix and check if we’ve hit any of the suffix hashes, and then
prepend to the suffix and check if we’ve hit any of the prefix hashes.</p>

<p>Because of the birthday paradox, and the fact that the set of hashes is only
2^16, the attack takes only a split second on my computer to run.</p>

<h2 id="character-sets">Character Sets</h2>
<p>The code for generating collisions takes a bytestring as input, and will only
use bytes from that.  This means you can, say, only feed it printable
characters, only ascii lowercase characters, or whatever you need to not break
the file you’re trying to collide.</p>

<p>Typically that means you want printable characters without newline for many
comment “to the end of the line” style comments, or you can avoid <code class="language-plaintext highlighter-rouge">/</code> if you
are using something like CSS that only does <code class="language-plaintext highlighter-rouge">/* */</code> style comments.</p>

<h2 id="block-size">Block Size</h2>

<p>Inserting a few bytes could change the number of blocks in the input.  You’ll
have to figure out what to do about that yourself.  Try inserting the new bytes
at a different location, or removing some other bytes first.</p>

<h2 id="conclusion">Conclusion</h2>

<p>This isn’t exactly a hardened target, so there’s nothing really novel here, but
I haven’t found any documentation of how to accomplish this elsewhere.</p>

<p>I doubt anyone will ever need this, but there is both an implementation of the
<a href="https://github.com/mcpherrinm/sumcoll/">sum tool and the attack tool here</a>.
If you have feedback on that tool or this blog post, feel free to post issues
there, or to email me.</p>]]></content><author><name>Matthew McPherrin</name></author><summary type="html"><![CDATA[The sum command-line tool is a simple checksum utility included in BSD and GNU Coreutils. It is not a cryptographically secure hash, and so I wrote a tool to set the sum of a file to an arbitrary value.]]></summary></entry><entry><title type="html">Blog</title><link href="https://mcpherrin.ca/2019/10/23/blog.html" rel="alternate" type="text/html" title="Blog" /><published>2019-10-23T00:00:00+00:00</published><updated>2019-10-23T00:00:00+00:00</updated><id>https://mcpherrin.ca/2019/10/23/blog</id><content type="html" xml:base="https://mcpherrin.ca/2019/10/23/blog.html"><![CDATA[<p>I have decided to set up a blog to organize and share things I do, just like
everyone else’s blogs.  I’ve made several decisions in how I’d like my blog to
work.</p>

<p>The first is that I want to store the website’s content in source control.  As
a software developer I’m very comfortable with the edit, run, CI and CD flow.
I can write in the same editor I always use.  I can make local changes offline,
test pages, and deploy when ready.  Or I can just open github.com and use the
in-browser editor.  Git is the tool of choice for me, hosted on github.com.</p>

<p>A statically generated website is easy to host anywhere.  I’m using Github and
Github Pages because it’s convenient and free, but I could easily switch to AWS
CodePipeline publishing to S3, or a docker container with Nginx serving the
static content.</p>

<p>Thus this setup is not tied to any particular vendor.  In a few minutes I could
completely abandon Github should the need ever arise.  That’s important to me,
as I want to be in control over my own content.  Leaving a hosted blogging
solution would potentially be much more complicated.</p>

<p>So the next question is what static site generator to use.  Github pages
supports Jekyll, so that makes it a great candidate.  I’ve been testing it out
and it seems to work well enough.  Markdown is easy to write for posts, and the
liquid templating system is straightforward.  I’m not using too many advanced
features, so switching shouldn’t be too hard if I don’t like Jekyll for some
reason in the future.</p>

<p>Finally, I have decided to make my own design rather than using a template. I
was able to make a basic blog template with no major issues in an evening,
which is another reason that Jekyll is working well. I made a base page layout,
an index page, and a post one.  It’ll probably be pretty ugly, but it’ll be
mine.</p>]]></content><author><name>Matthew McPherrin</name></author><summary type="html"><![CDATA[I have decided to set up a blog to organize and share things I do, just like everyone else’s blogs. I’ve made several decisions in how I’d like my blog to work.]]></summary></entry></feed>