summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app.py39
-rw-r--r--static/styles.css4
-rw-r--r--templates/index.html (renamed from index.html)6
-rw-r--r--templates/nonce-reuse.html (renamed from nonce-reuse.html)63
4 files changed, 81 insertions, 31 deletions
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..2177e9c
--- /dev/null
+++ b/app.py
@@ -0,0 +1,39 @@
+import binascii
+
+from flask import Flask, render_template, request, redirect, url_for
+
+from aesgcmanalysis import xor, gmac, gcm_encrypt, nonce_reuse_recover_secrets, gf128_to_bytes
+
+app = Flask(__name__)
+
+@app.route('/')
+def index():
+ return render_template('index.html')
+
+@app.route('/nonce-reuse', methods=['GET', 'POST'])
+def nonce_reuse():
+ key = nonce = c_forged = macs = None
+ m1 = m2 = mf = ''
+ if request.method == 'POST':
+ key = binascii.unhexlify(request.form['key'])
+ nonce = binascii.unhexlify(request.form['nonce'])
+ m1 = request.form['m1']
+ m2 = request.form['m2']
+ mf = request.form['mf']
+ c_forged, macs = solve(key, nonce, bytes(m1, 'ascii'), bytes(m2, 'ascii'), bytes(mf, 'ascii'))
+ return render_template('nonce-reuse.html', key=key, nonce=nonce, m1=m1, m2=m2, mf=mf, c_forged=c_forged, macs=macs)
+
+def solve(k, nonce, m1, m2, mf):
+ aad1 = aad2 = b""
+ c1, mac1 = gcm_encrypt(k, nonce, aad1, m1)
+ c2, mac2 = gcm_encrypt(k, nonce, aad2, m2)
+
+ possible_secrets = nonce_reuse_recover_secrets(nonce, aad1, aad2, c1, c2, mac1, mac2)
+ c_forged = xor(c1, xor(m1, mf))
+ aad_forged = b""
+ macs = []
+ for h, s in possible_secrets:
+ mac = gmac(h, s, aad_forged, c_forged)
+ macs.append((gf128_to_bytes(h), s, mac))
+ return c_forged, macs
+
diff --git a/static/styles.css b/static/styles.css
index c7d09c0..6360fc1 100644
--- a/static/styles.css
+++ b/static/styles.css
@@ -10,3 +10,7 @@
margin-top: -2px;
padding-left: 20px;
}
+
+ul {
+ margin-top: 5px;
+}
diff --git a/index.html b/templates/index.html
index 1fd52b1..fdcddd8 100644
--- a/index.html
+++ b/templates/index.html
@@ -18,11 +18,11 @@
<div class="crumbs">
<a href="/git/forbidden-salamanders">source code</a>
<span class="sep"> · </span>
- <a href="/forbidden-salamanders/nonce-reuse">nonce reuse</a>
+ <a href="/forbidden-salamanders/nonce-reuse">aes-gcm nonce reuse</a>
<span class="sep"> · </span>
- <a href="/forbidden-salamanders/nonce-truncation">nonce truncation</a>
+ <a href="/forbidden-salamanders/nonce-truncation">aes-gcm nonce truncation</a>
<span class="sep"> · </span>
- <a href="/forbidden-salamanders/key-commitment">key commitment</a>
+ <a href="/forbidden-salamanders/key-commitment">aes-gcm key commitment</a>
</div>
</div>
<p>
diff --git a/nonce-reuse.html b/templates/nonce-reuse.html
index 21c794d..9761955 100644
--- a/nonce-reuse.html
+++ b/templates/nonce-reuse.html
@@ -18,11 +18,11 @@
<div class="crumbs">
<a href="/git/forbidden-salamanders">source code</a>
<span class="sep"> · </span>
- <a href="/forbidden-salamanders/nonce-reuse"><strong>nonce reuse</strong></a>
+ <a href="/forbidden-salamanders/nonce-reuse"><strong>aes-gcm nonce reuse</strong></a>
<span class="sep"> · </span>
- <a href="/forbidden-salamanders/nonce-truncation">nonce truncation</a>
+ <a href="/forbidden-salamanders/nonce-truncation">aes-gcm nonce truncation</a>
<span class="sep"> · </span>
- <a href="/forbidden-salamanders/key-commitment">key commitment</a>
+ <a href="/forbidden-salamanders/key-commitment">aes-gcm key commitment</a>
</div>
</div>
<p>
@@ -85,55 +85,66 @@
</p>
</details>
<br>
- <form>
+ <form action="/forbidden-salamanders/nonce-reuse" method="post">
<div>
<label for="key">Key (16 bytes in hex)</label>
- <input id="key" type="text" value="59454c4c4f575f5355424d4152494e45">
+ <input name="key" id="key" type="text" value="{{ key.hex() if key else '59454c4c4f575f5355424d4152494e45' }}" minlength=32 maxlength=32>
</div>
<div>
<label for="nonce">Nonce (12 bytes in hex)</label>
- <input id="nonce" type="text" value="4a4f5247454c424f52474553">
+ <input name="nonce" id="nonce" type="text" value="{{ nonce.hex() if nonce else '4a4f5247454c424f52474553' }}" minlength=24 maxlength=24>
</div>
<div>
- <label for="m1">First message (in ASCII)</label>
- <input id="m1" type="text">
+ <label for="m1">First intercepted message (in ASCII)</label>
+ <input name="m1" id="m1" type="text" required maxlength=100 value="{{m1}}">
</div>
<div>
- <label for="m2">Second message (in ASCII)</label>
- <input id="m2" type="text">
+ <label for="m2">Second intercepted message (in ASCII)</label>
+ <input name="m2" id="m2" type="text" required maxlength=100 value="{{m2}}">
</div>
<div>
<label for="mf">Forged message; shorter than the first message (in ASCII)</label>
- <input id="mf" type="text">
+ <input name="mf" id="mf" type="text" required maxlength=100 value="{{mf}}">
</div>
<div>
- <input type="button" value="Recover authentication key and forge MAC">
+ <button type="submit">Recover authentication key and forge MAC</button>
</div>
</form>
+ {% if macs %}
<div>
- <label for="h">Authentication key</label>
- <input id="h" type="text" disabled value="deadbeef">
- </div>
- <div>
- <label for="mf">Forged ciphertext, assuming first message is known</label>
- <input id="mf" type="text">
- </div>
- <div>
- <label for="mac">Forged MAC</label>
- <input id="mac" type="text" disabled value="deadbeef">
+ <p>
+ Forged ciphertext: <code>{{ c_forged.hex() }}</code>
+ </p>
+ Forged MAC candidates:
+ <ul>
+ {% for h, _, mac in macs %}
+ <li>
+ MAC: <code>{{mac.hex()}}</code>
+ <ul>
+ <li>Authentication key: <code>{{h.hex()}}</code></li>
+ </ul>
+ </li>
+ {% endfor %}
+ </ul>
+ <form action="/forbidden-salamanders/nonce-reuse" method="get">
+ <div>
+ <button type="submit">Reset</button>
+ </div>
+ </form>
</div>
+ {% endif %}
<br>
<details>
<summary>
Show me the code.
</summary>
<pre>
-from <a href="/git/forbidden-salamanders">aesgcmanalysis</a> import xor, gcm_encrypt, gcm_decrypt, nonce_reuse_recover_secrets
+from <a href="/git/forbidden-salamanders">aesgcmanalysis</a> import xor, gmac, gcm_encrypt, gcm_decrypt, nonce_reuse_recover_secrets
k = b"tlonorbistertius"
nonce = b"jorgelborges"
@@ -170,10 +181,6 @@ assert succeeded</pre></details>
Show me the math.
</summary>
<p>
- A description of the construction of GMAC can be found at the <a
- href="/forbidden-salamanders">mission homepage</a>.
- </p>
- <p>
Once the polynomial difference is computed, one can use SageMath
to compute the factors:
</p>
@@ -205,7 +212,7 @@ for factor, _ in p.factor():
if factor.degree() == 1:
print('Authentication key:', factor - y)</pre>
<p>
- However, the library powering this demonstration implements <a href="https://en.wikipedia.org/wiki/Factorization_of_polynomials_over_finite_fields">polynomial factoring over finite fields</a>, which is an edifying exercise.
+ However, the library powering this demonstration implements <a href="https://en.wikipedia.org/wiki/Factorization_of_polynomials_over_finite_fields">polynomial factoring over finite fields</a> from scratch, which is an edifying exercise.
</p>
<p>
We present advice for those who wish to implement polynomial factorization as well: