<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://0xkrt26.github.io/math_behind_security/feed.xml" rel="self" type="application/atom+xml" /><link href="https://0xkrt26.github.io/math_behind_security/" rel="alternate" type="text/html" /><updated>2026-04-28T13:25:33+00:00</updated><id>https://0xkrt26.github.io/math_behind_security/feed.xml</id><title type="html">Math behind Security</title><subtitle>The mathematics behind why encryption works — and why it sometimes doesn&apos;t.</subtitle><author><name>0xkrt26</name></author><entry><title type="html">The Accidental Ancestor — How a Computer for Verifying Numbers Shaped Modern Hashing</title><link href="https://0xkrt26.github.io/math_behind_security/2026/04/28/the-accidental-ancestor-Luhn-algorithm.html" rel="alternate" type="text/html" title="The Accidental Ancestor — How a Computer for Verifying Numbers Shaped Modern Hashing" /><published>2026-04-28T00:00:00+00:00</published><updated>2026-04-28T00:00:00+00:00</updated><id>https://0xkrt26.github.io/math_behind_security/2026/04/28/the-accidental-ancestor-Luhn-algorithm</id><content type="html" xml:base="https://0xkrt26.github.io/math_behind_security/2026/04/28/the-accidental-ancestor-Luhn-algorithm.html"><![CDATA[<p>1954, Hans Peter Luhn filed for a US patent on a Computer for Verifying Numbers. This is one of the earliest examples of using mathematical transformations to verify data integrity, a 
concept that became a foundation for modern hashes. Today you can find it under names Luhn Algorithm, Luhn Formula or Modulus 10 Algorithm.</p>

<h3 id="how-does-this-algorithm-work">How does this algorithm work?</h3>

<p>Imagine you have a number. Let’s take</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>3846205
</code></pre></div></div>
<h3 id="step-1">Step 1.</h3>

<p>Find a substitution digit.</p>

<p>To do that multiply the original digit by two. If  result is 10 or bigger, add the digits. A substitution for the first digit from our example would be</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>3*2 = 6,
</code></pre></div></div>
<p>but if the original number was 7, its substitution would be</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>7*2 = 14 = 1+4 = 5
</code></pre></div></div>
<h3 id="step-2">Step 2.</h3>

<p>Replace every digit on an odd position from the left by its substitution.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>3846205 -&gt; 6886401
</code></pre></div></div>
<h3 id="step-3">Step 3.</h3>

<p>Determine a check digit.</p>

<p>To do that add all the digits from the number from step 2. Take modulo 10 of this sum and subtract it from 10. That’s your check digit.</p>

<p>In our example, check digit is 7:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>6+8+8+6+4+0+1 = 33 mod 10 = 3
10-3 = 7
</code></pre></div></div>
<p><em>In the original paper Luhn performs modulo 10 operation each time the addition happens</em></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(6+8) mod 10 = 4
(4+8) mod 10 = 2
etc
</code></pre></div></div>
<p><em>However, it gives the same result</em></p>

<h3 id="step-4">Step 4.</h3>

<p>Append this check digit to the number from step 2.</p>

<p>The check digit should be appended in its original form, therefore on an even position. In our example just like in the original device it’s added on the first from the right or the 8th position.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>68864017
</code></pre></div></div>
<h3 id="and-how-does-verifying-work">And how does verifying work?</h3>

<p>To verify the number perform a step 2 on the original number that already includes the check digit. Add all the digits. Take modulo 10 of this sum. The result should equal zero.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Original number with a check digit: 75689034
With substitutions: 55389064

Verification: 5+5+3+8+9+0+6+4 = 40 mod 10 = 0
</code></pre></div></div>
<p>Otherwise the number is invalid. For example if instead of 6 in the original number we accidentally type 7, the result of verification will be:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 5+5+5+8+9+0+6+4 = 42 mod 10 = 2
</code></pre></div></div>
<h3 id="does-it-really-work-for-all-the-numbers">Does it really work for all the numbers?</h3>

<p>Almost. Luhn Algorithm can catch all the single digit errors. Let’s take a look at this table that shows all 10 possible digits and their substitution:</p>

<table>
  <thead>
    <tr>
      <th>Original digit</th>
      <th>0</th>
      <th>1</th>
      <th>2</th>
      <th>3</th>
      <th>4</th>
      <th>5</th>
      <th>6</th>
      <th>7</th>
      <th>8</th>
      <th>9</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Substitution</td>
      <td>0</td>
      <td>2</td>
      <td>4</td>
      <td>6</td>
      <td>8</td>
      <td>1</td>
      <td>3</td>
      <td>5</td>
      <td>7</td>
      <td>9</td>
    </tr>
  </tbody>
</table>

