<?xml version="1.0" encoding="UTF-8"?><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/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>security &#8211; Gareth Klose</title>
	<atom:link href="https://garethklose.com/tag/security/feed" rel="self" type="application/rss+xml" />
	<link>https://garethklose.com</link>
	<description>writes about technology, television and travelling</description>
	<lastBuildDate>Thu, 17 Aug 2023 13:56:54 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.7.5</generator>
<site xmlns="com-wordpress:feed-additions:1">27787817</site>	<item>
		<title>State-Issued Identifiers aren&#8217;t generally good passwords</title>
		<link>https://garethklose.com/2023/08/state-issued-identifiers-arent-generally-good-passwords</link>
		
		<dc:creator><![CDATA[gareth]]></dc:creator>
		<pubDate>Fri, 11 Aug 2023 19:15:47 +0000</pubDate>
				<category><![CDATA[Rights and Legal]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[gdpr]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[spam]]></category>
		<guid isPermaLink="false">https://garethklose.com/?p=14803</guid>

					<description><![CDATA[Just because a number is long, doesn't mean that it's secure...]]></description>
										<content:encoded><![CDATA[
<p>For many years, despite repeated requests, a South African bank has been sending me bank statements.</p>



<p>The thing is that I don&#8217;t live in South Africa, have never visited, nor banked there. But I do have a particularly &#8220;good&#8221; email address that gets a lot of misdirected emails&#8230; I usually don&#8217;t read them, but this week I did, as I replied for the latest attempt of &#8220;please stop&#8221;.</p>



<p>The email included a PDF statement, password protected with the South African ID number of the customer. I suspect that protection is why the service centre seem so unbothered by the repeated requests to stop this information.</p>



<p>A few years back, I got <em>very</em> embedded in PII/GDPR. We were designing a data warehouse setup that allowed analysis of user activity, while protecting privacy, and enabling easier compliance with GDPR deletion requests. There was discussion about the feasibility of SHA2 hash reversal&#8230; and we took a lot of time to communicate the infeasibility with the legal team.</p>



<p>So this week, I started to wonder: If I were a bad actor (which I am not), could I feasibly crack this ID with some Python?</p>



<h2 class="wp-block-heading"><strong>What&#8217;s the challenge?</strong></h2>



<p>There are three sets to consider in this:</p>



<ul class="wp-block-list">
<li>The <strong>Absolute</strong> Keyspace: without any knowledge of the identifiers, the number of combinations?</li>



<li>The <strong>Available</strong> Keyspace: if the ID has constraints, how many valid combinations are there?</li>



<li>The <strong>Effective</strong> Keyspace: if we know anything more, how many combinations are applicable?</li>
</ul>



<p>A good security identifier should make discerning the differences between these difficult: it should involve a reasonable amount of calculation before it becomes obvious that an ID is valid, and correct.</p>



<h3 class="wp-block-heading">What do we know?</h3>



<p>South African ID Numbers are 13 decimal digits.</p>



<p>A single decimal can be 0-9, ten in total, and so each digit has a a cardinality of 10.</p>



<p>(Cardinality being the maths word for &#8216;number of choices&#8217; in a set)</p>



<p>We can use this information to calculate the absolute keyspace:</p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true"><pre>\begin{align*}
Keyspace_{Absolute} = &amp;10 \times 10 \times 10 \times 10 \times 10 \\
&amp; \times 10 \times 10 \times 10 \times 10 \\
&amp; \times 10 \times 10 \times 10 \times 10  \\
 = &amp; 10^{13}\\ 
 = &amp; 10,000,000,000,000
\end{align*}</pre></div>



<p>Since this work was derived in a Jupyter notebook, I&#8217;ll also include some python as we go along&#8230;</p>


<div class="wp-block-ub-content-toggle" id="ub-content-toggle-06756a9c-e552-4378-b630-6a5e096be593" data-mobilecollapse="true" data-desktopcollapse="true">
<div class="wp-block-ub-content-toggle-accordion" id="ub-content-toggle-panel-block-">
                <div class="wp-block-ub-content-toggle-accordion-title-wrap"" aria-controls="ub-content-toggle-panel-0-06756a9c-e552-4378-b630-6a5e096be593" tabindex="0">
                    <p class="wp-block-ub-content-toggle-accordion-title ub-content-toggle-title-06756a9c-e552-4378-b630-6a5e096be593">Python Code for absolute keyspace</p><div class="wp-block-ub-content-toggle-accordion-toggle-wrap right"><span class="wp-block-ub-content-toggle-accordion-state-indicator wp-block-ub-chevron-down"></span>
                    </div></div><div role="region" aria-expanded="false" class="wp-block-ub-content-toggle-accordion-content-wrap ub-hide" id="ub-content-toggle-panel-0-06756a9c-e552-4378-b630-6a5e096be593">

<pre class="wp-block-code"><code lang="python" class="language-python">number_of_digits = 13
keyspace_absolute = 10 ** number_of_digits
print(f"Number of combinations: {keyspace_absolute:,}")</code></pre>

</div></div>
</div>


<pre class="wp-block-code"><code lang="python" class="language-python">Number of combinations: 10,000,000,000,000</code></pre>



<h2 class="wp-block-heading">Is this feasible?</h2>



<p>So without knowing anything about the ID, there are 10 trillion combinations to check.</p>



<p>Python can attempt to open a PDF with a password around 150 times per second. This would be our basic implementation.</p>



<p>More specialised tools like <a href="https://www.openwall.com/john/">John the Ripper</a> raise that rate 4,500 per second, that&#8217;s around 30 times faster.</p>



<p>We&#8217;ll put these into a summary function, as we&#8217;ll be calling this a few times.</p>


<div class="wp-block-ub-content-toggle" id="ub-content-toggle-46c19f05-4482-439b-9436-5da397f0fb50" data-mobilecollapse="true" data-desktopcollapse="true">
<div class="wp-block-ub-content-toggle-accordion" id="ub-content-toggle-panel-block-">
                <div class="wp-block-ub-content-toggle-accordion-title-wrap"" aria-controls="ub-content-toggle-panel-0-46c19f05-4482-439b-9436-5da397f0fb50" tabindex="0">
                    <p class="wp-block-ub-content-toggle-accordion-title ub-content-toggle-title-46c19f05-4482-439b-9436-5da397f0fb50">Python for Summary Function</p><div class="wp-block-ub-content-toggle-accordion-toggle-wrap right"><span class="wp-block-ub-content-toggle-accordion-state-indicator wp-block-ub-chevron-down"></span>
                    </div></div><div role="region" aria-expanded="false" class="wp-block-ub-content-toggle-accordion-content-wrap ub-hide" id="ub-content-toggle-panel-0-46c19f05-4482-439b-9436-5da397f0fb50">

<pre class="wp-block-code"><code lang="python" class="language-python">test_rate_slow = 150
test_rate_fast = 4500
def summary_to_brute_force(combinations):
    hours_to_test_slow = (combinations / test_rate_slow) / 60 / 60
    hours_to_test_fast = (combinations / test_rate_fast) / 60 / 60
    return f"At slow rate: {hours_to_test_slow:,.2f} hours, or: {hours_to_test_slow / 24:,.2f} days" + \
           f"\nAt optimised: {hours_to_test_fast:,.2f} hours, or: {hours_to_test_fast / 24:,.3f} days" </code></pre>

</div></div>
</div>


<pre class="wp-block-code"><code lang="python" class="language-python">print(summary_to_brute_force(keyspace_absolute))
At slow rate: 18,518,518.52 hours, or: 771,604.94 days
At optimised: 617,283.95 hours, or: 25,720.165 days</code></pre>



<p>At this stage, it would not be worth the cost to brute-force this.</p>



<p>The information in the ID, or the document, is not valuable enough.</p>



<h2 class="wp-block-heading">Scoping the &#8220;Available Keyspace&#8221;</h2>



<p>The South African ID format is described <a href="https://mybroadband.co.za/news/security/303812-what-your-south-african-id-number-means-and-what-it-reveals-about-you.html">here</a> and <a href="https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/South-Africa-TIN.pdf">this OECD PDF</a>.</p>



<p>The format is&nbsp;<code>YYMMDDSSSSCAZ</code>:</p>



<ul class="wp-block-list">
<li><code>YYMMDD</code>&nbsp;is the date of birth</li>



<li><code>SSSS</code> separating people born on the same day
<ul class="wp-block-list">
<li>Female entries start <code>0-4</code>, males entries start <code>5-9</code></li>
</ul>
</li>



<li><code>C</code>&nbsp;represents citizenship status</li>



<li><code>A</code>&nbsp;was previously used to represent race, but is now unspecified</li>



<li><code>Z</code>&nbsp;is a checksum digit, using the Luhn algorithm</li>
</ul>



<h2 class="wp-block-heading" id="How-does-this-help-us?">How does this help us?</h2>



<p>The&nbsp;<code>Z</code>&nbsp;check digit reduces the key space by a factor of 10: we &#8220;only&#8221; have to brute-force for the first 12 digits, and calculate the 13th.</p>



<p>Since&nbsp;<code>A</code>&nbsp;is unspecified, we will leave its cardinality unchanged at 10.</p>



<p>The&nbsp;<code>C</code>&nbsp;citizenship status can be 0, 1, or 2. This digit now has cardinality of 3 instead of 10.</p>



<h3 class="wp-block-heading" id="Dates">Dates</h3>



<p>The&nbsp;<code>YYMMDD</code>&nbsp;digits are dates, these have constraints:</p>



<ul class="wp-block-list">
<li>Years are from 00-99</li>



<li>Months are from 01-12</li>



<li>Days are from 01-31</li>
</ul>



<p>If we just consider those digits individually, we can calculate the cardinality like this:</p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true"><pre>\begin{align*}
dates &amp;= 10 \times 10 \times 2 \times 10 \times 4 \times 10 \\
&amp;= 80,000
\end{align*}</pre></div>



<p>But that&#8217;s going to consider many impossible days: month 19 doesn&#8217;t exist, nor does day 35.</p>



<p>So we could just consider these 6 digits as a combined date field, and get a more useful answer:</p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true"><pre>\begin{align*}
dates &amp;= years \times days \\
&amp; = 100 \times 365 \\
&amp;= 36,500
\end{align*}</pre></div>



<p>(Yes, I am ignoring leap-years in this calculation&#8230; they&#8217;re not material to this calculation)</p>



<p>Our new understanding of the ID number format comes together, and we can compare the Absolute with the Available keyspaces:</p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true"><pre>\begin{align*}
Keyspace_{Absolute} = &amp;10^{13}\\
= &amp;10,000,000,000,000 \\
Keyspace_{Available} = &amp;valid\_dates \times serial\_numbers \\
&amp; \times citizenship\_status \times A\_column \\
= &amp;36,500 \times 10,000 \times 3 \times 10 \\
= &amp;10,950,000,000
\end{align*}</pre></div>



<p>So even without any knowledge of the target, only 0.1095% of the original key space needs to be searched.</p>


<div class="wp-block-ub-content-toggle" id="ub-content-toggle-03fbf3c8-52f0-4334-81ac-800ae8202400" data-mobilecollapse="true" data-desktopcollapse="true">
<div class="wp-block-ub-content-toggle-accordion" id="ub-content-toggle-panel-block-">
                <div class="wp-block-ub-content-toggle-accordion-title-wrap"" aria-controls="ub-content-toggle-panel-0-03fbf3c8-52f0-4334-81ac-800ae8202400" tabindex="0">
                    <p class="wp-block-ub-content-toggle-accordion-title ub-content-toggle-title-03fbf3c8-52f0-4334-81ac-800ae8202400">Python for Available keyspace</p><div class="wp-block-ub-content-toggle-accordion-toggle-wrap right"><span class="wp-block-ub-content-toggle-accordion-state-indicator wp-block-ub-chevron-down"></span>
                    </div></div><div role="region" aria-expanded="false" class="wp-block-ub-content-toggle-accordion-content-wrap ub-hide" id="ub-content-toggle-panel-0-03fbf3c8-52f0-4334-81ac-800ae8202400">

<pre class="wp-block-code"><code lang="python" class="language-python">cardinality_of_birthdays = 100 * 365 # we're ignoring leap years
cardinality_of_serial_numbers = 10000
cardinality_of_citizenship_states = 3
cardinality_of_the_a_digit = 10
keyspace_available = cardinality_of_birthdays * cardinality_of_serial_numbers * cardinality_of_citizenship_states * cardinality_of_the_a_digit
print(f"Number of valid ID numbers: {keyspace_available:,}")
print(summary_to_brute_force(keyspace_available))
 </code></pre>

</div></div>
</div>


<pre class="wp-block-code"><code lang="python" class="language-python">Number of valid ID numbers: 10,950,000,000
At slow rate: 20,277.78 hours, or: 844.91 days
At optimised: 675.93 hours, or: 28.164 days</code></pre>



<p>One month with optimised checking could be feasible, especially if you rented some machines&#8230; but can we do better?</p>



<h2 class="wp-block-heading">What&#8217;s the Effective Keyspace?</h2>



<figure class="wp-block-image size-full"><a href="https://cdn.garethklose.com/wp-content/uploads/2023/08/letter.png"><img fetchpriority="high" decoding="async" width="1392" height="1086" data-attachment-id="14817" data-permalink="https://garethklose.com/2023/08/state-issued-identifiers-arent-generally-good-passwords/letter" data-orig-file="https://cdn.garethklose.com/wp-content/uploads/2023/08/letter.png" data-orig-size="1392,1086" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Email Recreation" data-image-description="&lt;p&gt;The format of the email received, showing the presence of Salutation, name, and the provided ID suffix.&lt;/p&gt;
" data-image-caption="&lt;p&gt;A recreation of the email sent by the bank&lt;/p&gt;
" data-medium-file="https://cdn.garethklose.com/wp-content/uploads/2023/08/letter.png" data-large-file="https://cdn.garethklose.com/wp-content/uploads/2023/08/letter.png" src="https://cdn.garethklose.com/wp-content/uploads/2023/08/letter.png" alt="A badly recreated email from a bank, with a banner &quot;your electronic statement&quot;. The intro reads: Dear Mr G. Customer Please Find Attached your Statement for May • Information that only you will know is displayed in the eStatement verification block. This is done so you can be sure your statement is from BANKCO. • You will be required to enter the 13 digits of your identity number to view your statement. There is an additional box: Verification Info account number: *******5678 ID Number: *********1234" class="wp-image-14817"/></a><figcaption class="wp-element-caption">A recreation of the email sent by the bank</figcaption></figure>



<p>Revisiting the email, it contains some info I&#8217;ve ignored until now:</p>



<ul class="wp-block-list">
<li>The last 4 digits of the ID as verification</li>



<li>The recipient is addressed as &#8216;Mr Customer&#8217;</li>
</ul>



<p>Going back to the format&nbsp;<code>YYMMDDSSSSCAZ</code>.</p>



<p>We know the values for&nbsp;<code>C</code>&nbsp;&amp;&nbsp;<code>A</code>, so those now have cardinality of 1.</p>



<ul class="wp-block-list">
<li><code>C</code> &#8216;only&#8217; had a cardinality of 3, so that&#8217;s excludes 67% of possibilities</li>



<li><code>A</code> had a cardinality of 10, so that excludes of 90% of possibilities</li>
</ul>



<p>These combine however, so the remaining amount from knowing <code>C</code> &amp; <code>A</code> is: <span class="katex-eq" data-katex-display="false">\frac{1}{3} \times \frac{1}{10} = \frac{1}{30}</span></p>



<p>Let&#8217;s reconsider the&nbsp;<code>SSSS</code>&nbsp;block: which we&#8217;ll refer to as <code>S1</code>, <code>S2</code>, <code>S3</code>, <code>S4</code>.</p>



<ul class="wp-block-list">
<li>Since our ID is male we know that the <code>S1</code> must be 5/6/7/8/9, so cardinality of that digit is now 5</li>



<li>We know <code>S4</code>, so it has cardinality of 1</li>
</ul>



<p>Again these combine, so the total remaining is: <span class="katex-eq" data-katex-display="false">\frac{5}{10} \times \frac{1}{10} = \frac{1}{20}</span></p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true"><pre>\begin{align*}
SSSS_{possible} &amp;= 10^{4} = 10,000 \\
SSSS_{from\_email} &amp;= 5 \times 10 \times 10 \times 1 \\
&amp;= 500
\end{align*}</pre></div>



<p>Checking in the formula again:</p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true"><pre>\begin{align*}
Keyspace_{Absolute} = &amp;10,000,000,000,000 \\
Keyspace_{Available} = &amp;10,950,000,000 \\
Keyspace_{Effective} = &amp;valid\_dates \times serial\_numbers \\
&amp; \times citizenship\_status \times A\_column \\
= &amp;36,500 \times 500 \times 1 \times 1 \\
= &amp;18,250,000
\end{align*}</pre></div>



<p>We&#8217;re now down to 18.25 million possible keys to check.</p>


<div class="wp-block-ub-content-toggle" id="ub-content-toggle-7b998fbf-6273-4d5a-af56-fdec57f13276" data-mobilecollapse="true" data-desktopcollapse="true">
<div class="wp-block-ub-content-toggle-accordion" id="ub-content-toggle-panel-block-">
                <div class="wp-block-ub-content-toggle-accordion-title-wrap"" aria-controls="ub-content-toggle-panel-0-7b998fbf-6273-4d5a-af56-fdec57f13276" tabindex="0">
                    <p class="wp-block-ub-content-toggle-accordion-title ub-content-toggle-title-7b998fbf-6273-4d5a-af56-fdec57f13276">Python for effective keyspace</p><div class="wp-block-ub-content-toggle-accordion-toggle-wrap right"><span class="wp-block-ub-content-toggle-accordion-state-indicator wp-block-ub-chevron-down"></span>
                    </div></div><div role="region" aria-expanded="false" class="wp-block-ub-content-toggle-accordion-content-wrap ub-hide" id="ub-content-toggle-panel-0-7b998fbf-6273-4d5a-af56-fdec57f13276">

<pre class="wp-block-code"><code lang="python" class="language-python">cardinality_of_birthdays = 100 * 365 # ignoring leap years for now
cardinality_of_serial_numbers = 500
cardinality_of_citizenship_states = 1
cardinality_of_the_a_digit = 1
total_number_of_email_matching_combinations = cardinality_of_birthdays * cardinality_of_serial_numbers * cardinality_of_citizenship_states * cardinality_of_the_a_digit
excluded_by_using_email_information = keyspace_available - total_number_of_email_matching_combinations
print(f"Number of numbers matching email: {total_number_of_email_matching_combinations:,}")
print(summary_to_brute_force(total_number_of_email_matching_combinations))</code></pre>

</div></div>
</div>


<pre class="wp-block-code"><code lang="python" class="language-python">Number of numbers matching email: 18,250,000
At slow rate: 33.80 hours, or: 1.41 days
At optimised: 1.13 hours, or: 0.047 days</code></pre>



<p>Even the naive, 1.41 days is really starting to look feasible, and with John the Ripper, we&#8217;re already doing it in little over an hour.</p>



<h2 class="wp-block-heading"><strong>But what about the check digit?</strong></h2>



<p>Earlier we ignored the check number, since we can calculate it&#8230; but we <em>were</em> supplied it in the email.</p>



<p>We can use it to see if the ID is a potential match, and only check matching ones against the file.</p>



<p><a href="https://en.wikipedia.org/wiki/Luhn_algorithm">Luhn format</a> checkdigits use simple modulo 10 arithmetic.</p>



<p>This means only 10% of the generated IDs will be checked against the PDF password.</p>


<div class="wp-block-ub-content-toggle" id="ub-content-toggle-1cb1f99f-614e-4193-9f29-5cdc27048910" data-mobilecollapse="true" data-desktopcollapse="true">
<div class="wp-block-ub-content-toggle-accordion" id="ub-content-toggle-panel-block-">
                <div class="wp-block-ub-content-toggle-accordion-title-wrap"" aria-controls="ub-content-toggle-panel-0-1cb1f99f-614e-4193-9f29-5cdc27048910" tabindex="0">
                    <p class="wp-block-ub-content-toggle-accordion-title ub-content-toggle-title-1cb1f99f-614e-4193-9f29-5cdc27048910">Python for checksum validated keyspace</p><div class="wp-block-ub-content-toggle-accordion-toggle-wrap right"><span class="wp-block-ub-content-toggle-accordion-state-indicator wp-block-ub-chevron-down"></span>
                    </div></div><div role="region" aria-expanded="false" class="wp-block-ub-content-toggle-accordion-content-wrap ub-hide" id="ub-content-toggle-panel-0-1cb1f99f-614e-4193-9f29-5cdc27048910">

<pre class="wp-block-code"><code lang="python" class="language-python">using_checkdigit_exclusion = total_number_of_email_matching_combinations / 10
print(f"Entries matching email check digit: {using_checkdigit_exclusion:,.0f}")
print(summary_to_brute_force(using_checkdigit_exclusion))</code></pre>

</div></div>
</div>


<pre class="wp-block-code"><code lang="python" class="language-python">Entries matching email check digit: 1,825,000
At slow rate: 3.38 hours, or: 0.14 days
At optimised: 0.11 hours, or: 0.005 days</code></pre>



<p>Our &#8216;effective&#8217; keyspace is now 1,825,000 entries.</p>



<p>So even with a naive implementation just in Python, we can do it in less than a day.</p>



<h3 class="wp-block-heading"><strong>Age scoping</strong></h3>



<p>A friend pointed out that searching all ages between 0-100 is a bit pointless, so we could change that to be a range of 18-70?</p>



<p>Because the birthday field covers 100 years cleanly, we calculate the number of years we want to test.</p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true"><pre>keyspace_{Age Scoped} = keyspace_{effective} \times \frac{years\_to\_test}{100}</pre></div>



<p>However, given the effective keyspace we&#8217;re already down to, the impact of age reduction feels less useful in this scenario, if you had less information this reduction could be more useful.</p>


<div class="wp-block-ub-content-toggle" id="ub-content-toggle-bd0529bc-ed47-4827-b5a9-4e113bb7b2e0" data-mobilecollapse="true" data-desktopcollapse="true">
<div class="wp-block-ub-content-toggle-accordion" id="ub-content-toggle-panel-block-">
                <div class="wp-block-ub-content-toggle-accordion-title-wrap"" aria-controls="ub-content-toggle-panel-0-bd0529bc-ed47-4827-b5a9-4e113bb7b2e0" tabindex="0">
                    <p class="wp-block-ub-content-toggle-accordion-title ub-content-toggle-title-bd0529bc-ed47-4827-b5a9-4e113bb7b2e0">Python for age reduced keyspace</p><div class="wp-block-ub-content-toggle-accordion-toggle-wrap right"><span class="wp-block-ub-content-toggle-accordion-state-indicator wp-block-ub-chevron-down"></span>
                    </div></div><div role="region" aria-expanded="false" class="wp-block-ub-content-toggle-accordion-content-wrap ub-hide" id="ub-content-toggle-panel-0-bd0529bc-ed47-4827-b5a9-4e113bb7b2e0">

<pre class="wp-block-code"><code lang="python" class="language-python">min_age = 18
maximum_age = 70
age_range = maximum_age - min_age
percentage_of_people_in_age_range = age_range / 100
total_number_in_age_range = using_checkdigit_exclusion * percentage_of_people_in_age_range
print(f"Number in valid age range: {total_number_in_age_range:,}")
print(summary_to_brute_force(total_number_in_age_range))
</code></pre>

</div></div>
</div>


<pre class="wp-block-code"><code lang="python" class="language-python">Number in valid age range: 949,000.0
At slow rate: 1.76 hours, or: 0.07 days
At optimised: 0.06 hours, or: 0.002 days</code></pre>



<h2 class="wp-block-heading"><strong>In summary</strong></h2>



<p>From an absolute key space of 11,000,000,000,000, we&#8217;ve excluded over 99.99999% of the possible numbers, and have only 949,000 to check against the file.</p>


<div class="wp-block-ub-content-toggle" id="ub-content-toggle-0e4cf932-e13d-402a-98aa-4b9c8b1b41ac" data-mobilecollapse="true" data-desktopcollapse="true">
<div class="wp-block-ub-content-toggle-accordion" id="ub-content-toggle-panel-block-">
                <div class="wp-block-ub-content-toggle-accordion-title-wrap"" aria-controls="ub-content-toggle-panel-0-0e4cf932-e13d-402a-98aa-4b9c8b1b41ac" tabindex="0">
                    <p class="wp-block-ub-content-toggle-accordion-title ub-content-toggle-title-0e4cf932-e13d-402a-98aa-4b9c8b1b41ac">Python to generate table</p><div class="wp-block-ub-content-toggle-accordion-toggle-wrap right"><span class="wp-block-ub-content-toggle-accordion-state-indicator wp-block-ub-chevron-down"></span>
                    </div></div><div role="region" aria-expanded="false" class="wp-block-ub-content-toggle-accordion-content-wrap ub-hide" id="ub-content-toggle-panel-0-0e4cf932-e13d-402a-98aa-4b9c8b1b41ac">

<pre class="wp-block-code"><code lang="python" class="language-python">import pandas as pd
data = [
            [ keyspace_absolute, 100],
            [ keyspace_available, 100 * keyspace_available / keyspace_absolute],
            [ total_number_of_email_matching_combinations, 100 * total_number_of_email_matching_combinations / keyspace_absolute],
            [ using_checkdigit_exclusion, 100 * using_checkdigit_exclusion / keyspace_absolute],
            [ total_number_in_age_range, 100 * total_number_in_age_range / keyspace_absolute],
      ]
df = pd.DataFrame(data, columns=["Count", "Percentage of Total"], index=["Absolute Keyspace", "Available Keyspace", "Email Keyspace", "Using Email checkdigit", "Limiting by Age"])
brute_force_label = f"Hours @ {test_rate_slow}/s"
brute_force_faster_label = f"Hours @ {test_rate_fast:,}/s"
df[brute_force_label] = df["Count"] / test_rate_slow / 60 / 60
df[brute_force_faster_label] = df["Count"] / test_rate_fast / 60 / 60
df.style.set_properties(**{'font-family': "Menlo, Consolas, Monospace"}) \
  .format(subset=["Count"], thousands=",", precision=0) \
  .format('{:.6f} %', subset=["Percentage of Total"]) \
  .format(thousands=",", precision=1, subset=[brute_force_label, brute_force_faster_label]) 
</code></pre>

</div></div>
</div>


<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<figure class="wp-block-table"><table><tbody><tr><td class="has-text-align-right" data-align="right"><strong>Set of potential ID Numbers</strong></td><td class="has-text-align-right" data-align="right"><strong>Size of set</strong></td><td class="has-text-align-right" data-align="right"><strong>Percentage of Absolute</strong></td><td class="has-text-align-right" data-align="right"><strong>Hours @ 150/s</strong></td><td class="has-text-align-right" data-align="right"><strong>Hours @ 4,500/s</strong></td></tr><tr><td class="has-text-align-right" data-align="right">Absolute Keyspace</td><td class="has-text-align-right" data-align="right">10,000,000,000,000</td><td class="has-text-align-right" data-align="right">100.000000%</td><td class="has-text-align-right" data-align="right">18,518,518.5</td><td class="has-text-align-right" data-align="right">617,284.0</td></tr><tr><td class="has-text-align-right" data-align="right">Available Keyspace</td><td class="has-text-align-right" data-align="right">10,950,000,000</td><td class="has-text-align-right" data-align="right">0.109500%</td><td class="has-text-align-right" data-align="right">20,277.8</td><td class="has-text-align-right" data-align="right">675.9</td></tr><tr><td class="has-text-align-right" data-align="right">Email Keyspace</td><td class="has-text-align-right" data-align="right">18,250,000</td><td class="has-text-align-right" data-align="right">0.000182%</td><td class="has-text-align-right" data-align="right">33.8</td><td class="has-text-align-right" data-align="right">1.1</td></tr><tr><td class="has-text-align-right" data-align="right">Using Email Checkdigit</td><td class="has-text-align-right" data-align="right">1,825,000</td><td class="has-text-align-right" data-align="right">0.000018%</td><td class="has-text-align-right" data-align="right">3.4</td><td class="has-text-align-right" data-align="right">0.1</td></tr><tr><td class="has-text-align-right" data-align="right">Limiting by Age</td><td class="has-text-align-right" data-align="right">949,000</td><td class="has-text-align-right" data-align="right">0.000009%</td><td class="has-text-align-right" data-align="right">1.8</td><td class="has-text-align-right" data-align="right">0.1</td></tr></tbody></table></figure>
</div></div>



<h2 class="wp-block-heading"><strong>Visualisation</strong></h2>



<p>Graphing this is really hard, differences in scale make it really difficult to communicate.</p>



<p>Since I&#8217;m not a data-vis genius, this uses a log-scale.</p>


<div class="wp-block-ub-content-toggle" id="ub-content-toggle-b88ddc1d-773c-4bca-848b-2e7a0e34c1ea" data-mobilecollapse="true" data-desktopcollapse="true">
<div class="wp-block-ub-content-toggle-accordion" id="ub-content-toggle-panel-block-">
                <div class="wp-block-ub-content-toggle-accordion-title-wrap"" aria-controls="ub-content-toggle-panel-0-b88ddc1d-773c-4bca-848b-2e7a0e34c1ea" tabindex="0">
                    <p class="wp-block-ub-content-toggle-accordion-title ub-content-toggle-title-b88ddc1d-773c-4bca-848b-2e7a0e34c1ea">Python to generate Graph</p><div class="wp-block-ub-content-toggle-accordion-toggle-wrap right"><span class="wp-block-ub-content-toggle-accordion-state-indicator wp-block-ub-chevron-down"></span>
                    </div></div><div role="region" aria-expanded="false" class="wp-block-ub-content-toggle-accordion-content-wrap ub-hide" id="ub-content-toggle-panel-0-b88ddc1d-773c-4bca-848b-2e7a0e34c1ea">

<pre class="wp-block-code"><code lang="python" class="language-python">import matplotlib.pyplot as plt
fig, ax = plt.subplots()
data = df['Count'][::-1]
data.plot(kind='barh', logx=True, title="Keyspace Reduction\nnote the log-scale",ax=ax)
vals = ax.get_xticks()
ax.set_xticks(ax.get_xticks()[::2])
ax.set_xlabel("Keys in Keyspace")
</code></pre>

</div></div>
</div>


<figure class="wp-block-image size-full"><a href="https://cdn.garethklose.com/wp-content/uploads/2023/08/output.png"><img decoding="async" width="699" height="480" data-attachment-id="14822" data-permalink="https://garethklose.com/2023/08/state-issued-identifiers-arent-generally-good-passwords/output" data-orig-file="https://cdn.garethklose.com/wp-content/uploads/2023/08/output.png" data-orig-size="699,480" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Reduction in keyspace size" data-image-description="" data-image-caption="" data-medium-file="https://cdn.garethklose.com/wp-content/uploads/2023/08/output.png" data-large-file="https://cdn.garethklose.com/wp-content/uploads/2023/08/output.png" src="https://cdn.garethklose.com/wp-content/uploads/2023/08/output.png" alt="" class="wp-image-14822"/></a></figure>



<h1 class="wp-block-heading" id="Conclusions">Conclusions</h1>



<p>This analysis shows that in common with recent attacks on the&nbsp;<a href="https://www.wired.com/story/tetra-radio-encryption-backdoor/">Tetra encryption system</a>&nbsp;, if you&#8217;re not using all of the absolute keyspace, your protection is far weaker than may appear from a big number.</p>



<p>These national/structured IDs do not make good secrets: the structure inherently reduces the size of the effective keyspace, and makes it very easy to exclude ranges of people (by age or gender).</p>



<p>While phishing is a problem, and emails need to be/appear authentic &#8211; we need to use mechanisms to achieve this at the email level: SPF, DKIM, DMARC, BIMI. While imperfect, these are far better than including information directly related to the ID/information being protected.</p>



<p>In this scenario even with a naive implementations, it would be entirely feasible to brute-force this particular email/pdf combination, which would expose customer information.</p>



<p>Now I don&#8217;t know how valuable that information in the statement is, but I wonder if it be used as part of a social engineering attack?</p>



<p>A plea to companies: <em>If I message asking you to stop send me statements, maybe stop?</em></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">14803</post-id>	</item>
		<item>
		<title>Falsehoods Smart-Device people believe about Home Networks</title>
		<link>https://garethklose.com/2014/06/falsehoods-about-smart-devices-and-home-networks</link>
		
		<dc:creator><![CDATA[gareth]]></dc:creator>
		<pubDate>Mon, 30 Jun 2014 10:20:55 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[developers]]></category>
		<category><![CDATA[embedded devices]]></category>
		<category><![CDATA[internet of things]]></category>
		<category><![CDATA[iot]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[support]]></category>
		<category><![CDATA[wifi]]></category>
		<guid isPermaLink="false">http://garethklose.com/?p=889</guid>

					<description><![CDATA[A few years ago someone posted a great article about the bad assumptions programmers make about names; here's a similar list about assumptions about home networks and smart devices.]]></description>
										<content:encoded><![CDATA[<p>We all remember the excellent <a href="http://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/">Falsehoods people believe about names</a> don&#8217;t we?</p>
<p>Having lived with a few smart devices sharing my network for a while, I thought we need a similar one about smart devices and home networking.</p>
<p>Items marked with a * contributed or inspired by <a href="http://twitter.com/davidmoss">@davidmoss</a></p>
<ul>
<li>The WiFi is always available</li>
<li>The WiFi is continuously connected to the internet</li>
<li>The WiFi network isn&#8217;t hidden</li>
<li>The WiFi network isn&#8217;t restricted by MAC address so they can be hidden from the user</li>
<li>The WiFi network doesn&#8217;t use strong authentication like WPA2</li>
<li>The WiFi network definitely doesn&#8217;t use authentication mentioning the word &#8216;Enterprise&#8217;</li>
<li>The user knows the exact authentication type is use for the WiFi, so no need to auto-detect it*</li>
<li>There is only a single WiFi network</li>
<li>The name of the WiFi network is ASCII*</li>
<li>There is only a single access point for the WiFi network</li>
<li>Any device connected to the home-network is trusted to control the smart devices on it</li>
<li>Smart devices and their controllers are on the same network</li>
<li>Devices on the network can connect directly to each other</li>
<li>The network is simple, and doesn&#8217;t use other technologies such as powerline<sup class='footnote'><a href='#fn-889-1' id='fnref-889-1' onclick='return fdfootnote_show(889)'>1</a></sup></li>
<li>All networks have a PC type device to install/configure/upgrade devices (and that device is running Windows)*</li>
<li>There is always a DHCP Server*</li>
<li>Devices will always get the same IP address on the internal network from the DHCP server</li>
<li>DHCP device names don&#8217;t have to be explanatory, because nobody ever sees them</li>
<li>Devices can have inbound connections from the internet <sup class='footnote'><a href='#fn-889-2' id='fnref-889-2' onclick='return fdfootnote_show(889)'>2</a></sup></li>
<li>The network is reliable without packet loss</li>
<li>The connectivity is sufficient for all devices on the network</li>
<li>The performance characteristics of the network is constant and doesn&#8217;t change across time</li>
<li>The Internet connectivity isn&#8217;t metered, and there&#8217;s no problem downloading lots of data</li>
<li>Encryption of traffic is an overhead that isn&#8217;t needed on embedded devices</li>
<li>Predictable IDs like Serial-Numbers are good default security tokens</li>
<li>Unchangeable IDs like Serial-Numbers are acceptable security tokens</li>
<li>The device won&#8217;t be used as a platform for attacks, so doesn&#8217;t need hardened from threats internal and external to the network. <sup class='footnote'><a href='#fn-889-3' id='fnref-889-3' onclick='return fdfootnote_show(889)'>3</a></sup></li>
<li>Devices can be shipped and abandoned. They won&#8217;t be used for years, as so any future software vulnerabilities can be ignored</li>
<li>IPv6 is for the future, and doesn&#8217;t need to be supported<sup class='footnote'><a href='#fn-889-4' id='fnref-889-4' onclick='return fdfootnote_show(889)'>4</a></sup></li>
</ul>
<p>What have I missed?</p>
<div class='footnotes' id='footnotes-889'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-889-1'> These should be layer 2 transparent, but they can disrupt Multicast which can break bonjour <span class='footnotereverse'><a href='#fnref-889-1'>&#8617;</a></span></li>
<li id='fn-889-2'> aside from security implications, ISPs are moving to a <a href="http://en.wikipedia.org/wiki/Carrier-grade_NAT">carrier-grade NAT</a> to work around IPv4 address exhaustion, so inbound ports may not be possible <span class='footnotereverse'><a href='#fnref-889-2'>&#8617;</a></span></li>
<li id='fn-889-3'> many devices have a pretty complete Linux stack, at least complete enough for attackers to use <span class='footnotereverse'><a href='#fnref-889-3'>&#8617;</a></span></li>
<li id='fn-889-4'> Chicken and Egg this one <span class='footnotereverse'><a href='#fnref-889-4'>&#8617;</a></span></li>
</ol>
</div>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">889</post-id>	</item>
		<item>
		<title>Security is hard, but the easy bits aren&#8217;t</title>
		<link>https://garethklose.com/2014/06/security-is-hard-but-the-easy-bits-arent</link>
		
		<dc:creator><![CDATA[gareth]]></dc:creator>
		<pubDate>Fri, 20 Jun 2014 13:51:04 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[security]]></category>
		<guid isPermaLink="false">http://garethklose.com/?p=885</guid>

					<description><![CDATA[The hard bits of security are hard, but the easy bits aren't. As infrastructure gets more dynamic, we need to make sure it isn't everyone else redefining it.]]></description>
										<content:encoded><![CDATA[<p>Another week, another story about security.</p>
<p>Actually multiple stories about security.</p>
<p>And what&#8217;s upsetting with these ones are the fact that the fixes for them are already available.</p>
<p>I don&#8217;t cut-code anymore. I&#8217;m not a particular adept coder, and I think my code is a bit ugly. But I still know what bad practice smells like and what upsets me is how often we have repeat the mistakes of old. <sup class='footnote'><a href='#fn-885-1' id='fnref-885-1' onclick='return fdfootnote_show(885)'>1</a></sup> <sup class='footnote'><a href='#fn-885-2' id='fnref-885-2' onclick='return fdfootnote_show(885)'>2</a></sup></p>
<p>Yes there are always deadlines, but if we&#8217;re working with advanced software defined infrastructures, then we have to restrict who can redefine those.</p>
<p>If you&#8217;re in a Product Manager role, don&#8217;t be afraid to ask what you&#8217;re doing for security, or what response plans are if something is compromised. Be mindful of the risk to your reputation or risk if you don&#8217;t give developers time to improve security instead of piling ever more features on. The mitigations for the most obvious attacks are documented, and usually relatively easy to implement.</p>
<h1>And now to the details</h1>
<p><a href="http://searchaws.techtarget.com/news/2240223024/Code-Spaces-goes-dark-after-AWS-cloud-security-hack">Code Spaces had all their data wiped</a>, we don&#8217;t know all the details but it sounds like:</p>
<ul>
<li>They hadn&#8217;t enabled 2factor auth on their AWS account</li>
<li>Their backups weren&#8217;t to a different AWS account,  or better still to another provider.</li>
</ul>
<p>If you&#8217;re running a production service, and you&#8217;re hosting data for anyone else, then your backups need to be rock solid. Backing up to the same provider, in the same account, is like copying all the files from your desktop into a folder called &#8220;backup&#8221;.  Sure you&#8217;ve two copies but when that disk goes bang they&#8217;re both gone.</p>
<p>And yes, 2 Factor is a pain when you&#8217;re logging into services, but if you&#8217;re hosting customer data that&#8217;s a pain you need to cope with. Providers usually let you set up many secondary accounts with reduced privileges, so use those tools to protect your services, and let people do just what they need in order to do their jobs.</p>
<p>On a similar theme people are <a href="http://arstechnica.com/security/2014/06/secret-keys-stashed-in-google-play-apps-pose-risk-to-android-users-developers/">leaving their AWS keys in android apps</a>. Amazon offers a ticket granting service that&#8217;s ideal for this, but that&#8217;s more work, but work that you should be doing.</p>
<p>Some people aren&#8217;t even using those permissioning tools to embed keys with limited access, which just to reiterate, you shouldn&#8217;t be doing anyway. Instead they are embedding their main access key pair, which means that attackers could access and delete all data, and spin up thousands of instances just for fun/profit.</p>
<p>Security is hard, the recent problems found in libraries like OpenSSL are hard for an individual coder to work around, but decent libraries are still better than going it alone.</p>
<p>The 80:20 rule is ever present, will you ever make your app fully secure; unlikely. Can you prevent the most obvious attacks with application of best practices, which many programming languages can do for you; yes.</p>
<p><strong>Don&#8217;t</strong> leave keys lying around, give apps or services any more permissions than they need, or use predictable IDs for sensitive data&#8230;</p>
<p><strong>Do</strong> sanitise data you&#8217;re given, protect from XSS attacks, turn on 2-Factor Authentication for anything serious and always keep decent backups hosted on separate infrastructure&#8230;</p>
<p>These lists go on, but they not new: Best practice years ago, is still best practice now.</p>
<div class='footnotes' id='footnotes-885'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-885-1'> Don&#8217;t get me started on file-moving scripts that don&#8217;t use incoming and outgoing folders to avoid race-conditions <span class='footnotereverse'><a href='#fnref-885-1'>&#8617;</a></span></li>
<li id='fn-885-2'> Or when we tolerate software from vendors that can&#8217;t run as anything other than root or Administrator <span class='footnotereverse'><a href='#fnref-885-2'>&#8617;</a></span></li>
</ol>
</div>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">885</post-id>	</item>
		<item>
		<title>Security becoming life and death</title>
		<link>https://garethklose.com/2011/10/security-becoming-life-and-death</link>
		
		<dc:creator><![CDATA[gareth]]></dc:creator>
		<pubDate>Wed, 26 Oct 2011 16:44:59 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[medical devices]]></category>
		<category><![CDATA[safety]]></category>
		<category><![CDATA[security]]></category>
		<guid isPermaLink="false">http://garethklose.com/?p=570</guid>

					<description><![CDATA[When medical devices are hacked, is it finally time to get that security should be implicit as a requirement.]]></description>
										<content:encoded><![CDATA[<p>(Given many of my posts are second rate <a href="http://daringfireball.net">Gruber</a> posts on the mac, this one is a second rate <a href="http://www.schneier.com/">Schneier</a>)</p>
<p>I like <a href="http://en.wikipedia.org/wiki/Chip_and_PIN">Chip+PIN</a>. I don’t think <a href="http://en.wikipedia.org/wiki/EMV">EMV</a> is perfect: it has the complexity of a committee driven standard created by competing companies, and it has flaws and oversights. I’ll still wager it’s more secure than someone looking at a signature, and since skimming attacks get immediately moved abroad (when the cloned cards are created from the legacy mag-stripe) behavioural analysis makes spotting fraud a bit easier.</p>
<p>I do not feel the same way about Verified By Visa which I continue to curse every time I use it.</p>
<p>Anyway I very much disliked the UK Cards Association’s response to the excellent Cambridge Computer Laboratory when they’ve published flaws and potential attacks, demanding they take the papers down. They played the near standard “oh it’s very hard to do right now, we don’t think anyone could really do that, please, they’re very clever and most people won’t be” line. The only problem is that with each new vulnerability, the Cambridge Team appear to be producing more plausible attacks. UK Cards were <a href="http://www.cl.cam.ac.uk/~rja14/Papers/ukca.pdf">rightly told to go away</a>.</p>
<p>It would have been nicer to hear:</p>
<blockquote><p>“We thank the CCL for their work in exposing potential attacks in the EMV system. At the moment we think these are peripheral threats, but we will work with EMV partners to take the findings onboard, and resolve these as the standard evolves”
</p></blockquote>
<p>This is course blows the “Chip+PIN is a totally secure” line out the water &#8211; which matters because they’re trying to move the liability onto the consumer, admitting the system is even partially compromised lessens that.</p>
<p>At the end of the day, this is just money. There’s always been fraud, there always will be. Not life and death.</p>
<p>I used to work in Broadcast. Many of those systems were insecure relying on being in a partitioned network. DNS and Active Directory were frowned on, being seen as potential points of failure rather than useful configuration and security tool.  The result was a known, but brittle system. Hardening of builds was an afterthought and the armadillo model of crunchy perimeter, soft centre, meant that much like the <a href="http://www.wired.com/dangerroom/2011/10/virus-hits-drone-fleet/">US Predator Drone control pods</a>, once inside passage made easy.</p>
<p>Depressing, yes? Particularly because so many of these problems were solved before, and solved well. But it was just telly. Not life and death.</p>
<p>I mean, it’s not like you can remotely inject someone with a lethal dose of something.</p>
<p>Except it is: A few months back someone <a href="http://nakedsecurity.sophos.com/2011/08/08/bh-2011-hacking-medical-devices-for-fun-and-insulin/">reversed engineered the protocol of their insulin pump</a>, able to control it with the serial number. This was bad enough. Devices that inject things into humans shouldn’t be controllable without some of authentication beyond a 6 digit number.</p>
<p>At the time the familiar: “it’s too difficult, you still need the number, you’ve got to be nearby” response was provided.</p>
<p>Two months later, <a href="http://www.cso.com.au/article/404909/lethal_medical_device_hack_taken_next_level/?fp=4&#038;fpid=959105">another security person has now managed to decode the magical number</a>, and used a long distance aerial to be able to send commands to the pump.</p>
<p>I’m sure it’s still “too hard to be viable”: because the death of someone isn’t something that has major consequences that could have the kind of support that makes hard things viable&#8230;</p>
<p>Security is hard to do well, and we need to start embedding it in everything &#8211; it is now a matter of life and death. But it’s hard, and hard for the psychology just as much as a technical. You should really use an existing algorithm implementation because the chances are it’s better than yours: but that’s licensing and IPR, so just roll your own cipher believing your application is too trivial to be a target for hacking. Besides your proprietary wire-protocol is proprietary, it’s already secret. People aren’t going to bother to figure it out.</p>
<p>Security makes things harder: you can’t just wire-sniff your protocol anymore to debug stuff. Your test suites become more complicated because you can no longer play back the commands and expect the device to respond. That little embedded processor isn’t powerful enough to be doing crypto: it’s going to up the unit price, it’s going to increase power usage and latency.</p>
<p>Many programmers, still, belong to the “if I hit it and hit it until it works” school of coding. I don’t mean test-driven-development, I’m meaning those coders who think if it compiles, it ships. These people don’t really adapt well to  working in a permissions based sandbox; it’s harder to split your processes up so that only the things that need the privileges have them (we’ve all done ‘chmod 777 *’ to get an application up and running).</p>
<p>Until everyone realises that every device with smarts is a vector, from <a href="http://www.accuvant.com/capability/accuvant-labs/security-research/battery-firmware-hacking">Batteries</a>, to APIs, to websites we&#8217;re increasingly at risk. I guess that massive solar flare could take things out for us. </p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">570</post-id>	</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/

Object Caching 0/175 objects using APC
Page Caching using Disk: Enhanced 
Content Delivery Network via Amazon Web Services: CloudFront: cdn.garethklose.com
Minified using Disk
Database Caching using APC (Request-wide modification query)

Served from: garethklose.com @ 2026-06-26 18:35:31 by W3 Total Cache
-->