예제 #1
0
def algebraic_normal_form_coordinate(s, i):
    """Returns the algebraic normal form of the `i`th coordinate of the
    SBox s.

    """
    coordinate = BooleanFunction([(x >> i) & 1 for x in list(s)])
    return coordinate.algebraic_normal_form()
예제 #2
0
    def linear_approximation_matrix(self):
        """
        Return linear approximation matrix ``A`` for this S-box.

        Let ``i_b`` be the ``b``-th bit of ``i`` and ``o_b`` the
        ``b``-th bit of ``o``. Then ``v = A[i,o]`` encodes the bias of
        the equation ``sum( i_b * x_i ) = sum( o_b * y_i )`` if
        ``x_i`` and ``y_i`` represent the input and output variables
        of the S-box.

        See [He2002]_ for an introduction to linear cryptanalysis.

        EXAMPLES::

            sage: from sage.crypto.sbox import SBox
            sage: S = SBox(7,6,0,4,2,5,1,3)
            sage: S.linear_approximation_matrix()
            [ 4  0  0  0  0  0  0  0]
            [ 0  0  0  0  2  2  2 -2]
            [ 0  0 -2 -2 -2  2  0  0]
            [ 0  0 -2  2  0  0 -2 -2]
            [ 0  2  0  2 -2  0  2  0]
            [ 0 -2  0  2  0  2  0  2]
            [ 0 -2 -2  0  0 -2  2  0]
            [ 0 -2  2  0 -2  0  0 -2]

        According to this matrix the first bit of the input is equal
        to the third bit of the output 6 out of 8 times::

            sage: for i in srange(8): print(S.to_bits(i)[0] == S.to_bits(S(i))[2])
            False
            True
            True
            True
            False
            True
            True
            True
        """
        m = self.m
        n = self.n

        nrows = 1<<m
        ncols = 1<<n

        B = BooleanFunction(self.m)
        L = []
        for j in range(ncols):
            for i in range(nrows):
                B[i] = ZZ(self(i)&j).popcount()
            L.append(B.walsh_hadamard_transform())

        A = Matrix(ZZ, ncols, nrows, L)
        A = -A.transpose()/2
        A.set_immutable()

        return A
예제 #3
0
파일: sbox.py 프로젝트: mcognetta/sage
    def linear_approximation_matrix(self):
        """
        Return linear approximation matrix ``A`` for this S-box.

        Let ``i_b`` be the ``b``-th bit of ``i`` and ``o_b`` the
        ``b``-th bit of ``o``. Then ``v = A[i,o]`` encodes the bias of
        the equation ``sum( i_b * x_i ) = sum( o_b * y_i )`` if
        ``x_i`` and ``y_i`` represent the input and output variables
        of the S-box.

        See [He2002]_ for an introduction to linear cryptanalysis.

        EXAMPLES::

            sage: from sage.crypto.sbox import SBox
            sage: S = SBox(7,6,0,4,2,5,1,3)
            sage: S.linear_approximation_matrix()
            [ 4  0  0  0  0  0  0  0]
            [ 0  0  0  0  2  2  2 -2]
            [ 0  0 -2 -2 -2  2  0  0]
            [ 0  0 -2  2  0  0 -2 -2]
            [ 0  2  0  2 -2  0  2  0]
            [ 0 -2  0  2  0  2  0  2]
            [ 0 -2 -2  0  0 -2  2  0]
            [ 0 -2  2  0 -2  0  0 -2]

        According to this matrix the first bit of the input is equal
        to the third bit of the output 6 out of 8 times::

            sage: for i in srange(8): print(S.to_bits(i)[0] == S.to_bits(S(i))[2])
            False
            True
            True
            True
            False
            True
            True
            True
        """
        m = self.m
        n = self.n

        nrows = 1<<m
        ncols = 1<<n

        B = BooleanFunction(self.m)
        L = []
        for j in range(ncols):
            for i in range(nrows):
                B[i] = ZZ(self(i)&j).popcount()
            L.append(B.walsh_hadamard_transform())

        A = Matrix(ZZ, ncols, nrows, L)
        A = -A.transpose()/2
        A.set_immutable()

        return A
