<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/rss-style.xsl" type="text/xsl"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	     xmlns:dc="http://purl.org/dc/elements/1.1/"
	   xmlns:atom="http://www.w3.org/2005/Atom"
	     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>The least secure TOTP code possible &#8211; Terence Eden’s Blog</title>
	<atom:link href="https://shkspr.mobi/blog/2025/02/the-least-secure-totp-code-possible/feed/" rel="self" type="application/rss+xml" />
	<link>https://shkspr.mobi/blog</link>
	<description>Regular nonsense about tech and its effects 🙃</description>
	<lastBuildDate>Tue, 25 Feb 2025 15:04:58 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://shkspr.mobi/blog/wp-content/uploads/2023/07/cropped-avatar-32x32.jpeg</url>
	<title>The least secure TOTP code possible &#8211; Terence Eden’s Blog</title>
	<link>https://shkspr.mobi/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title><![CDATA[The least secure TOTP code possible]]></title>
		<link>https://shkspr.mobi/blog/2025/02/the-least-secure-totp-code-possible/</link>
					<comments>https://shkspr.mobi/blog/2025/02/the-least-secure-totp-code-possible/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Mon, 24 Feb 2025 12:34:05 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[CyberSecurity]]></category>
		<category><![CDATA[rant]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[standards]]></category>
		<category><![CDATA[totp]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=58360</guid>

					<description><![CDATA[If you use Multi-Factor Authentication, you&#039;ll be well used to scanning in QR codes which allow you to share a secret code with a website. These are known as Time-based One Time Passwords (TOTP).  As I&#039;ve moaned about before, TOTP has never been properly standardised. It&#039;s a mish-mash of half-finished proposals with no active development, no test suite, and no-one looking after it. Which is…]]></description>
										<content:encoded><![CDATA[<p>If you use Multi-Factor Authentication, you'll be well used to scanning in QR codes which allow you to share a secret code with a website. These are known as Time-based One Time Passwords (TOTP<sup id="fnref:pop"><a href="https://shkspr.mobi/blog/2025/02/the-least-secure-totp-code-possible/#fn:pop" class="footnote-ref" title="Yes! Just like Top of The Pops! The famous British TV show! Wow! I bet you're the first person in history to make that joke! Have a biscuit." role="doc-noteref">0</a></sup>).</p>

<p>As I've moaned about before, <a href="https://shkspr.mobi/blog/2022/05/why-is-there-no-formal-specification-for-otpauth-urls/">TOTP has never been properly standardised</a>. It's a mish-mash of half-finished proposals with no active development, no test suite, and no-one looking after it. Which is <em>exactly</em> what you want from a security specification, right?!</p>

<p>So let's try to find some edge-cases and see where things break down.</p>

<h2 id="one-punch-man"><a href="https://shkspr.mobi/blog/2025/02/the-least-secure-totp-code-possible/#one-punch-man">One Punch Man</a></h2>

<p>This is possibly the <em>least</em> secure TOTP code I could create. Scan it and see whether your app will accept it.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/02/ultra.png" alt="QR code." width="350" height="350" class="aligncenter size-full wp-image-58361">

<p>What makes it so crap?  There are three things which protect you when using TOTP.</p>

<ol>
<li>The shared secret. In this case, it is <code>abcdefghijklmno</code> - OK, that's not the easiest thing to guess, but it isn't exactly complex.</li>
<li>The amount time the code is valid for before changing. Most TOTP codes last 30 seconds, this lasts 120.</li>
<li>The length of the code. Most codes are 6 digits long. In theory, the spec allows 8 digits. This is 1. Yup. A single digit.</li>
</ol>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/02/totp-bitwarden-fs8.png" alt="BitWarden showing a single digit for 119 seconds." width="504" height="378" class="aligncenter size-full wp-image-58380">

<p>If you were thick enough to use this<sup id="fnref:noooooo"><a href="https://shkspr.mobi/blog/2025/02/the-least-secure-totp-code-possible/#fn:noooooo" class="footnote-ref" title="Please don't!" role="doc-noteref">1</a></sup>, an attacker would have a 1/10 chance of simply <em>guessing</em> your MFA code. If they saw you type it in, they'd have a couple of minutes in which to reuse it.</p>

<p>Can modern TOTP apps add this code? I <a href="https://mastodon.social/@Edent/114032994415288253">crowdsourced the answers</a>.</p>

<p>Surprisingly, a few apps accept it! Aegis, 1password, and BitWarden will happily store it and show you a 1 digit code for 120 seconds.</p>

<p>A few reject it. Authy, Google Authenticator, and OpenOTP claim the code is broken and won't add it.</p>

<p>But, weirdly, a few <em>interpret it incorrectly!</em> The native iOS app, Microsoft Authenticator, and KeepassXC store the code, but treat it as a 6 digit, 30 second code.</p>

<h2 id="do-the-right-thing"><a href="https://shkspr.mobi/blog/2025/02/the-least-secure-totp-code-possible/#do-the-right-thing">Do The Right Thing</a></h2>

<p>What is the right thing to do in this case? The code is outside the (very loosely defined) specification. <a href="https://lawsofux.com/postels-law/">Postel's Law</a> tells us that we should try our best to interpret malformed data - which is what Aegis and BitWarden do.</p>

<p>But, in a security context, that could be dangerous. Perhaps rejecting a dodgy code makes more sense?</p>

<p>What is absolutely daft<sup id="fnref:stronger"><a href="https://shkspr.mobi/blog/2025/02/the-least-secure-totp-code-possible/#fn:stronger" class="footnote-ref" title="I wanted to use the words &quot;utterly fucking stupid&quot; but I felt it was unprofessional." role="doc-noteref">2</a></sup> is ignoring the bits of the code you don't like and substituting your own data! Luckily, in a normal TOTP enrolment, the user has to enter a code to prove they've saved it correctly. Entering in a 6 digit code where only 1 is expected is likely to fail.</p>

<h2 id="were-only-human"><a href="https://shkspr.mobi/blog/2025/02/the-least-secure-totp-code-possible/#were-only-human">We're Only Human</a></h2>

<p>A one-digit code is ridiculous. But what about the other extreme? Would a 128-digit code be acceptable? For a human, no; it would be impossible to type in correctly. For a machine with a shared secret, it possibly makes sense.</p>

<p>On a high-latency connection or with users who may have mobility difficulties, a multi-minute timeframe could be sensible. For something of extremely high security, sub-30 seconds may be necessary.</p>

<p>But, again, the specification hasn't evolved to meet user needs. It is stagnant and decaying.</p>

<h2 id="whats-next"><a href="https://shkspr.mobi/blog/2025/02/the-least-secure-totp-code-possible/#whats-next">What's Next?</a></h2>

<p>There's an <a href="https://www.ietf.org/archive/id/draft-linuxgemini-otpauth-uri-00.html">draft proposal to tighten up to TOTP spec</a> which has expired.</p>

<p>It would be nice if the major security players came together to work out a <em>formal</em> and <em>complete</em> specification for this vital piece of security architecture. But I bet it won't ever happen.</p>

<ul>
<li><a href="https://github.com/google/google-authenticator/wiki/Key-Uri-Format">Google have archived their work on authentication standards</a>.</li>
<li><a href="https://developer.apple.com/documentation/authenticationservices/securing-logins-with-icloud-keychain-verification-codes#3795996">Apple points to Google's outdated spec</a>.</li>
<li><a href="https://docs.yubico.com/yesdk/users-manual/application-oath/uri-string-format.html">YubiCo's incompatible spec hasn't been updated in 4 years</a>.</li>
<li>The <a href="https://www.iana.org/assignments/uri-schemes/prov/otpauth">otpauth registration</a> lists a consortium called <a href="https://openauthentication.org">https://openauthentication.org</a> who don't appear to published anything in a decade.</li>
<li>Microsoft don't have any documentation whatsoever.</li>
</ul>

<p>So there you have it. We're told to rely on TOTP for our MFA - yet the major apps all disagree on how the standard should be implemented. This is a recipe for an eventual security disaster.</p>

<p>How do we fix it?</p>

<div id="footnotes" role="doc-endnotes">
<hr>
<ol start="0">

<li id="fn:pop">
<p>Yes! Just like Top of The Pops! The famous British TV show! Wow! I bet you're the first person in history to make that joke! Have a biscuit.&nbsp;<a href="https://shkspr.mobi/blog/2025/02/the-least-secure-totp-code-possible/#fnref:pop" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:noooooo">
<p>Please don't!&nbsp;<a href="https://shkspr.mobi/blog/2025/02/the-least-secure-totp-code-possible/#fnref:noooooo" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:stronger">
<p>I wanted to use the words "utterly fucking stupid" but I felt it was unprofessional.&nbsp;<a href="https://shkspr.mobi/blog/2025/02/the-least-secure-totp-code-possible/#fnref:stronger" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

</ol>
</div>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=58360&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/02/the-least-secure-totp-code-possible/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
	</channel>
</rss>
