arxpy.primitives.simon module

Simon family of block ciphers.

class arxpy.primitives.simon.SimonRF[source]

Bases: arxpy.bitvector.operation.Operation

The non-linear part of the round function of Simon.

This corresponds to ((x <<< a) & (x <<< b)) ^ (x <<< c), where (a, b, c) = (8, 1, 2).

classmethod output_width(x)[source]

Return the bit-width of the resulting bit-vector.

classmethod eval(x)[source]

Evaluate the operator with given operands.

This is an internal method. To evaluate a bit-vector operation, use the operator ().

class arxpy.primitives.simon.XDSimonRF(input_diff)[source]

Bases: arxpy.differential.derivative.Derivative

Represent the derivative of SimonRF w.r.t XOR differences.

>>> from arxpy.bitvector.core import Constant, Variable
>>> from arxpy.differential.difference import XorDiff
>>> alpha = XorDiff(Constant(0, 16))
>>> f = XDSimonRF(alpha)
>>> x = Constant(0, 16)
>>> f.eval(x)  # f(x + alpha) - f(x)
XorDiff(0x0000)
>>> f.max_weight(), f.error(), f.num_frac_bits()
(15, 0, 0)
diff_type

alias of arxpy.differential.difference.XorDiff

op

alias of SimonRF

is_possible(output_diff)[source]

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.

has_probability_one(output_diff)[source]

Return whether the input diff propagates to the output diff with probability one.

>>> from arxpy.bitvector.core import Constant, Variable
>>> from arxpy.differential.difference import XorDiff
>>> alpha = XorDiff(Constant(0, 16))
>>> f = XDSimonRF(alpha)
>>> f.has_probability_one(XorDiff(Constant(0, 16)))
0b1
weight(output_diff)[source]

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.

max_weight()[source]

Return the maximum value the weight can achieve.

exact_weight(output_diff)[source]

Return the weight without rounding to the closest integer.

It is assumed the exact weight is always smaller than the weight.

num_frac_bits()[source]

Return the number of fractional bits in the weight.

error()[source]

Return the maximum difference between the weight and the exact weight.

This method returns an upper bound (in absolute value) of the maximum difference (over all input and output difference) between the weight and the exact weight.

class arxpy.primitives.simon.SimonInstance[source]

Bases: enum.Enum

An enumeration.

arxpy.primitives.simon.get_Simon_instance(simon_instance)[source]

Return an instance of the Simon family.