def save_classifications_in_parallel(comm,
                                     name_prefix,
                                     list_of_f,
                                     start=0,
                                     stop=None,
                                     directory=None):
    r"""
    Using MPI, construct and save a number of Cayley graph classifications
    corresponding to a list of bent functions.

    INPUT:

    - ``comm`` -- MPI communicator.
    - ``name_prefix`` -- String. Name prefix to use with ``save_mangled`` to save each classification.
    - ``list_of_f`` -- List of forms or bent functions.
    - ``start`` -- Integer. Default=0. Index of start position in the list.
    - ``stop`` -- Integer. Default=None. Index after end position, or ``None`` if whole remaining list.
    - ``directory`` -- string, optional. The directory where the object
      is to be saved. Default is None, meaning the current directory.

    OUTPUT: None.

    EFFECT: Uses ``name`` to save the classifications corresponding to ``list_of_f``.
    """
    rank = comm.Get_rank()
    size = comm.Get_size()

    if stop == None:
        stop = len(list_of_f)
    for n in range(start + rank, stop, size):
        name = name_prefix + '_' + str(n)
        form = BooleanFunction(list_of_f[n]).truth_table(format='hex')
        save_one_classification(name, form, directory=directory)
예제 #5
0
    def component_function(self, b):
        r"""
        Return a Boolean function corresponding to the component function
        `b \cdot S(x)`.

        If `S` is an `m \times n` S-Box, then `b \in \GF{2}^n` and
        `\cdot` denotes dot product of two vectors.

        INPUT:

        - ``b`` -- either an integer or a tuple of `\GF{2}` elements of
          length ``self.n``

        EXAMPLES::

            sage: S = mq.SBox([7,6,0,4,2,5,1,3])
            sage: f3 = S.component_function(3)
            sage: f3.algebraic_normal_form()
            x0*x1 + x0*x2 + x0 + x2

            sage: f5 = S.component_function([1, 0, 1])
            sage: f5.algebraic_normal_form()
            x0*x2 + x0 + x1*x2
        """
        m = self.m
        n = self.n
        ret = BooleanFunction(m)

        if isinstance(b, (int, long, Integer)):
            b = vector(GF(2), self.to_bits(b, n))
        elif len(b) == n:
            b = vector(GF(2), b)
        else:
            raise TypeError(
                "cannot compute component function using parameter %s" % (b, ))

        for x in range(1 << m):
            ret[x] = bool(
                b.dot_product(vector(GF(2), self.to_bits(self(x), n))))
        return ret
예제 #6
0
    def __or__(self, other):
        """
        Return the concatenation of `self` and `other` which must have the same number of variables.

        INPUT:

        - ``self`` -- the current object.
        - ``other`` -- another Boolean function.

        OUTPUT:

        The concatenation of `self`and `other`

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf0 = BooleanFunctionImproved([1,0,1,0])
            sage: bf1 = BooleanFunctionImproved([1,1,0,0])
            sage: (bf0|bf1).truth_table(format='int')
            (1, 0, 1, 0, 1, 1, 0, 0)
            sage: C = bf0.truth_table() + bf1.truth_table()
            sage: (bf0|bf1).truth_table(format='int') == C
            True

        TESTS:

        ::

            sage: bf0|BooleanFunctionImproved([0,1])
            Traceback (most recent call last):
            ...
            ValueError: the two Boolean functions must have the same number of variables
        """
        bf_self = BooleanFunction(self)
        return type(self)(bf_self | other)
예제 #7
0
    def __mul__(self, other):
        """
        Return the elementwise product of `self`and `other` which must have the same number of variables.

        INPUT:

        - ``self`` -- the current object.
        - ``other`` -- another Boolean function.

        OUTPUT:

        The elementwise product of `self`and `other`

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf0 = BooleanFunctionImproved([1,0,1,0])
            sage: bf1 = BooleanFunctionImproved([1,1,0,0])
            sage: (bf0*bf1).truth_table(format='int')
            (1, 0, 0, 0)
            sage: P = bf0.algebraic_normal_form() * bf1.algebraic_normal_form()
            sage: (bf0*bf1).algebraic_normal_form() == P
            True

        TESTS:

        ::

            sage: bf0*BooleanFunctionImproved([0,1])
            Traceback (most recent call last):
            ...
            ValueError: the two Boolean functions must have the same number of variables
        """
        bf_self = BooleanFunction(self)
        return type(self)(bf_self * other)