<p>We can see, that the second row is just a permutation of the first one. This means that every original digit gets assigned its unique substitution and therefore each mistype will result in a changed checksum. For example:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Original digits: 2 6
Substitutions: 4 6
Original sum: 10

Mistype digits: 3 6
Substitutions: 6 6
Malicious sum: 12

</code></pre></div></div>
<p>Luhn Algorithm can also catch all the transposition of neighboring digits errors, except for the transposition of 09 or 90, because as we can see from the table above, their substitutions equal the original values.</p>

<h3 id="so-is-it-a-cryptographically-secured-hash-function">So is it a cryptographically secured hash function?</h3>

<p>No. Luhn Algorithm was created to protect against accidental errors, not malicious attacks. For example, it can’t detect two digit errors, as many of them result in an unchanged sum:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Original digits: 2 6
Substitutions: 4 6
Original sum: 10

Malicious digits: 6 7
Substitutions: 3 7
Malicious sum: 10
</code></pre></div></div>
<p>That’s why nowadays, numbers that require verification, like your credit card number or your id number, use additional security or better protected algorithms.</p>

<h3 id="further-notes">Further notes</h3>

<p>A year before, in 1953 Luhn introduced the concept that would later serve as a foundation for the hash tables. In the internal IBM memo, he introduces the idea of using math to organize data into searchable buckets, which is basically what we call hash tables nowadays.</p>

<p>As it was an internal IBM memo, it doesn’t have any public access, therefore all the information can be taken only from the secondary source, an <a href="https://spectrum.ieee.org/hans-peter-luhn-and-the-birth-of-the-hashing-algorithm">IEEE Spectrum article</a>. Rather than repeat it here, I’d recommend reading the <a href="https://spectrum.ieee.org/hans-peter-luhn-and-the-birth-of-the-hashing-algorithm">IEEE Spectrum article</a> directly. It explains the idea with a clear telephone number database example.</p>

<p>The mathematics behind Luhn’s concept for such information storage had to be modified later to improve transformation, guarantee even distribution and minimize collisions. <a href="https://0xkrt26.github.io/math_behind_security/2026/04/25/searching-smarter-rolling-hashes.html">Rabin-Karp algorithm</a> that I’ve already written about provides some solutions to these problems.</p>

<h3 id="my-sources-and-further-readings">My sources and further readings:</h3>
<p><a href="https://spectrum.ieee.org/hans-peter-luhn-and-the-birth-of-the-hashing-algorithm">IEEE Article about Hans Peter Luhn</a> 
<a href="https://docs.google.com/viewer?url=patentimages.storage.googleapis.com/pdfs/US2950048.pdf">Luhn’s Patent on a Computer for Verifying Numbers</a>
<a href="https://fermatslibrary.com/s/a-new-method-of-recording-and-searching-information">Luhn “A new method of recording and searching information”</a></p>]]></content><author><name>0xkrt26</name></author><summary type="html"><![CDATA[1954, Hans Peter Luhn filed for a US patent on a Computer for Verifying Numbers. This is one of the earliest examples of using mathematical transformations to verify data integrity, a concept that became a foundation for modern hashes. Today you can find it under names Luhn Algorithm, Luhn Formula or Modulus 10 Algorithm.]]></summary></entry><entry><title type="html">Searching smarter - Plagiarism Detection with Rolling Hashes</title><link href="https://0xkrt26.github.io/math_behind_security/2026/04/25/searching-smarter-rolling-hashes.html" rel="alternate" type="text/html" title="Searching smarter - Plagiarism Detection with Rolling Hashes" /><published>2026-04-25T00:00:00+00:00</published><updated>2026-04-25T00:00:00+00:00</updated><id>https://0xkrt26.github.io/math_behind_security/2026/04/25/searching-smarter-rolling-hashes</id><content type="html" xml:base="https://0xkrt26.github.io/math_behind_security/2026/04/25/searching-smarter-rolling-hashes.html"><![CDATA[<p>1987 Michael O. Rabin and Richard M. Karp introduced rolling hashes and polynomial hashing — concepts that reappear throughout modern cryptography and are widely used for plagiarism detection.</p>

<h3 id="how-does-it-work">How does it work?</h3>

<p>This is what polynomial hash looks like:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>H=c1*b^(n-1)+c2*b^(n-2)+...cn*b^(0) mod p,
	where cn = character n of the plaintext
	n = number of characters in the plaintext
	p = suitable prime number
	b = base of the code system (256 etc)
</code></pre></div></div>
<p><em>Note: if we leave mod p away, we’ll be left with the same algorithm we use to convert numbers for example  from binary to decimal system (for binary b = 2).</em></p>

<h3 id="but-why-calculate-hash-function-when-we-can-just-straight-ahead-compare-characters">But why calculate hash function when we can just straight ahead compare characters?</h3>

