def weight(self, output_diff): x, y, z = [d.val for d in self.input_diff] def eq(x, y, z): return (~x ^ y) & (~x ^ z) pr1 = eq(x, y, z) return PopCount(~pr1)
def weight(self, output_diff): x, y, z = [d.val for d in self.input_diff] def eq(a, b): return ~a ^ b pr1 = ~x & eq(y, z) return PopCount(~pr1)
def test_PopCountExtra(self, width, x, y, z): bvx = Constant(x % (2 ** width), width) hwx = PopCount(bvx) bvy = Constant(y % (2 ** width), width) hwy = PopCount(bvy) bvz = Constant(z % (2 ** width), width) hwz = PopCount(bvz) popsum2 = PopCountSum2(bvx, bvy) popsum3 = PopCountSum3(bvx, bvy, bvz) popdiff = PopCountDiff(bvx, bvy) self.assertEqual( int(hwx) + int(hwy), int(popsum2)) self.assertEqual( int(hwx) + int(hwy) + int(hwz), int(popsum3)) self.assertEqual( (int(hwx) - int(hwy)) % (2 ** popdiff.width), int(popdiff))
def is_possible(self, output_diff): """Return whether the given output `XorDiff` is possible. >>> from arxpy.bitvector.core import Constant, Variable >>> from arxpy.bitvector.context import NotEvaluation >>> from arxpy.bitvector.printing import BvWrapPrinter >>> from arxpy.differential.difference import XorDiff >>> alpha = XorDiff(Constant(0, 16)) >>> f = XDSimonRF(alpha) >>> f.is_possible(XorDiff(Constant(0, 16))) 0b1 >>> u, v = Variable("u", 16), Variable("v", 16) >>> f = XDSimonRF(XorDiff(u)) >>> with NotEvaluation([PopCount]): ... result = f.is_possible(XorDiff(v)) >>> print(BvWrapPrinter().doprint(result)) Ite(0xffff == u, 0b0 == (PopCount(v ^ (u <<< 2))[0]), ==(0x0000, |(~(u <<< 8) & (u <<< 1) & (u <<< 15) & (v ^ (u <<< 2) ^ ((v ^ (u <<< 2)) <<< 7)), ~((u <<< 1) | (u <<< 8)) & (v ^ (u <<< 2)) >>> result.xreplace({u: Constant(0, 16), v: Constant(0, 16)}) 0b1 See `Derivative.is_possible` for more information. """ a, b, c = self.op.a, self.op.b, self.op.c n = self.input_diff[0].val.width assert math.gcd(n, a - b) == 1 and a > b and n % 2 == 0 alpha = self.input_diff[0].val Rol = RotateLeft varibits = Rol(alpha, a) | Rol(alpha, b) r = (2 * a - b) % n doublebits = (Rol(alpha, b) & (~Rol(alpha, a)) & Rol(alpha, r)) beta = output_diff.val gamma = beta ^ Rol(alpha, c) def is_even(x): return BvComp(x[0], Constant(0, 1)) case2 = BvComp(Constant(0, n), (gamma & (~varibits)) | ((gamma ^ Rol(gamma, a - b)) & doublebits)) condition = Ite(BvComp(alpha, ~Constant(0, n)), is_even(PopCount(gamma)), case2) return condition
def test_extraop(self, width, x): bv = Constant(x % (2 ** width), width) hw = PopCount(bv) rev = Reverse(bv) lz = LeadingZeros(bv) lz_bf = "" for i in bv.bin()[2:]: if i == "0": lz_bf += "1" else: break lz_bf += "0"*(bv.width - len(lz_bf)) self.assertEqual(int(hw), bin(int(bv)).count("1")) self.assertEqual(rev.bin()[2:], bv.bin()[2:][::-1]) self.assertEqual(lz.bin()[2:], lz_bf)
def weight(self, output_diff): """Return the weight of a possible output `XorDiff`. >>> from arxpy.bitvector.core import Constant, Variable >>> from arxpy.bitvector.context import NotEvaluation >>> from arxpy.bitvector.printing import BvWrapPrinter >>> from arxpy.bitvector.extraop import PopCount >>> from arxpy.differential.difference import XorDiff >>> alpha = XorDiff(Constant(0, 16)) >>> f = XDSimonRF(alpha) >>> f.weight(XorDiff(Constant(0, 16))) 0b00000 >>> alpha = XorDiff(Variable("u", 16)) >>> f = XDSimonRF(alpha) >>> beta = XorDiff(Variable("v", 16)) >>> with NotEvaluation([PopCount]): ... print(BvWrapPrinter().doprint(f.weight(beta))) Ite(0xffff == u, 0b01111, PopCount((~(u <<< 8) & (u <<< 1) & (u <<< 15)) ^ ((u <<< 1) | (u <<< 8))) See `Derivative.weight` for more information. """ a, b = self.op.a, self.op.b n = self.input_diff[0].val.width alpha = self.input_diff[0].val Rol = RotateLeft varibits = Rol(alpha, a) | Rol(alpha, b) r = (2 * a - b) % n doublebits = (Rol(alpha, b) & (~Rol(alpha, a)) & Rol(alpha, r)) hw = PopCount(varibits ^ doublebits) width = max((n - 1).bit_length(), hw.width) value = Ite(BvComp(alpha, ~Constant(0, n)), Constant(n - 1, width), ZeroExtend(hw, width - hw.width)) return value
def weight(self, output_diff): dx, dy = [d.val for d in self.input_diff] return PopCount(dx | dy)