예제 #8
0
    def __invert__(self):
        """
        Return the complement Boolean function of `self`.

        INPUT:

        - ``self`` -- the current object.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf0 = BooleanFunctionImproved([1,0,1,1])
            sage: bf1 = ~bf0
            sage: type(bf1)
            <class 'boolean_cayley_graphs.boolean_function_improved.BooleanFunctionImproved'>
            sage: bf1.algebraic_normal_form()
            x0*x1 + x0
            sage: bf1.truth_table()
            (False, True, False, False)
        """
        bf_self = BooleanFunction(self)
        return type(self)(~bf_self)
예제 #9
0
    if(tt[i] == 1):
        print(i)

#print(join_arr(get_cv(p)))

f = open("input","r")
arr = f.readlines()
f.close()
arr = arr[2:]


print(arr)

bfs = []
for i in range(0, len(arr)):
    print(len(arr[i][:-1]))
    bfs.append(BooleanFunction(arr[i][:-1]))













    CYCLE_LENGTHS[i] = len(CYCLES[i])
    if (CYCLE_LENGTHS[i] & _sage_const_0x1) != _sage_const_0:
        AT_LEAST_ONE_ODD_FLAG = _sage_const_1

print("The length of each cycle : "), (CYCLE_LENGTHS)
#start computing

_0_BASIS = range(NUM_CYCLES)
for i in range(NUM_CYCLES):
    Boolean_Table = range(S_BOX_CARDINALITY)
    for j in range(S_BOX_CARDINALITY):
        if j in CYCLES[i]:
            Boolean_Table[j] = _sage_const_1
        else:
            Boolean_Table[j] = _sage_const_0
    _0_BASIS[i] = BooleanFunction(Boolean_Table)
    if is_nonlinear_invariant(S_BOX, _0_BASIS[i]) is not True:
        print("Warning! "), (_0_BASIS[i].algebraic_normal_form()), (
            "is not a nonlinear invariant but it is got.")

#S-Box(x(n-1), x(n-2), ..., x0)
NUM_NON_INVARIANT = _sage_const_0
NUM_NON_INVARIANT_WITH_LINEAR_STRUCTURE = _sage_const_0
NUM_BALANCED_NON_INVARIANT_WITH_LINEAR_STRUCTURE = _sage_const_0

if AT_LEAST_ONE_ODD_FLAG == _sage_const_1:
    NUM_NON_INVARIANT = _sage_const_2**(NUM_CYCLES)
else:
    NUM_NON_INVARIANT = _sage_const_2**(NUM_CYCLES + _sage_const_1)

print("== Nonlinear Invariants Info of %s" % ALG_NAME)
예제 #11
0
# In[121]:


nf =   x0*x1*x2*x3*x4*x5 + x0*x1*x2*x3*x4 + x0*x1*x2*x3 + x0*x1*x2*x4 + x0*x1*x3*x4*x5 + x0*x1*x4*x5 + x0*x1*x4 + x0*x1*x5 + x0*x2*x3*x4 + x0*x2*x3*x5 + x0*x2*x3 + x0*x2*x4 + x0*x3*x4*x5 + x0*x3*x4 + x0*x3*x5 + x0*x3 + x0*x4 + x0*x5 + x0 + x1*x2*x3*x4*x5 + x1*x2*x3*x4 + x1*x2*x4 + x1*x2*x5 + x1*x3 + x1*x4*x5 + x1*x4 + x1*x5 + x1 + x2*x3*x4*x5 + x2*x3*x5 + x2*x3 + x2*x4*x5 + x2*x4 + x2*x5 + x2 + x3*x4*x5 + 1


# In[119]:


from sage.crypto.boolean_function import BooleanFunction

