diff options
-rw-r--r-- | app.py | 39 | ||||
-rw-r--r-- | static/styles.css | 4 | ||||
-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
@@ -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: |