<?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>cryptography &#8211; Terence Eden’s Blog</title>
	<atom:link href="https://shkspr.mobi/blog/tag/cryptography/feed/" rel="self" type="application/rss+xml" />
	<link>https://shkspr.mobi/blog</link>
	<description>Regular nonsense about tech and its effects 🙃</description>
	<lastBuildDate>Sat, 23 Aug 2025 06:44:33 +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>cryptography &#8211; Terence Eden’s Blog</title>
	<link>https://shkspr.mobi/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title><![CDATA[Lazy way to cause SHA-256 collisions for lazy evaluators]]></title>
		<link>https://shkspr.mobi/blog/2024/04/lazy-way-to-cause-sha-256-collisions-for-lazy-evaluators/</link>
					<comments>https://shkspr.mobi/blog/2024/04/lazy-way-to-cause-sha-256-collisions-for-lazy-evaluators/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Tue, 09 Apr 2024 11:34:11 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[cryptography]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=49889</guid>

					<description><![CDATA[Humans are lazy. That&#039;s why we have computers; to do the boring work for us.  I recently downloaded a file. The website said the file should have a SHA-256 hash of: ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb  So I ran sha256 filename on my machine. And then lazily compared the hashes. By which I mean &#34;Yeah the first few characters match, as do the last few. It&#039;s probably…]]></description>
										<content:encoded><![CDATA[<p>Humans are lazy. That's why we have computers; to do the boring work for us.</p>

<p>I recently downloaded a file. The website said the file should have a SHA-256 hash of:
<code>ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb</code></p>

<p>So I ran <code>sha256 filename</code> on my machine. And then lazily compared the hashes. By which I mean "Yeah the first few characters match, as do the last few. It's probably fine."</p>

<p>Stupid lazy humans.</p>

<p>It's pretty easy to demonstrate that you can take a string, generate a hash, and then create a different string which has a hash with the same first character as the original.</p>

<p>This toy example starts with a string "a" and then creates a different string "b". It then pads the "b" string with spaces until the first characters of both hashes match:</p>

<pre><code class="language-php">$s1 = "a";
$h1 = hash("sha256", $s1);
$first = substr($h1, 0, 1);
echo $first . "\n";

$s2 = "b";

for ($x=0; $x&lt;100; $x++) {
   $s2 .= " ";
   $h2 = hash("sha256", $s2);
   if ( $first == substr($h2,0,1) ) { 
      echo "{$s2}.{$h2}\n";
   }
}
</code></pre>

<p>Assuming SHA-256 is randomly distributed, and there are 16 possible values for each character, this should produce ~6.25 matching hashes.</p>

<p>And, indeed it does! Four hashes appear which all have the same first character.</p>

<p>What about generating a "collision" of the first and last characters?  16x16 = 256.  So that should be doable on modest hardware.</p>

<pre><code class="language-php">$s1 = "a";
$h1 = hash("sha256", $s1);
$first = substr($h1, 0, 1);
$last  = substr($h1, -1); 
echo "{$first}-{$last}\n";

$s2 = "b";

for ($x=0; $x&lt;2000; $x++) {
   $s2 .= " ";
   $h2 = hash("sha256", $s2);
   if ( $first == substr($h2,0,1) &amp;&amp; $last == substr($h2, -1) ) { 
      echo "{$s2}.{$h2}\n";
   }
}
</code></pre>

<p>That spits out a bunch of strings where the first and last characters of the hash matches the first and last of the original hash.</p>

<p>Of course, from there it gets exponentially harder. If you want to match 2 characters at each end, you'll need around 65,536 attempts.  As it happens, it takes 74,653 attempts before a "collision" of the first two and last two characters are found.</p>

<p>Of course, padding with spaces makes the string significantly longer. So you could pad with incrementing Unicode characters. Depending on the contents of the message, you could fill it with invisible characters which wouldn't be seen by an ordinary user.</p>

<p>Is this a <em>practical</em> way to generate full-length hashes? No, obviously not. It goes some way to show just how difficult it is to force even a partial collision.</p>

<p>There is <a href="https://www.da.vidbuchanan.co.uk/blog/colliding-secure-hashes.html">a brilliant explanation of this problem space on David Buchanan's blog</a>.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=49889&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/04/lazy-way-to-cause-sha-256-collisions-for-lazy-evaluators/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[A simple(ish) guide to verifying HTTP Message Signatures in PHP]]></title>
		<link>https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/</link>
					<comments>https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Tue, 27 Feb 2024 12:34:04 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[cryptography]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[mastodon]]></category>
		<category><![CDATA[security]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=49733</guid>

					<description><![CDATA[Mastodon makes heavy use of HTTP Message Signatures. They&#039;re a newish almost-standard which allows a server to verify that a request made to it came from the person who sent it.  This is a quick example to show how to verify these signatures using PHP. I don&#039;t claim that it covers every use-case, and it is no-doubt missing some weird edge cases. But it successfully verifies messages sent by…]]></description>
										<content:encoded><![CDATA[<p>Mastodon makes heavy use of <a href="https://datatracker.ietf.org/doc/rfc9421/">HTTP Message Signatures</a>. They're a newish almost-standard which allows a server to verify that a request made to it came from the person who sent it.</p>

<p>This is a quick example to show how to verify these signatures using PHP. I don't claim that it covers every use-case, and it is no-doubt missing some weird edge cases. But it successfully verifies messages sent by multiple Fediverse servers.</p>

<p>Let's step through it with an example of a message sent from Mastodon to my server.</p>

<h2 id="headers"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#headers">Headers</a></h2>

<p>The HTTP request starts with these headers:</p>

<pre><code class="language-_">User-Agent:  http.rb/5.1.1 (Mastodon/4.3.0-nightly.2024-02-23; +https://mastodon.social/)
Host:  example.com
Date:  Sun, 25 Feb 2024 10:48:22 GMT
Accept-Encoding:  gzip
Digest:  SHA-256=Hqu/6MR2imi8DTzbNp5PNEAFSyk0poN7+x5F+Z4vZMg=
Content-Type:  application/activity+json
Signature:  keyId="https://mastodon.social/users/Edent#main-key",algorithm="rsa-sha256",headers="(request-target) host date digest content-type",signature="P07V5I2zflR8FRsDMHshHmhgOwSkjWevujEbOyKMwjycrdVXjTD0ACiLuc5lTqDEXZ/...4eg=="
Connection:  Keep-Alive
Content-Length:  2857
</code></pre>

<p>Some of those you may be familiar with, some not.  The first thing we'll do is a sanity check; was this message sent recently? Because clocks drift in and out of synchronisation, we'll check if the message was within ±30 seconds.</p>

<pre><code class="language-php">$headers = getallheaders();
if ( !isset( $headers["Date"] ) ) { return null; }  //  No date set
$dateHeader = $headers["Date"];
$headerDatetime  = DateTime::createFromFormat('D, d M Y H:i:s T', $dateHeader);
$currentDatetime = new DateTime();

// Calculate the time difference in seconds
$timeDifference = abs( $currentDatetime-&gt;getTimestamp() - $headerDatetime-&gt;getTimestamp() );
return ( $timeDifference &lt; 30 );
</code></pre>

<p>That was easy! On to the next bit.</p>

<h2 id="digest"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#digest">Digest</a></h2>

<p>A message posted to the server usually has a body. In this case it is a long string of JSON data.  To ensure the message hasn't been altered in transit, one of the headers is:</p>

<pre><code class="language-_">Digest:  SHA-256=Hqu/6MR2imi8DTzbNp5PNEAFSyk0poN7+x5F+Z4vZMg=
</code></pre>

<p>That says, if you do a SHA-256 hash of the JSON you received, and convert that hash to Base64, it should match the digest in the header.</p>

<pre><code class="language-php">$digestString = $headers["Digest"];
//  Usually in the form `SHA-256=Hqu/6MR2imi8DTzbNp5PNEAFSyk0poN7+x5F+Z4vZMg=`
//  The Base64 encoding may have multiple `=` at the end. So split this at the first `=`
$digestData = explode( "=", $digestString, 2 );
$digestAlgorithm = $digestData[0];
$digestHash = $digestData[1];

//  There might be many different hashing algorithms
//  TODO: Find a way to transform these automatically
if ( "SHA-256" == $digestAlgorithm ) {
    $digestAlgorithm = "sha256";
} else if ( "SHA-512" == $digestAlgorithm ) {
    $digestAlgorithm = "sha512";
}

$json = file_get_contents( "php://input" );

//  Manually calculate the digest based on the data sent
$digestCalculated = base64_encode( hash( $digestAlgorithm, $json, true ) );

return ( $digestCalculated == $digestHash );
</code></pre>

<p>But, of course, if someone has manipulated the JSON, they may also have manipulated the digest. So it is time to look at the signature.</p>

<h2 id="the-signature"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#the-signature">The Signature</a></h2>

<p>Let's take a look at the signature header:</p>

<pre><code class="language-_">Signature:
  keyId="https://mastodon.social/users/Edent#main-key",
  algorithm="rsa-sha256",
  headers="(request-target) host date digest content-type",
  signature="P07V5I2zflR8FRsDMHshHmhgOwSkjWevujEbOyKMwjycrdVXjTD0ACiLuc5lTqDEXZ/...4eg=="
</code></pre>

<p>This contains 4 pieces of information.</p>

<ol>
<li><code>keyID</code> - a link to the user's public key.</li>
<li><code>algorithm</code> - the algorithm used by this signature.</li>
<li><code>headers</code> - the headers which make up the string to be signed.</li>
<li><code>signature</code> - the signature string.</li>
</ol>

<p>Let's split them up so they can be used:</p>

<pre><code class="language-php">//  Examine the signature
$signatureHeader = $headers["Signature"];

// Extract key information from the Signature header
$signatureParts = [];
//  Converts 'a=b,c=d e f' into ["a"=&gt;"b", "c"=&gt;"d e f"]
               // word="text"
preg_match_all('/(\w+)="([^"]+)"/', $signatureHeader, $matches);
foreach ($matches[1] as $index =&gt; $key) {
    $signatureParts[$key] = $matches[2][$index];
}
</code></pre>

<p>Let's tackle each part in order.</p>

<h3 id="get-the-users-public-key"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#get-the-users-public-key">Get the user's public key</a></h3>

<p>You might think you can just get <code>https://mastodon.social/users/Edent#main-key</code> - but you would be wrong.</p>

<p>Firstly, you need to tell the key server that you want the JSON representation of the URl - otherwise you'll end up with HTML.</p>

<pre><code class="language-php">$publicKeyURL = $signatureParts["keyId"];
$context   = stream_context_create(
    [ "http" =&gt; [ "header" =&gt; "Accept: application/activity+json" ] ] 
);
$userJSON  = file_get_contents( $publicKeyURL, false, $context );
</code></pre>

<p>That gets you the JSON representation of the user.  On Mastodon, the key can be found at:
<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/02/jsonkey.pnh-fs8.png" alt="Screenshot of JSON. As described in text." width="938" height="355" class="aligncenter size-full wp-image-49734"></p>

<p>I don't know how to automatically find the key, so I've hard-coded its location.</p>

<pre><code class="language-php">$userData  = json_decode( $userJSON, true );
$publicKey = $userData["publicKey"]["publicKeyPem"];
</code></pre>

<h3 id="get-the-algorithm"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#get-the-algorithm">Get the algorithm</a></h3>

<p>This is rather straightforward. It's just the text in the signature header:</p>

<pre><code class="language-php">$algorithm = $signatureParts["algorithm"];
</code></pre>

<h3 id="reconstruct-the-signing-header"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#reconstruct-the-signing-header">Reconstruct the signing header</a></h3>

<p>Let's take a look at the third piece of the puzzle:</p>

<p><code>headers="(request-target) host date digest content-type"</code></p>

<p>This says "The signature is based on the following parts in order". So we only care about the headers which make up the request, the host, the date, the digest, and the content type. Other servers may require different parts of the headers.</p>

<p>Again, let's tackle them in order.</p>

<h4 id="request-target"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#request-target"><code>(request-target)</code></a></h4>

<p>This means the method of the request and the target it was sent to.  In our example, this is a <code>POST</code> sent to the path <code>/inbox</code>.</p>

<h4 id="host"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#host"><code>host</code></a></h4>

<p>This is the HTTP host the message was sent to.  This should be retrieved from the server, not taken from the sent headers.</p>

<h4 id="date-digest-content-type"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#date-digest-content-type"><code>date digest content-type</code></a></h4>

<p>These are the values from the headers which were sent with the request.</p>

<h4 id="putting-it-all-together"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#putting-it-all-together">Putting it all together</a></h4>

<p>Annoyingly, the HTTP headers are written in Title-Case whereas the headers in the Signature are in lower-case. So some conversion is necessary:</p>

<pre><code class="language-php">//  Manually reconstruct the header string
$signatureHeaders = explode(" ", $signatureParts["headers"] );
$signatureString = "";
foreach ($signatureHeaders as $signatureHeader) {
    if ( "(request-target)" == $signatureHeader ) {
        $method = strtolower( $_SERVER["REQUEST_METHOD"] );
        $target = strtolower( $_SERVER["REQUEST_URI"] );
        $signatureString .= "(request-target): {$method} {$target}\n";
    } else if ( "host" == $signatureHeader ) {
        $host = strtolower( $_SERVER["HTTP_HOST"] );    
        $signatureString .= "host: {$host}\n";
    } else {
        //  In the HTTP header, the keys use Title Case
        $signatureString .= "{$signatureHeader}: " . $headers[ ucwords( $signatureHeader, "-" ) ] . "\n";
    }
}

//  Remove trailing newline
$signatureString = trim( $signatureString );
</code></pre>

<p>This results in a string like this:</p>

<pre><code class="language-_">(request-target): post /inbox
host: example.com
date: Sun, 25 Feb 2024 10:48:22 GMT
digest: SHA-256=Hqu/6MR2imi8DTzbNp5PNEAFSyk0poN7+x5F+Z4vZMg=
content-type: application/activity+json
</code></pre>

<h2 id="get-the-signature"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#get-the-signature">Get the signature</a></h2>

<p>The signature that we are sent is in Base64.</p>

<p><code>signature="P07V5I2zflR8FRsDMHshHmhgOwSkjWevujEbOyKMwjycrdVXjTD0ACiLuc5lTqDEXZ/...4eg=="</code></p>

<p>It needs to be decoded before we can use it.</p>

<pre><code class="language-php">$signature = base64_decode( $signatureParts["signature"] );
</code></pre>

<h2 id="verify-the-signature"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#verify-the-signature">Verify the signature</a></h2>

<p>We're nearly there!  Luckily, we don't have to do any crazy cryptography by hand. We use PHP's <a href="https://www.php.net/manual/en/function.openssl-verify"><code>openssl_verify()</code></a>:</p>

<pre><code class="language-php">//  Finally! Calculate whether the signature is valid
$verified = openssl_verify(
    $signatureString, 
    $signature, 
    $publicKey, 
    $algorithm
);
</code></pre>

<p>That takes the reconstructed string based on the headers, the signature which was sent, the public key we retrieved, and the algorithm.</p>

<p>If it all matches, it will return <code>true</code>.  If not... time for some debugging!</p>

<h2 id="but-what-about"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#but-what-about">But what about...?</a></h2>

<p>This is <em>not</em> a complete solution. My code almost certainly contains bugs, unforeseen edge-cases, memory leaks, black holes, and poisonous frogs.  This is intended to step you through the practical process of verifying an HTTP Message Signature.</p>

<p>Then you should get a properly tested and validated library and use that instead.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=49733&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Offline Digital Currency Transactions]]></title>
		<link>https://shkspr.mobi/blog/2023/03/offline-digital-currency-transactions/</link>
					<comments>https://shkspr.mobi/blog/2023/03/offline-digital-currency-transactions/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Mon, 06 Mar 2023 12:34:22 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[blockchain]]></category>
		<category><![CDATA[crypto]]></category>
		<category><![CDATA[cryptography]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=42683</guid>

					<description><![CDATA[Wouldn&#039;t it be good if digital currencies worked offline?  I&#039;m going to talk through a proposed user experience, and then discuss how it would work in practice.  Let us imagine a future digital currency ₢. It might be fiat, it might be crypto, doesn&#039;t really matter.   Alice loads up a smartcard with ₢100 and locks it. Alice gives Bob the smartcard. Bob uses offline verification to see that the sma…]]></description>
										<content:encoded><![CDATA[<p>Wouldn't it be good if digital currencies worked offline?</p>

<p>I'm going to talk through a proposed user experience, and then discuss how it would work in practice.</p>

<p>Let us imagine a future digital currency <strong>₢</strong>. It might be fiat, it might be crypto, doesn't really matter.</p>

<ul>
<li>Alice loads up a smartcard with ₢100 and locks it.</li>
<li>Alice gives Bob the smartcard.</li>
<li>Bob uses offline verification to see that the smartcard contains ₢100 of unspent currency.</li>
<li>Bob unlocks the smartcard and transfers the ₢100 to his own wallet.</li>
</ul>

<h2 id="sketching-out-how-it-works"><a href="https://shkspr.mobi/blog/2023/03/offline-digital-currency-transactions/#sketching-out-how-it-works">Sketching out how it works.</a></h2>

<p>The key thing here is that Bob doesn't need to connect to the Internet - or do a live check with any 3rd party - in order to verify that the card has cash.  How would that work?</p>

<p>It is - sadly and unavoidably - an escrow system.  If you want to avoid the "double-spend" problem without going online, then you need intermediary to vouch that the funds are locked.</p>

<p>Let us imagine a physical token. For example, a Smartcard with an embedded microchip. The microchip has a unique ID and is able to perform certain cryptographic functions.  It is able to sign data with its own private key - for example, it may have embedded a subkey of its manufacturer.</p>

<p>When Alice loads a card, this is what happens.</p>

<ul>
<li>Alice sends a challenge, signed with her private key, to the Smartcard.</li>
<li>Smartcard sends Alice a response to the challenge, and its unique ID, signed with its private key.</li>
<li>Alice tells the Escrow provider that she is in possession of a specific Smartcard by sending her signed challenge and the Smartcard's signed response.</li>
<li>The Escrow provider checks a public ledger to see if this specific Smartcard is in use.</li>
<li>If the card is not in use, the Escrow sends a challenge, signed with its private key, to the Smartcard.</li>
<li>Smartcard sends the Escrow provider a response signed with its private key.</li>
<li>Escrow provider tells Alice that it is convinced that she is in possession of that Smartcard.</li>
<li>Alice sends ₢100 to the Escrow provider.</li>
<li>Escrow sends the Smartcard a cryptographically signed digital certificate saying that Escrow is in possession of ₢100 and will release it to the bearer of the Smartcard.

<ul>
<li>The certificate could be time-limited?</li>
</ul></li>
<li>Smartcard validates the certificate and securely stores it for later retrieval.</li>
</ul>

<p>Effectively, this Smartcard is now digitally engraved with the words "<a href="https://www.bankofengland.co.uk/freedom-of-information/2016/25-february-2016">I promise to pay the bearer on demand</a>".  Anyone who proves that they are in possession of that <em>specific</em> Smartcard, can redeem the stored value from the Escrow provider.</p>

<p>Here's how it works.</p>

<ul>
<li>Bob asks Alice for ₢100.</li>
<li>Alice hands Bob a Smartcard.</li>
<li>Bob asks the Smartcard for the amount it has stored.</li>
<li>Smartcard responds with a figure which is cryptographically signed with the private keys of the Smartcard and the Escrow provider.</li>
<li>Bob has previously stored the public keys of all major Escrow providers.</li>
<li>Bob validates offline the Escrow's signed statement against the Escrow's public key.

<ul>
<li>Alternatively, Bob may have the Smartcard vendor's public keys available for validation.</li>
</ul></li>
<li>Once satisfied the card contains the correct amount, he takes the card.</li>
</ul>

<p>How does Bob redeem the stored value?  Well, firstly, he doesn't have to! The smartcard is <em>fungible</em>. He can hand it over to someone else as payment.</p>

<p>But, if Bob wants to "cash in" the card and transfer the ₢100 to his own wallet, he will need an Internet connection</p>

<ul>
<li>Bob sends a challenge, signed with her private key, to the Smartcard.</li>
<li>Smartcard sends Bob a response to the challenge, and its unique ID, signed with its private key.</li>
<li>Bob tells the Escrow provider that he is in possession of a specific Smartcard by sending his signed challenge and the Smartcard's signed response.</li>
<li>The Escrow provider checks a public ledger to see if this specific Smartcard is in use.</li>
<li>If the card is not in use, the Escrow sends a challenge, signed with its private key, to the Smartcard.</li>
<li>Smartcard sends the Escrow provider a response signed with its private key.</li>
<li>Escrow provider tells Bob that it is convinced that he is in possession of that Smartcard.</li>
<li>Bob tells the Escrow provider he wants to cash out and sends them the details of his wallet.</li>
<li>Escrow provider sends an instruction to the smart card to "self-destruct" and remove the signed amount.</li>
<li>Smartcard deletes the stored amount and sends a signed transaction back to the Escrow.</li>
<li>Escrow transfers the money to Bob's wallet.</li>
</ul>

<p>All this is... complicated. And relies on smartcards which have close-to-unbreakable storage for their private keys. And has a lot on baked-in assumptions about humans <em>want</em> to transfer money. But it is <em>something</em>. At the moment, all cryptocurrencies <em>demand</em> a permanent Internet connection if you want to use them. I think offline transactions are useful.</p>

<p>Notably, it <em>doesn't</em> require a blockchain or any cryptocurrency. It makes use of cryptography, sure. But you don't need inefficient, permanently-online, slow databases to make this work.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=42683&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2023/03/offline-digital-currency-transactions/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Illegal Hashes]]></title>
		<link>https://shkspr.mobi/blog/2022/11/illegal-hashes/</link>
					<comments>https://shkspr.mobi/blog/2022/11/illegal-hashes/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Mon, 28 Nov 2022 12:34:14 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[cryptography]]></category>
		<category><![CDATA[hashing]]></category>
		<category><![CDATA[NaBloPoMo]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=43570</guid>

					<description><![CDATA[To understand this blog post, you need to know two things.   There exists a class of numbers which are illegal in some jurisdictions. For example, a number may be copyrighted content, a decryption key, or other text considered illegal. There exists a class of algorithms which will take any arbitrary data and produce a fixed length text from it. This process is known as &#34;hashing&#34;. These algorithms …]]></description>
										<content:encoded><![CDATA[<p>To understand this blog post, you need to know two things.</p>

<ol>
<li>There exists a class of <a href="https://en.wikipedia.org/wiki/Illegal_number">numbers which are illegal in some jurisdictions</a>. For example, a number may be copyrighted content, a decryption key, or other text considered illegal.</li>
<li>There exists a class of algorithms which will take any arbitrary data and produce a fixed length text from it. This process is known as "<a href="https://en.wikipedia.org/wiki/Hash_function">hashing</a>". These algorithms are deterministic - that is, entering the same data will always produce the same hash.</li>
</ol>

<p>Let's take the <a href="https://en.wikipedia.org/wiki/MD5">MD5 hashing algorithm</a>. Feed it <em>any</em> data and it will produce hash with a fixed length of 128 bits. Using an 8 bit alphabet, that's 16 human-readable characters.</p>

<p>Suppose you live in a country with <i lang="fr">Lèse-majesté</i> - laws which make it treasonous to insult or threaten the monarch.</p>

<p>There exists a seemingly innocent piece of data - an image, an MP3, a text file - which when fed to MD5 produces these 128 bits:</p>

<pre><code class="language-_">01001001 00100000 01101000 01100001 
01110100 01100101 00100000 01110100 
01101000 01100101 00100000 01110001 
01110101 01100101 01100101 01101110 
</code></pre>

<p>Decoded into ASCII, that spells <code>I hate the queen</code>.</p>

<p>128 bits is <em>probably</em> too short to be illegal in all but the most repressive of regimes. It would be hard, if not impossible, to squeeze terrorist plans into that little space.</p>

<p>But it is just enough space to store an <a href="https://en.wikipedia.org/wiki/AACS_encryption_key_controversy">encryption key for copyrighted material</a>.</p>

<p>Therefore, it is possible that there exists a file which - by pure coincidence - happens to have an MD5 hash which is illegal.</p>

<p>Because MD5 is a relatively weak algorithm, it is possible to <a href="https://github.com/corkami/collisions">create <em>deliberate</em> hash "collisions"</a>. That is, take some data and manipulate it until it has the <em>same</em> MD5 as a different piece of data.</p>

<p>Someone could, theoretically, deliberately create a file which looks unremarkable when viewed, but is illegal when hashed.</p>

<p>The SHA-1 hashing algorithm produces 160 bits - 20 ASCII characters. It is <em>somewhat</em> <a href="https://www.zdnet.com/article/sha-1-collision-attacks-are-now-actually-practical-and-a-looming-danger/">cheap and easy to produce a file with a specific SHA-1 hash</a>.</p>

<p>The SHA-512 hashing algorithm, as its name suggests, produces a 512 bit hash. That's enough space for 64 ASCII characters. Is that long enough to contain text which is blatantly illegal? Almost certainly. But modern hashing algorithms are designed to be resistant to collision attacks. So much so that it seems like <a href="https://link.springer.com/chapter/10.1007/978-3-030-84242-0_22">theoretical quantum computers will be needed to crack them</a>.  The chances of any file having an illegal hash is infinitesimally small.</p>

<p>Nevertheless, it intrigues me that there may be a form of hash-steganography. How would you detect whether the hash of a file was problematic?</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=43570&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2022/11/illegal-hashes/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[How does Shamir's Secret Sharing deal with the Murder on the Orient Express Problem?]]></title>
		<link>https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/</link>
					<comments>https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Thu, 07 Jul 2022 11:34:08 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[cryptography]]></category>
		<category><![CDATA[security]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=42859</guid>

					<description><![CDATA[Shamir&#039;s Secret Sharing (henceforth &#34;SSS&#34;) is clever. Far too clever for most people to understand - but let&#039;s give it a go.  Suppose you have a super-secure password for a Really Important Thing.  Th15IsMyP4s5w0rd!123  You can remember this - because you&#039;re awesome. But it might be a good idea to share the password with someone else, just in case.  Of course, if you share it with one person,…]]></description>
										<content:encoded><![CDATA[<p>Shamir's Secret Sharing (henceforth "SSS") is clever. Far too clever for most people to understand - but let's give it a go.</p>

<p>Suppose you have a super-secure password for a Really Important Thing.</p>

<p><code>Th15IsMyP4s5w0rd!123</code></p>

<p>You can remember this - because you're awesome. But it <em>might</em> be a good idea to share the password with someone else, just in case.  Of course, if you share it with one person, they'll be able to use it. No good! So you split the password into several overlapping pieces and give each one to a different trusted friend.</p>

<pre> T____s____s____d____ 
</pre>

<p><br></p>

<pre> ____Is___4s___r____3 
</pre>

<p><br></p>

<pre> Th____MyP4____r____3 
</pre>

<p><br></p>

<pre> __15_______5w0__!12_ 
</pre>

<p><br></p>

<p>And so on and so forth.  As you can see, no one person has the entire password. All the participants need to get together in order to reconstruct the whole things.</p>

<p>(This is a <strong>massive</strong> simplification. The <em>real</em> SSS is so mind-boggling complex that your brain will melt before you understand even half of it. At a minimum, you need to be able to understand maths like this:</p>

<p><a href="https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing"></a></p><a href="https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing">

<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="33.286ex" height="9.343ex" style="vertical-align: -5.005ex;" viewBox="0 -1867.7 14331.5 4022.5" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" aria-labelledby="MathJax-SVG-1-Title">
<title id="MathJax-SVG-1-Title">{\displaystyle a_{0}=f(0)=\sum _{j=0}^{k-1}y_{j}\prod _{\begin{smallmatrix}m\,=\,0\\m\,\neq \,j\end{smallmatrix}}^{k-1}{\frac {x_{m}}{x_{m}-x_{j}}}}</title>
<defs aria-hidden="true">
<path stroke-width="1" id="E1-MJMATHI-61" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z"></path>
<path stroke-width="1" id="E1-MJMAIN-30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z"></path>
<path stroke-width="1" id="E1-MJMAIN-3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"></path>
<path stroke-width="1" id="E1-MJMATHI-66" d="M118 -162Q120 -162 124 -164T135 -167T147 -168Q160 -168 171 -155T187 -126Q197 -99 221 27T267 267T289 382V385H242Q195 385 192 387Q188 390 188 397L195 425Q197 430 203 430T250 431Q298 431 298 432Q298 434 307 482T319 540Q356 705 465 705Q502 703 526 683T550 630Q550 594 529 578T487 561Q443 561 443 603Q443 622 454 636T478 657L487 662Q471 668 457 668Q445 668 434 658T419 630Q412 601 403 552T387 469T380 433Q380 431 435 431Q480 431 487 430T498 424Q499 420 496 407T491 391Q489 386 482 386T428 385H372L349 263Q301 15 282 -47Q255 -132 212 -173Q175 -205 139 -205Q107 -205 81 -186T55 -132Q55 -95 76 -78T118 -61Q162 -61 162 -103Q162 -122 151 -136T127 -157L118 -162Z"></path>
<path stroke-width="1" id="E1-MJMAIN-28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"></path>
<path stroke-width="1" id="E1-MJMAIN-29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z"></path>
<path stroke-width="1" id="E1-MJSZ2-2211" d="M60 948Q63 950 665 950H1267L1325 815Q1384 677 1388 669H1348L1341 683Q1320 724 1285 761Q1235 809 1174 838T1033 881T882 898T699 902H574H543H251L259 891Q722 258 724 252Q725 250 724 246Q721 243 460 -56L196 -356Q196 -357 407 -357Q459 -357 548 -357T676 -358Q812 -358 896 -353T1063 -332T1204 -283T1307 -196Q1328 -170 1348 -124H1388Q1388 -125 1381 -145T1356 -210T1325 -294L1267 -449L666 -450Q64 -450 61 -448Q55 -446 55 -439Q55 -437 57 -433L590 177Q590 178 557 222T452 366T322 544L56 909L55 924Q55 945 60 948Z"></path>
<path stroke-width="1" id="E1-MJMATHI-6A" d="M297 596Q297 627 318 644T361 661Q378 661 389 651T403 623Q403 595 384 576T340 557Q322 557 310 567T297 596ZM288 376Q288 405 262 405Q240 405 220 393T185 362T161 325T144 293L137 279Q135 278 121 278H107Q101 284 101 286T105 299Q126 348 164 391T252 441Q253 441 260 441T272 442Q296 441 316 432Q341 418 354 401T367 348V332L318 133Q267 -67 264 -75Q246 -125 194 -164T75 -204Q25 -204 7 -183T-12 -137Q-12 -110 7 -91T53 -71Q70 -71 82 -81T95 -112Q95 -148 63 -167Q69 -168 77 -168Q111 -168 139 -140T182 -74L193 -32Q204 11 219 72T251 197T278 308T289 365Q289 372 288 376Z"></path>
<path stroke-width="1" id="E1-MJMATHI-6B" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z"></path>
<path stroke-width="1" id="E1-MJMAIN-2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z"></path>
<path stroke-width="1" id="E1-MJMAIN-31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"></path>
<path stroke-width="1" id="E1-MJMATHI-79" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path>
<path stroke-width="1" id="E1-MJSZ2-220F" d="M220 812Q220 813 218 819T214 829T208 840T199 853T185 866T166 878T140 887T107 893T66 896H56V950H1221V896H1211Q1080 896 1058 812V-311Q1076 -396 1211 -396H1221V-450H725V-396H735Q864 -396 888 -314Q889 -312 889 -311V896H388V292L389 -311Q405 -396 542 -396H552V-450H56V-396H66Q195 -396 219 -314Q220 -312 220 -311V812Z"></path>
<path stroke-width="1" id="E1-MJMATHI-6D" d="M21 287Q22 293 24 303T36 341T56 388T88 425T132 442T175 435T205 417T221 395T229 376L231 369Q231 367 232 367L243 378Q303 442 384 442Q401 442 415 440T441 433T460 423T475 411T485 398T493 385T497 373T500 364T502 357L510 367Q573 442 659 442Q713 442 746 415T780 336Q780 285 742 178T704 50Q705 36 709 31T724 26Q752 26 776 56T815 138Q818 149 821 151T837 153Q857 153 857 145Q857 144 853 130Q845 101 831 73T785 17T716 -10Q669 -10 648 17T627 73Q627 92 663 193T700 345Q700 404 656 404H651Q565 404 506 303L499 291L466 157Q433 26 428 16Q415 -11 385 -11Q372 -11 364 -4T353 8T350 18Q350 29 384 161L420 307Q423 322 423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 181Q151 335 151 342Q154 357 154 369Q154 405 129 405Q107 405 92 377T69 316T57 280Q55 278 41 278H27Q21 284 21 287Z"></path>
<path stroke-width="1" id="E1-MJMAIN-2260" d="M166 -215T159 -215T147 -212T141 -204T139 -197Q139 -190 144 -183L306 133H70Q56 140 56 153Q56 168 72 173H327L406 327H72Q56 332 56 347Q56 360 70 367H426Q597 702 602 707Q605 716 618 716Q625 716 630 712T636 703T638 696Q638 692 471 367H707Q722 359 722 347Q722 336 708 328L451 327L371 173H708Q722 163 722 153Q722 140 707 133H351Q175 -210 170 -212Q166 -215 159 -215Z"></path>
<path stroke-width="1" id="E1-MJMATHI-78" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z"></path>
</defs>
<g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)" aria-hidden="true">
 <use xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-61" x="0" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-30" x="748" y="-213"></use>
 <use xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-3D" x="1261" y="0"></use>
 <use xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-66" x="2317" y="0"></use>
 <use xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-28" x="2867" y="0"></use>
 <use xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-30" x="3257" y="0"></use>
 <use xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-29" x="3757" y="0"></use>
 <use xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-3D" x="4425" y="0"></use>
<g transform="translate(5481,0)">
 <use xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJSZ2-2211" x="0" y="0"></use>
<g transform="translate(124,-1090)">
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-6A" x="0" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-3D" x="412" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-30" x="1191" y="0"></use>
</g>
<g transform="translate(85,1151)">
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-6B" x="0" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-2212" x="521" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-31" x="1300" y="0"></use>
</g>
</g>
<g transform="translate(7092,0)">
 <use xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-79" x="0" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-6A" x="693" y="-213"></use>
</g>
<g transform="translate(8141,0)">
 <use xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJSZ2-220F" x="451" y="0"></use>
<g transform="translate(0,-1469)">
<g transform="translate(167,0)">
<g transform="translate(-11,0)">
<g transform="translate(0,378)">
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-6D" x="0" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-3D" x="1114" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-30" x="2128" y="0"></use>
</g>
<g transform="translate(31,-345)">
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-6D" x="0" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-2260" x="1114" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-6A" x="2128" y="0"></use>
</g>
</g>
</g>
</g>
<g transform="translate(454,1151)">
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-6B" x="0" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-2212" x="521" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-31" x="1300" y="0"></use>
</g>
</g>
<g transform="translate(10490,0)">
<g transform="translate(120,0)">
<rect stroke="none" width="3600" height="60" x="0" y="220"></rect>
<g transform="translate(1153,677)">
 <use xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-78" x="0" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-6D" x="809" y="-213"></use>
</g>
<g transform="translate(60,-686)">
 <use xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-78" x="0" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-6D" x="809" y="-213"></use>
 <use xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMAIN-2212" x="1515" y="0"></use>
<g transform="translate(2516,0)">
 <use xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-78" x="0" y="0"></use>
 <use transform="scale(0.707)" xlink:href="https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/#E1-MJMATHI-6A" x="809" y="-213"></use>
</g>
</g>
</g>
</g>
</g>
</svg>

</a><p><a href="https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing"></a> before you can even make a start.)</p>

<p>You can make it so that a simple majority of secret-holders are mathematically guaranteed to be able to reconstruct the password.  So you could split it between 10 friends, safe in the knowledge that your security is impenetrable until at least 6 of them betray you.</p>

<p>"Murder on the Orient Express" is one of Agatha Christie's most beloved murder mysteries. It's 88 years old which, so I'm told, is beyond the statute of limitation for spoilers.</p>

<p>In the book, American businessman Samuel Ratchett is murdered while travelling on the Orient Express train. But <em>which</em> passenger murderised him?</p>

<p>All of them. They all did it. Individually they all had motive, so they ganged up and each stabbed him.</p>

<p>I'm sure none of your friends would do the same.</p>

<p>If you used SSS to split your Cryptocurrency password between a dozen trusted friends, I'm sure the promise of untold riches wouldn't be enough to tempt half of them. Would it?</p>

<p>Of course, you don't tell the secret-keepers who their fellows are. But social graphs are fairly easy to navigate. And not all of your friends have perfect security. A few hacks here, a gentle inquiry there, a bribe or two, and a threatening word in the right ear - suddenly you find yourself drugged, in the dark, and being stabbed. Metaphorically.</p>

<p>There are no simple technological solutions to complex social problems.</p>

<p>There is no fancy mathematics which can fix this. If you split a secret in such a way that it can be reconstructed for a sanctioned purpose, then it can be reconstructed for an <em>unsanctioned</em> purpose.</p>

<p>SSS is a <em>technologically</em> excellent scheme - but it requires strong <em>social</em> bonds to operate effectively.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=42859&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2022/07/how-does-shamirs-secret-sharing-deal-with-the-murder-on-the-orient-express-problem/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Staking Claims with Scheduled Tweets]]></title>
		<link>https://shkspr.mobi/blog/2020/08/staking-claims-with-scheduled-tweets/</link>
					<comments>https://shkspr.mobi/blog/2020/08/staking-claims-with-scheduled-tweets/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 23 Aug 2020 11:04:21 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[cryptography]]></category>
		<category><![CDATA[twitter]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=36354</guid>

					<description><![CDATA[Twitter has a nifty new feature which allows you to schedule the publication of a Tweet. But, crucially, it doesn&#039;t let the reader know when the message was originally written.  How can you, as a publisher, prove that you wrote a scheduled Tweet at a specific time?  Here&#039;s one method.   Write a Tweet which contains a timestamp - &#34;This is my message 2020-08-17&#34; Generate a hash of the message -…]]></description>
										<content:encoded><![CDATA[<p>Twitter has a nifty new feature which allows you to schedule the publication of a Tweet. But, crucially, it doesn't let the reader know when the message was <em>originally</em> written.</p>

<p>How can you, as a publisher, prove that you wrote a scheduled Tweet at a specific time?</p>

<p>Here's one method.</p>

<ol>
<li>Write a Tweet which contains a timestamp - "This is my message 2020-08-17"</li>
<li>Generate a hash of the message - <code>SHA256: BAE149775399E3AEBC9DEF9D4D4468C9217593B58B76655F479C9CEE4FF73CBA</code></li>
<li>Post the hash to Twitter.</li>
<li>Schedule your message as a <em>reply</em> to the hash.</li>
</ol>

<p>Here's an example - check the dates:</p>

<blockquote class="social-embed" id="social-embed-1297473659880091650" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><blockquote class="social-embed" id="social-embed-1295344665101766656" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://twitter.com/edent" class="social-embed-user" itemprop="url"><img class="social-embed-avatar social-embed-avatar-circle" src="data:image/webp;base64,UklGRkgBAABXRUJQVlA4IDwBAACQCACdASowADAAPrVQn0ynJCKiJyto4BaJaQAIIsx4Au9dhDqVA1i1RoRTO7nbdyy03nM5FhvV62goUj37tuxqpfpPeTBZvrJ78w0qAAD+/hVyFHvYXIrMCjny0z7wqsB9/QE08xls/AQdXJFX0adG9lISsm6kV96J5FINBFXzHwfzMCr4N6r3z5/Aa/wfEoVGX3H976she3jyS8RqJv7Jw7bOxoTSPlu4gNbfXYZ9TnbdQ0MNnMObyaRQLIu556jIj03zfJrVgqRM8GPwRoWb1M9AfzFe6Mtg13uEIqrTHmiuBpH+bTVB5EEQ3uby0C//XOAPJOFv4QV8RZDPQd517Khyba8Jlr97j2kIBJD9K3mbOHSHiQDasj6Y3forATbIg4QZHxWnCeqqMkVYfUAivuL0L/68mMnagAAA" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">Terence Eden is on Mastodon</p>@edent</div></a><img class="social-embed-logo" alt="Twitter" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%0Aaria-label%3D%22Twitter%22%20role%3D%22img%22%0AviewBox%3D%220%200%20512%20512%22%3E%3Cpath%0Ad%3D%22m0%200H512V512H0%22%0Afill%3D%22%23fff%22%2F%3E%3Cpath%20fill%3D%22%231d9bf0%22%20d%3D%22m458%20140q-23%2010-45%2012%2025-15%2034-43-24%2014-50%2019a79%2079%200%2000-135%2072q-101-7-163-83a80%2080%200%200024%20106q-17%200-36-10s-3%2062%2064%2079q-19%205-36%201s15%2053%2074%2055q-50%2040-117%2033a224%20224%200%2000346-200q23-16%2040-41%22%2F%3E%3C%2Fsvg%3E"></header><section class="social-embed-text" itemprop="articleBody">My reply to this message will have a SHA256 hash of:<br>04CBC2CCD67A7C4F932FCBD21E8A5C366D4E18D1AC2EDC6782FDC873AE1E2859</section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/edent/status/1295344665101766656"><span aria-label="4 likes" class="social-embed-meta">❤️ 4</span><span aria-label="0 replies" class="social-embed-meta">💬 0</span><span aria-label="4 reposts" class="social-embed-meta">🔁 4</span><time datetime="2020-08-17T13:00:09.000Z" itemprop="datePublished">13:00 - Mon 17 August 2020</time></a></footer></blockquote><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://twitter.com/edent" class="social-embed-user" itemprop="url"><img class="social-embed-avatar social-embed-avatar-circle" src="data:image/webp;base64,UklGRkgBAABXRUJQVlA4IDwBAACQCACdASowADAAPrVQn0ynJCKiJyto4BaJaQAIIsx4Au9dhDqVA1i1RoRTO7nbdyy03nM5FhvV62goUj37tuxqpfpPeTBZvrJ78w0qAAD+/hVyFHvYXIrMCjny0z7wqsB9/QE08xls/AQdXJFX0adG9lISsm6kV96J5FINBFXzHwfzMCr4N6r3z5/Aa/wfEoVGX3H976she3jyS8RqJv7Jw7bOxoTSPlu4gNbfXYZ9TnbdQ0MNnMObyaRQLIu556jIj03zfJrVgqRM8GPwRoWb1M9AfzFe6Mtg13uEIqrTHmiuBpH+bTVB5EEQ3uby0C//XOAPJOFv4QV8RZDPQd517Khyba8Jlr97j2kIBJD9K3mbOHSHiQDasj6Y3forATbIg4QZHxWnCeqqMkVYfUAivuL0L/68mMnagAAA" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">Terence Eden is on Mastodon</p>@edent</div></a><img class="social-embed-logo" alt="Twitter" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%0Aaria-label%3D%22Twitter%22%20role%3D%22img%22%0AviewBox%3D%220%200%20512%20512%22%3E%3Cpath%0Ad%3D%22m0%200H512V512H0%22%0Afill%3D%22%23fff%22%2F%3E%3Cpath%20fill%3D%22%231d9bf0%22%20d%3D%22m458%20140q-23%2010-45%2012%2025-15%2034-43-24%2014-50%2019a79%2079%200%2000-135%2072q-101-7-163-83a80%2080%200%200024%20106q-17%200-36-10s-3%2062%2064%2079q-19%205-36%201s15%2053%2074%2055q-50%2040-117%2033a224%20224%200%2000346-200q23-16%2040-41%22%2F%3E%3C%2Fsvg%3E"></header><section class="social-embed-text" itemprop="articleBody"><small class="social-embed-reply"><a href="https://twitter.com/edent/status/1295344665101766656">Replying to @edent</a></small>The previous Tweet in this thread contains the SHA256 hash of *this* Tweet. This message was written on 2020-08-17.</section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/edent/status/1297473659880091650"><span aria-label="8 likes" class="social-embed-meta">❤️ 8</span><span aria-label="1 replies" class="social-embed-meta">💬 1</span><span aria-label="0 reposts" class="social-embed-meta">🔁 0</span><time datetime="2020-08-23T10:00:01.000Z" itemprop="datePublished">10:00 - Sun 23 August 2020</time></a></footer></blockquote>

<h2 id="is-this-useful"><a href="https://shkspr.mobi/blog/2020/08/staking-claims-with-scheduled-tweets/#is-this-useful">Is this useful?</a></h2>

<p>Probably not <em>very</em> useful. Here's a couple of ideas.</p>

<p>Post your prediction for something, without influencing it. For example, the results of an election.</p>

<p>A sort of <a href="https://en.wikipedia.org/wiki/Dead_man%27s_switch#Software">Dead Man's Switch</a> - a message to be sent when you're not available.</p>

<p>It isn't foolproof.</p>

<p>It's <em>really</em> easy to screw up a hash. My first couple of experiments didn't work because of errant whitespaces.</p>

<p>Modern hashes like SHA256 are <em>probably</em> resistant to collisions in Twitter's limited message space.</p>

<p>And, of course, a person can post two hashes - for contradictory messages - and only publish replies one of them.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=36354&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2020/08/staking-claims-with-scheduled-tweets/feed/</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Why API responses should be signed]]></title>
		<link>https://shkspr.mobi/blog/2020/01/why-api-responses-should-be-signed/</link>
					<comments>https://shkspr.mobi/blog/2020/01/why-api-responses-should-be-signed/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 17 Jan 2020 12:33:29 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[cryptography]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=33170</guid>

					<description><![CDATA[I&#039;m going to start this discussion with the why and then move on to the how. Let&#039;s begin with a couple of user stories.  As the recipient of some data, I want to verify that it hasn&#039;t been tampered with.  and  As the recipient of some data, I want to verify who originally published it.  Here&#039;s why I think this is important. We are in an era of fake news. A screenshot can be easily altered. A…]]></description>
										<content:encoded><![CDATA[<p>I'm going to start this discussion with the <em>why</em> and then move on to the <em>how</em>. Let's begin with a couple of user stories.</p>

<blockquote><p>As the recipient of some data, I want to verify that it hasn't been tampered with.</p></blockquote>

<p>and</p>

<blockquote><p>As the recipient of some data, I want to verify who originally published it.</p></blockquote>

<p>Here's why I think this is important. We are in an era of fake news. A screenshot can be easily altered. A webpage is trivial to edit. But data should be provably true.</p>

<p>Recently, a prominent person's private Twitter messages were leaked. It was presented as a series of JSON files ostensibly directly from the API. But, of course, there was no way to prove the data-dump didn't contain misinformation.</p>

<p>If I call <code>https://api.example.com/?id=123</code> myself, then I can be reasonably sure that the data has come from the server unaltered.</p>

<p>But what if someone emails me a JSON file? Or someone re-hosts an XML dump? Or a hacker claims to have uncovered proof of...?</p>

<p>As data-journalism gathers pace, it's vital to be able to see whether data is authentic.</p>

<p>Suppose you see a news site claiming that your favourite sports star endorses the opposing team. They have an image of a tweet. But you wouldn't trust an image of a website (I hope) without a checking a live link. Right?</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2019/11/Screenshot_2019-11-21-VicGovAu-on-Twitter-Boost-Your-Business-vouchers-of-up-to-25000-are-available-to-help-Social-Enterp....png" alt="Fake tweet showing the Victoria Government announcing I am King of Australia." width="658" height="190" class="aligncenter size-full wp-image-33171">

<p>But in the data world, we get no such assurances.</p>

<p>Here's data from a Tweet I've just faked:</p>

<pre><code class="language-_">{
  &amp;quot;created_at&amp;quot;: &amp;quot;Wed Oct 10 20:19:24 +0000 2018&amp;quot;,
  &amp;quot;id&amp;quot;: 105011862119892123,
  &amp;quot;text&amp;quot;: &amp;quot;Terence Eden is now officially the King of Australia&amp;quot;,
  &amp;quot;user&amp;quot;: {
    &amp;quot;id&amp;quot;: 6253282,
    &amp;quot;id_str&amp;quot;: &amp;quot;6253282&amp;quot;,
    &amp;quot;name&amp;quot;: &amp;quot;Australian Government&amp;quot;,
    &amp;quot;screen_name&amp;quot;: &amp;quot;AusGovOfficia1&amp;quot;,
</code></pre>

<p>I've just made that up. But you've got no way to prove that it did <em>not</em> come from Twitter.  Perhaps it <em>was</em> a real Tweet which was subsequently deleted?</p>

<h2 id="where-this-matters"><a href="https://shkspr.mobi/blog/2020/01/why-api-responses-should-be-signed/#where-this-matters">Where this matters</a></h2>

<p>Do you rely on data for your job? If someone gives you a scrap of data claiming to be from a website, how can you prove it is authentic?</p>

<p>Perhaps a Police API tells you what the crime rate is, or a betting API tells you what the odds are, or a news API tells you who was convicted of a crime. Or a source leaks information from a social network. How can you prove that the data is authentic and unaltered? Or someone else could present false data as coming from a trusted source. Or a trusted source could publish fake data and later claim they didn't.</p>

<p>Here's the end result that I want.</p>

<ul>
<li>Given a piece of data,</li>
<li>Prove that where it came from and,</li>
<li>Prove that it hasn't been altered.</li>
</ul>

<h2 id="how-to-do-it"><a href="https://shkspr.mobi/blog/2020/01/why-api-responses-should-be-signed/#how-to-do-it">How to do it</a></h2>

<p>This is where I get stumped. I can clearly see the need for this. Disinformation is an attack on civilisation. But I can't see how to do it in a seamless and easy to understand way.</p>

<p>There have been <a href="https://ordina-jworks.github.io/security/2016/03/12/Digitally-signing-your-JSON-documents.html">lots of proposals for how to do this</a>.</p>

<p>I think it boils down to three distinct design choices.</p>

<ol>
<li>Keep the signature and the message separate.</li>
<li>Include the signature in the message.</li>
<li>Only sign part of the message.</li>
</ol>

<h3 id="separation-of-powers"><a href="https://shkspr.mobi/blog/2020/01/why-api-responses-should-be-signed/#separation-of-powers">Separation of Powers</a></h3>

<p>The first is conceptually easiest.</p>

<ul>
<li>The API call <code>example.com/?id=123</code> returns some JSON containing the data requested.</li>
<li>The API call <code>example.com/?id=123&amp;signed=true</code> returns the signature <em>only</em>.</li>
</ul>

<p>It relies on a few assumptions. Mostly that a <code>GET</code> operation is <a href="https://en.wikipedia.org/wiki/Immutable_object">Immutable</a> in terms of what it returns. That is, the data returned from a query is always the same.</p>

<p>It reduces complexity for the server and client. If the client doesn't care about verification, the server doesn't have to calculate it.</p>

<p>It might be complicated to store the information. You would need to keep <code>response.json</code> and <code>response.signed.json</code> as separate files.</p>

<p>It might be fragile. If a single bit or byte of the data is altered - say tabs get converted to spaces - then the signature could become invalid.</p>

<p>If you want someone to verify an API response, they need two separate files and need to load them in the right order into any verification system.  Again, not an impossible task, but might make things more complicated than necessary.</p>

<h3 id="inclusivity"><a href="https://shkspr.mobi/blog/2020/01/why-api-responses-should-be-signed/#inclusivity">Inclusivity</a></h3>

<p>Does the set of all sets include itself? This isn't just a philosophical problem. If a signature is included in a response, does the signing process have to take account of the signature?</p>

<p>The usual way around this is to encode the result first. So, imagine your API response was BASE64 encoded and then signed. It might look like this:</p>

<pre><code class="language-_">{
   &amp;quot;response&amp;quot;: &amp;quot;data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D...&amp;quot;,
   &amp;quot;signature&amp;quot;: &amp;quot;0f60066673e0de....&amp;quot;
}
</code></pre>

<p>That keeps the document and signature together, but does have some disadvantages.
It loses the human-readable nature of the response. It also means that your code has to BASE64 decode the response before interpreting it. Both of those are annoying for debuggers - but not critical issues.</p>

<h3 id="partial"><a href="https://shkspr.mobi/blog/2020/01/why-api-responses-should-be-signed/#partial">Partial</a></h3>

<p>What if we only sign the critical parts of the response, rather than all the metadata? This is perhaps the easiest to implement, but has some drawbacks.</p>

<pre><code class="language-_">{
  &amp;quot;created_at&amp;quot;: &amp;quot;Wed Oct 10 20:19:24 +0000 2018&amp;quot;,
  &amp;quot;id&amp;quot;: 105011862119892123,
  &amp;quot;text&amp;quot;: &amp;quot;Terence Eden is now officially the King of Australia&amp;quot;,
  &amp;quot;text-sig&amp;quot;: &amp;quot;0f60066673e0de....&amp;quot;,
  ...
</code></pre>

<p>That is, only sign the text. Or perhaps text + ID. Or any useful subset of the API response. It's simple to parse for humans and computers. But the metadata might be a crucial part of the information we want to verify. Knowing the date something was published, for example, could be as important as the content itself.</p>

<h2 id="put-it-all-on-the-blockchain"><a href="https://shkspr.mobi/blog/2020/01/why-api-responses-should-be-signed/#put-it-all-on-the-blockchain">Put it all on the blockchain!!!!!</a></h2>

<p>No.</p>

<p>Well... OK. Maybe this is a use for a Merkle Tree or similar. If every API response has an ID, then a cryptographic hash <em>could</em> be appended to a public ledger.  But that has all the disadvantages of the previous schemes without any real benefit.</p>

<h2 id="security-is-hard"><a href="https://shkspr.mobi/blog/2020/01/why-api-responses-should-be-signed/#security-is-hard">Security is hard</a></h2>

<p>The problem with all of the above approaches is that the API provider needs to safely and securely manage cryptographic keys. That's expensive and complicated. If an attacker got access to the keys, they could issue fake statements.</p>

<p>But, the good news is that the tech tech is here and it works. <a href="https://jose.readthedocs.io/en/latest/">JOSE</a> is a suite of specifications - including <a href="https://jwt.io/">JSON Web Tokens</a> - which are well used across the Internet. Mostly for signing OAuth logins.</p>

<p>So, can we use it?</p>

<h2 id="will-anyone-care"><a href="https://shkspr.mobi/blog/2020/01/why-api-responses-should-be-signed/#will-anyone-care">Will anyone care?</a></h2>

<p>I suppose this is the crucial question. Right now I can easily fake a screenshot and the majority of people won't even look to see if the information is true - no matter how incredible the claim is.</p>

<p>But we need to build a better foundation for the future. One where information brokers can say "I have proof that this exact data came from this specific website at this precise time."</p>

<p>We have to believe that truth and trust are important.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=33170&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2020/01/why-api-responses-should-be-signed/feed/</wfw:commentRss>
			<slash:comments>35</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Things For Which Cryptographic Signing Would Be Useful]]></title>
		<link>https://shkspr.mobi/blog/2018/05/things-for-which-cryptographic-signing-would-be-useful/</link>
					<comments>https://shkspr.mobi/blog/2018/05/things-for-which-cryptographic-signing-would-be-useful/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 27 May 2018 14:26:30 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[blockchain]]></category>
		<category><![CDATA[cryptography]]></category>
		<category><![CDATA[pgp]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=29644</guid>

					<description><![CDATA[Every time someone mentions BlockChain, I have to down my drink. Those are the rules.  You see, most uses of Distributed Ledger are really just a way to get people interested in cryptographic signing. There&#039;s lots of money and attention flowing to projects which have no need to publish to an energy-inefficient global database.  They would be better suited to public-key cryptography.  Let me give…]]></description>
										<content:encoded><![CDATA[<p>Every time someone mentions BlockChain, I have to down my drink. Those are the rules.</p>

<p>You see, <em>most</em> uses of Distributed Ledger are really just a way to get people interested in cryptographic signing. There's lots of money and attention flowing to projects which have no need to publish to an energy-inefficient global database.  They would be better suited to public-key cryptography.</p>

<p>Let me give you an example, then we'll dive in to some details.</p>

<p>Recently, I needed to prove that I went to University.  How did I do it?  I rang up the alumni department, paid for a copy of my transcript, they posted it to me printed on high quality paper, I scanned it and emailed it to the person who wanted it.  I've no idea if anyone checked if it was legitimate.</p>

<p>This is fragile nonsense!</p>

<p>In an Internet-connected world, sending forgeable bits of paper around is just daft.  All the university need to do was publish something like this:</p>

<pre><code class="language-text">-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

I confirm that Terence Eden studied at Example University 1998-2002 
earning a 2.1 in Advanced Drinking
-----BEGIN PGP SIGNATURE-----

wsFcBAEBCAAQBQJbCnsECRAADQX2QFV8YgAA6swQAHTZ2jtR2x5bK1oX+shZK0SM
1EXIWvBN0ECzeFsY86AtL4bd9qTKwpjgWPsPN4NSh7Rpg2xvgLTKIdFWSsMsWTrw
QPtKiaFbYa/1Cah8uBV6rSJOodKXRGveni9vojpjT1fUZ0APhzhLbki6mvfwMquq
IWQwqgEAp4odp8Yv98sIXvSKlc/f7Y4XDYmCyapPaoNDOpzXsROSuQIqaLqrTrjf
D/U+fTQrKSx9LqsW7KLgb3dfBPXVOjBmFdCn+iNJjVMF1GLNk0fjWsUu3oy4vvrX
9SCoM5TzCxBRdGZpVmrvOSr0hg5Rmx7VRXfVhUj4/kfaM2s0NWxGr0rBMzRYsl1o
OLDplZqhYxcHI3XivfFTAwZY7UZvCPnNJCQCFDtpFnRgdpq97Lynj2cF6u9gU/gL
Kb3cTeut2uHtMJAG7DN3tpQMLWDrbX96eXDB64zD73gfOyXrbjivSStSlCC8VrmU
njkc3393qiYW9AF9zKtYo8x/9n0/WhO6kSW0Mt/V6LdIhqFVqHyWZqh6vRAtfNIf
W80OR/dKtXSBYZgmg72/pgZBNeBne9lL+Nd4I/MlVzmC96fI+jkoeXO0cZanXWRm
2JoW+7R8I8de4PS9fjTMl8fVgEAsWFXjMUas0fJu4POxQDoSIaSEGxYJvTc01lGS
tzdqLOC6zBKeS6ndUFdH
=kSYS
-----END PGP SIGNATURE-----
</code></pre>

<p>Now, perhaps it needs to be cross-signed with a <a href="https://en.wikipedia.org/wiki/Trusted_timestamping">Trusted Timestamp Server</a> or possibly incorporating my signing key as well - but the basics are there.  Either stick that up on a website, or email it to anyone who wants to check my qualifications.</p>

<p>No Merkle-Trees or paying vastly inflated transaction fees.  Just a document which has been signed by the issuer and can be validated as legitimate.  Why do you need anything else?  Public key signature systems are quick, simple, and cheap.  Pick any three!</p>

<p>The best part is... this technology is <em>already</em> in use!  If you have a modern passport, it contains an RFID chip which holds data about you.  These <a href="https://www.researchgate.net/figure/Overview-of-data-signed-and-stored-in-e-passports-chip_fig1_221406395">biometric data are cryptographically signed</a>.  It uses a PKI solution to ensure no one has tampered with the information.</p>

<h2 id="potential-uses"><a href="https://shkspr.mobi/blog/2018/05/things-for-which-cryptographic-signing-would-be-useful/#potential-uses">Potential Uses</a></h2>

<p>Feel free to add more in the comments section.</p>

<ul>
<li>Qualifications

<ul>
<li>Example University confirms that I have this qualification.</li>
</ul></li>
<li>Work history / employment references

<ul>
<li>Big Corp verifies that I was employed from these dates in this position.</li>
</ul></li>
<li>Customer verification

<ul>
<li>Energy Company confirms I am a current customer.</li>
</ul></li>
<li>Nuclear Launch Codes

<ul>
<li>This order is legitimate and has been cross-signed by at least 3 members of the of the command chain.</li>
</ul></li>
<li>Medicine Licencing

<ul>
<li>This drug is approved by this regulator in this territory.</li>
</ul></li>
<li>Legislation

<ul>
<li>This amendment to that law was published by this legislature.</li>
</ul></li>
<li>Prison sentences

<ul>
<li>This Judge issued this sentence on that person.</li>
</ul></li>
<li>Food

<ul>
<li>The farm that provided this food has been certified as an organic farm by this inspector.</li>
</ul></li>
<li>Statements

<ul>
<li>This document was written by that author and published by that organisation.</li>
</ul></li>
<li>Prescriptions

<ul>
<li>This doctor from that surgery prescribes these drugs to that patient.</li>
</ul></li>
<li>Credit History

<ul>
<li>This mortgage has been provided to that person and they have paid off 10% of it.</li>
</ul></li>
</ul>

<h2 id="downsides"><a href="https://shkspr.mobi/blog/2018/05/things-for-which-cryptographic-signing-would-be-useful/#downsides">Downsides</a></h2>

<p>This is a technological solution to the human problem of trust.</p>

<p>Firstly, there's no guarantee that people will <em>actually</em> verify the message - as this XKCD Cartoon puts so succinctly.</p>

<p><a href="https://xkcd.com/1181/"><img src="https://shkspr.mobi/blog/wp-content/uploads/2018/05/pgp.png" alt="How to use PGP to verify that an email is authentic: Look for this text at the top  [In mail header, light grey.] Reply [Highlighted, with arrow pointing to it from the text &quot;Look for this text at the top&quot; above.]     -----BEGIN PGP SIGNED MESSAGE-----     [In mail message, light grey.]     HASH: SHA256     Hey,     First of all, thanks for taking care of      [After mail message.]     If it's there, the email is probably fine." width="588" height="458" class="aligncenter size-full wp-image-29647"></a></p>

<p>Secondly, there's no guarantee that people will actually have <em>the software</em> to verify the message - <a href="https://www.wired.com/story/us-border-patrol-hasnt-validated-e-passport-data-for-years/">US Border Patrol are <em>still</em> unable to verify e-Passports</a>.</p>

<p>Thirdly, there's no guarantee that keys won't be stolen or broken in the future.  One (small) advantage of a Distributed Ledger is that you can verify <em>when</em> a claim was published.  Assuming <a href="https://www.multichain.com/blog/2017/05/blockchain-immutability-myth/">a malicious party hasn't found yet another weakness in the technology</a>.</p>

<p>Fourthly, a claim once issued is hard to revoke.  If my university discovers I cheated in an exam, of if a company mistakenly says I am their customer - how do you issue a notice of revocation?  If a corrupt employee is bribed to make a fake claim about me, it could be impossible to backtrack.
Again, this problem isn't solved by putting claims on a BlockChain.</p>

<p>Finally, there's no guarantee that people will <em>understand</em> what verification means.</p>

<p>Just because I present you evidence that "Terence Eden" has a qualification, that doesn't mean that I <em>am</em> Terence Eden. Or even the <em>same</em> Terence Eden mentioned.</p>

<p>Just because the label on a box of baby-milk claims that the supply chain has been verified, it does not mean that the contents are unadulterated with plastic.</p>

<p>Which leads us back to the start.  We can make verifiable claims - but will anyone care?  In a world where <a href="https://shkspr.mobi/blog/2018/04/what-is-a-signature/">a scrawled ink signature is seen as the ultimate proof of truth</a> and <a href="https://shkspr.mobi/blog/2018/04/tools-to-defeat-fake-news-reverse-image-search/">easily debunked forgeries are treated as genuine news</a> how do we convince people to care about verification?</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=29644&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2018/05/things-for-which-cryptographic-signing-would-be-useful/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