<p>This is a legitimate way to compare strings called a naive string comparison, but i wouldn’t recommend it for large texts. It will be too long and not as elegant as Rabin-Karp algorithm. Take a look yourself: imagine you have a string out of 17 letters, for example “abbrabraarbababra”, and you need to write a program that will find how many times in this string there’s a 3-letter combination “abr”. If you use a naive string comparison you’ll probably write something like this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>text = "abbrabraarbababra"
pattern = "abr"

for each character i in the text:
   	    if text[i] == 'a':
       	if text[i+1] == 'b':
       	    if text[i+2] == 'r':
           		print "found at position", i
</code></pre></div></div>
<p>This algorithm checks every single character, some of them even multiple times.</p>

<p>Now Rabin-Karp algorithm uses what’s called rolling hash function that is much faster and more efficient than the naive comparison.</p>

<h3 id="what-makes-rolling-hash-function-faster">What makes Rolling Hash function faster?</h3>

<p>It works pretty simply. Instead of checking every letter in a triple, you treat the triple as a whole. Imagine you’re a detective looking for a criminal (specific face) among suspects. Naive comparison is like checking every facial feature of every suspect one by one: first eyes, then nose, then mouth. Using a hash is like comparing the complete face at once.</p>

<p>And we don’t even have to calculate a hash function for each triple from scratch! Rolling hash function calculates the next hash value based on the old hash value using this formula:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Hnew = (b*(Hold -c1*b^(n-1))+cnew) mod p,
</code></pre></div></div>
<p>which basically removes first character of the triple and adds the next one.</p>

<h3 id="is-rabin-karp-algorithm-always-efficient">Is Rabin-Karp algorithm always efficient?</h3>

<p>Unfortunately no. But good news: even in the worst case scenario, where all calculated hashes are identical, the efficiency will be the same as by naive comparison. So it’s definitely worth trying.</p>

<h3 id="wait-why-would-hashes-be-identical-arent-they-all-unique">Wait, why would hashes be identical? Aren’t they all unique?</h3>

<p>While it’s our goal to make hashes unique and do our best to avoid collisions, some poorly chosen variables can still lead to the pigeonhole principle (it’s a fancy name for having collisions, you can read more about it <a href="https://math.mit.edu/~fgotti/docs/Courses/C.%20Combinatorial%20Analysis/1.%20Pigeonhole%20Principle/Pigeonhole%20Principle.pdf">here</a>). That’s why even after hash values match, Rabin-Karp algorithm still compares string values to exclude collisions.</p>

<h3 id="but-why-do-collisions-happen">But why do collisions happen?</h3>

<p>To answer this question, let’s take a look at polynomial hash again. We have two variables that are chosen independently from the plaintext: b and p.</p>

<h3 id="oh-so-collisions-happen-because-b-is-too-small">Oh, so collisions happen because b is too small?</h3>

<p>Not exactly, the number of collisions (preferably their absence) depends primarily on the chosen p value. The larger p is the less collisions we’ll get. Why? Let’s imagine:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>p = 7,

then 1 mod 7 = 1
2 mod 7 = 2
3 mod 7 = 3
...
6 mod 7 = 6
7 mod 7 = 0
	
and...
all over again: 8 mod 7 = 1
9 mod 7 = 2
etc.
</code></pre></div></div>
<p>Which gives us only seven unique values. Now if we took p = 23, we would have had 23 unique values. And so on. The bigger prime number we take, the less likely we will have repetitions. But also keep in mind that it shouldn’t be too big, otherwise it can lead to performance issues.</p>

<h3 id="why-does-p-have-to-be-a-prime-number">Why does p have to be a prime number?</h3>

<p>It doesn’t have to, but it again reduces collisions. Imagine p as a number of baskets we can put our numbers in. If we take p=12, then we have 12 baskets. At first, if we do the same modulo operations we did for p=7 in the previous example, we’ll end up with the same distribution. But in real life numbers usually don’t come in as a perfectly sorted row. Worst Case scenario: we get only numbers dividable by 3. So instead of:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1, 2, 3, 4, 5, 6... 11, 12, etc,
</code></pre></div></div>
<p>we get:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>3, 6, 9, 12, 15, 18, etc.
</code></pre></div></div>
<p>That will lead to an uneven distribution, where baskets 3, 6, 9 and 0 will be full, whereas other baskets will be completely empty. Therefore we need to reduce the number of dividers, to prevent a worst case scenario and achieve an even distribution.</p>

<p><em>If you are looking for illustrations and more detailed but simple explanation, you can find them <a href="https://cs.stackexchange.com/a/157627">here</a></em></p>

<h3 id="so-if-the-number-of-collisions-is-defined-by-p-why-would-we-need-to-use-b-why-not-just-adding-character-values-and-mod-them">So if the number of collisions is defined by p, why would we need to use b? Why not just adding character values and mod them?</h3>

