From 96a52a1030c1bb27619372c6cebb633e02017847 Mon Sep 17 00:00:00 2001 From: cyfraeviolae Date: Thu, 25 Aug 2022 02:16:03 -0400 Subject: data truncation truncation launch remove files --- app.py | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) (limited to 'app.py') diff --git a/app.py b/app.py index d573efc..efc45bf 100644 --- a/app.py +++ b/app.py @@ -1,11 +1,12 @@ -import binascii +import binascii, secrets from flask import Flask, render_template, request, redirect, url_for from flask_wtf import FlaskForm from wtforms import StringField from wtforms.validators import DataRequired, Length, ValidationError +from Crypto.Cipher import AES -from aesgcmanalysis import xor, gmac, gcm_encrypt, nonce_reuse_recover_secrets, gf128_to_bytes +from aesgcmanalysis import xor, gmac, gcm_encrypt, nonce_reuse_recover_secrets, gf128_to_bytes, nonce_truncation_recover_secrets app = Flask(__name__) @@ -21,7 +22,6 @@ def hex_check(form, field): def not_equal_to(other): def helper(form, field): - print(other, form['m1'], field) if other not in form: return if form[other].data == field.data: @@ -46,10 +46,10 @@ def nonce_reuse(): if form.validate(): skey = binascii.unhexlify(key) snonce = binascii.unhexlify(nonce) - c_forged, macs = solve(skey, snonce, bytes(m1, 'utf-8'), bytes(m2, 'utf-8'), bytes(mf, 'utf-8')) + c_forged, macs = solve_nonce_reuse(skey, snonce, bytes(m1, 'utf-8'), bytes(m2, 'utf-8'), bytes(mf, 'utf-8')) return render_template('nonce-reuse.html', form=form, key=key, nonce=nonce, m1=m1, m2=m2, mf=mf, c_forged=c_forged, macs=macs) -def solve(k, nonce, m1, m2, mf): +def solve_nonce_reuse(k, nonce, m1, m2, mf): aad1 = aad2 = b"" c1, mac1 = gcm_encrypt(k, nonce, aad1, m1) c2, mac2 = gcm_encrypt(k, nonce, aad2, m2) @@ -63,3 +63,36 @@ def solve(k, nonce, m1, m2, mf): macs.append((gf128_to_bytes(h), s, mac)) return c_forged, macs +class NonceTruncationForm(FlaskForm): + key = StringField('key', validators=[DataRequired(), Length(min=32, max=32), hex_check]) + nonce = StringField('nonce', validators=[DataRequired(), Length(min=24, max=24), hex_check]) + mf = StringField('forged message', validators=[DataRequired(), Length(min=1, max=64)]) + +@app.route('/nonce-truncation', methods=['GET', 'POST']) +def nonce_truncation(): + form = NonceTruncationForm(meta={'csrf': False}) + key = nonce = None + mf = '' + h = c_forged = mac = None + if form.is_submitted(): + key, nonce, mf = form.key.data, form.nonce.data, form.mf.data + if form.validate(): + skey = binascii.unhexlify(key) + snonce = binascii.unhexlify(nonce) + h, c_forged, mac = solve_nonce_truncation(skey, snonce, bytes(mf, 'utf-8')) + return render_template('nonce-truncation.html', form=form, key=key, nonce=nonce, + mf=mf, h=h, c_forged=c_forged, mac=mac) + +def solve_nonce_truncation(k, nonce, mf): + aad = b"" + m = secrets.token_bytes(512) + c, mac = gcm_encrypt(k, nonce, aad, m, mac_bytes=1) + + def oracle(base, aad, mac, nonce): + cipher = AES.new(k, mode=AES.MODE_GCM, nonce=nonce, mac_len=1) + cipher.update(aad) + cipher.decrypt_and_verify(base, mac) + h, s = nonce_truncation_recover_secrets(c, mac, nonce, 1, aad, oracle) + c_forged, aad_forged = xor(c, xor(m, mf)), b"" + mac = gmac(h, s, aad_forged, c_forged) + return gf128_to_bytes(h), c_forged, mac[:1] -- cgit v1.2.3