tb = [0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1]
tb = [0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0]

tb = [a^1 for a in tb]
func = BooleanFunction(tb)


# In[122]:


f2 = BooleanFunction(nf)
for a, b in zip(func.truth_table(), f2.truth_table()):
  print(a,b)


# In[125]:


print(func.algebraic_normal_form())
print(func.absolute_autocorrelation())
예제 #12
0
if S_BOX_CARDINALITY < ANALYSIS_BIT_RANGE:
    boolean = _sage_const_0x1 << S_BOX_CARDINALITY

    while boolean < (_sage_const_0x2 << S_BOX_CARDINALITY):

        boolean_table = [int(x) for x in bin(boolean)[_sage_const_3:]]
        minus_pow_boolean = boolean_to_minus_power(boolean_table)
        walsh_coeff = walsh_trasform(minus_pow_boolean)
        walsh_coeff_vec = vector(walsh_coeff)

        #Check if the walsh coefficient vector is the eigenvector of M with S_BOX_CARDINALITY or -S_BOX_CARDINALITY eigenvalues.
        if (walsh_coeff_vec in eigenspace_with_plus_size_value
                or walsh_coeff_vec in eigenspace_with_minus_size_value):
            NUM_NON_INVARIANT += _sage_const_1
            #Check if the nonlinear invariant has the linear structures.
            if BooleanFunction(
                    boolean_table).has_linear_structure() == _sage_const_1:
                NUM_NON_INVARIANT_WITH_LINEAR_STRUCTURE += _sage_const_1
                #Check if the nonlinear invariant is balanced.
                if BooleanFunction(
                        boolean_table).is_balanced() == _sage_const_1:
                    NUM_BALANCED_NON_INVARIANT_WITH_LINEAR_STRUCTURE += _sage_const_1
        boolean += _sage_const_1

    print("# of Nonlinear Invariants : %d" % NUM_NON_INVARIANT)
    print("# of Nonlinear Invariants with Linear Structure : %d" %
          NUM_NON_INVARIANT_WITH_LINEAR_STRUCTURE)
    print("# of Balanced Nonlinear Invariants with Linear Structure : %d" %
          NUM_BALANCED_NON_INVARIANT_WITH_LINEAR_STRUCTURE)
else:
    print("# of nonlinear invariants is too large to analyze.")
예제 #13
0
        [x15, x14, x13, x12, x11, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0],
        [
            _sage_const_2, _sage_const_2, _sage_const_2, _sage_const_2,
            _sage_const_2, _sage_const_2, _sage_const_2, _sage_const_2,
            _sage_const_2, _sage_const_2, _sage_const_2, _sage_const_2,
            _sage_const_2, _sage_const_2, _sage_const_2, _sage_const_2
        ])
else:
    print("The bit size of the S-box is not supported")
    exit

NUM_MONOMIALS = int(_sage_const_2**S_BOX_BIT_SIZE)
MONOMIALS_ANF_STR = range(NUM_MONOMIALS)

for i in range(NUM_MONOMIALS):
    MONOMIALS[i] = BooleanFunction(MONOMIALS[i])
    MONOMIALS_ANF_STR[i] = str(MONOMIALS[i].algebraic_normal_form())

NONLINEAR_INVARIANT_MATRIX = matrix(GF(_sage_const_2), NUM_MONOMIALS)
#compute NONLINEAR_INVARIANT_MATRIX
for row in range(NUM_MONOMIALS):
    for col in range(NUM_MONOMIALS):
        NONLINEAR_INVARIANT_MATRIX[row, col] = _sage_const_0

for mono_idx in range(NUM_MONOMIALS):
    mono_sbox = BooleanFunction(x0**(_sage_const_0))  # here "1"
    for var_idx in range(S_BOX_BIT_SIZE):
        if "x%d" % var_idx in MONOMIALS_ANF_STR[mono_idx]:
            mono_sbox = mono_sbox * S_BOX_BOOLEANS[var_idx]
    mono_plus_mono_sbox = MONOMIALS[mono_idx] + mono_sbox
    mono_plus_mono_sbox_anf_str = str(