<p>The problem is, that different strings can result in the same sum. Let’s take a look at this example (instead of ascii we’ll just take the alphabet position of the letter):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>be = 2+5 = 7
eb = 5+2 = 7, 
just like cd = 3+4 = 7 
</code></pre></div></div>
<p>Those b constructions add weight to each value making repetitions less likely.</p>

<h3 id="but-what-size-for-b-should-we-choose">But what size for b should we choose?</h3>

<p>Depends on the alphabet you’re using. Usually the value of b is 256, which covers all ASCII characters, but it can also be smaller or bigger. Just make sure it covers all the characters your alphabet has, otherwise it’ll also lead to collisions. But be careful: if the value of b is too big it can result in overflow.</p>

<h3 id="and-how-exactly-is-rabin-karp-method-used-in-modern-cryptography">And how exactly is Rabin-Karp method used in modern cryptography?</h3>

<p>Even though the Rabin-Karp algorithm is nowadays used primarily for spell checking and bio-informatics, just like other string matching algorithms, it can also be used in network intrusion detection systems to verify the data packets traveling through the network or in digital forensics to find evidence within digital data. Rabin-Karp algorithm introduced a concept of polynomial hashing, however, cryptographic hashing required fundamentally different construction that we’ll talk about next time.</p>

<p><em>P.S. This post was partially inspired by <a href="https://guptadeepak.com/the-evolution-of-hashing-algorithms-from-md5-to-modern-day/">The Evolution of Hashing Algorithms</a>. It credits Rabin-Karp as the origin of hashing history, which, as I found out after a deeper research, isn’t quite accurate. Hashing goes back further than 1987, but that’s a story for the next post.</em></p>

<h3 id="my-sources-and-further-readings">My sources and further readings:</h3>
<p><a href="https://people.csail.mit.edu/alinush/6.006-spring-2014/rec06-rabin-karp-spring2011.pdf">MIT Rabin-Karp Algorithm</a>
<a href="https://math.mit.edu/~fgotti/docs/Courses/C.%20Combinatorial%20Analysis/1.%20Pigeonhole%20Principle/Pigeonhole%20Principle.pdf">MIT Pigeonhole</a>
<a href="https://cacm.acm.org/news/in-memoriam-michael-o-rabin/">Michael O. Rabin Biography</a>
<a href="https://www.researchgate.net/publication/332773245_Exact_String_Matching_Algorithms_Survey_Issues_and_Future_Research_Directions">Research about String Matching Algorithms</a>
<a href="https://academic.oup.com/bioinformaticsadvances/article/3/1/vbad162/7413189">Oxford Rabin-Karp in Bioinformatics</a>
<a href="https://www.geeksforgeeks.org/dsa/rabin-karp-algorithm-for-pattern-searching/">More about Rabin-Karp Algorithm</a>
<a href="https://www.geeksforgeeks.org/dsa/hash-functions-and-list-types-of-hash-functions/">More about Hash Functions</a></p>]]></content><author><name>0xkrt26</name></author><summary type="html"><![CDATA[1987 Michael O. Rabin and Richard M. Karp introduced rolling hashes and polynomial hashing — concepts that reappear throughout modern cryptography and are widely used for plagiarism detection.]]></summary></entry><entry><title type="html">Short intro</title><link href="https://0xkrt26.github.io/math_behind_security/2026/04/22/intro.html" rel="alternate" type="text/html" title="Short intro" /><published>2026-04-22T00:00:00+00:00</published><updated>2026-04-22T00:00:00+00:00</updated><id>https://0xkrt26.github.io/math_behind_security/2026/04/22/intro</id><content type="html" xml:base="https://0xkrt26.github.io/math_behind_security/2026/04/22/intro.html"><![CDATA[<p>How is my data secured? How was it kept safe throughout history? Can I decrypt it without a key?</p>

<p>At school these questions wouldn’t leave me alone, so I sat down and wrote a program that would break a Vigenère cipher (mostly by combining pieces of code I found that were supposed to do it). Later they led me to apply to Technical University of Munich (TUM) to study Computer Science. And eventually, they’re what helped me realize I belong in Mathematics instead.</p>

<p>So this blog is a side project for my TUM Math application. It goes like this: I pick a topic from the intersection of mathematics and cybersecurity, research it properly, and then break it down here the way I used to explain math to my classmates before our  Math Abi. No unnecessary complexity, just the idea itself, as clearly as I can.</p>

<p>If you’ve ever wondered why encryption actually works (or how it gets broken) you’re in the right place.</p>]]></content><author><name>0xkrt26</name></author><summary type="html"><![CDATA[How is my data secured? How was it kept safe throughout history? Can I decrypt it without a key?]]></summary></entry></feed>