# Group Theory

## Group

## `Group`

This class generate a group self._g based on the operation (here denoted +) with the function ope: (a ** b) % n

In group theory, any group has an identity element (e), which with the binary operation, do not change the value and must satisfy the condition: $a + e = 0$

Attributes:

- `n` (`Integer`) –

  It's the G_n elements in the Group

- `g` (`List`) –

  The set of the Group

- `operation` (`Function`) –

  Function for generating the Group

- `identity` (`Integer`) –

  The identity of the group.

- `reverse` (`Dict`) –

  For each elements of the Group of n, we have the reverse value

Source code in `Cryptotools/Groups/group.py`

      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124

    class Group:
        """
            This class generate a group self._g based on the operation (here denoted +)
            with the function ope: (a ** b) % n

            In group theory, any group has an identity element (e), which with the binary operation, do not change the value and must satisfy the condition: $a + e = 0$

            Attributes:
                n (Integer): It's the G_n elements in the Group
                g (List): The set of the Group
                operation (Function): Function for generating the Group
                identity (Integer): The identity of the group.
                reverse (Dict): For each elements of the Group of n, we have the reverse value
        """
        def __init__(self, n, g, ope):
            self._n = n
            self._g = g
            self._operation = ope
            self._identity = 0
            self._reverse = dict()

        def getG(self) -> list():
            """
                This function return the Group

                Returns:
                    List of all elements in the Group
            """
            return self._g

        def closure(self) -> bool:
            """
                Check the closure law
                In a group, each element a, b belongs to G, such as a + b belongs to G

                Returns:
                    Return a Boolean if the closure law is respected. True if yes otherwise it's False
            """
            for e1 in self._g:
                for e2 in self._g:
                    res = self._operation(e1, e2, self._n)
                    if  not res in self._g:
                        # raise Exception(f"{res} not in g. g is not a group")
                        return False
            return True

        def associative(self) -> bool:
            """
                Check the associative law.
                In a group, for any a, b and c belongs to G,
                they must respect this condition: (a + b) + c = a + (a + b)

                Returns:
                    Return a boolean if the Associative law is respected. True if yes otherwise it's False
            """
            a = self._g[0]
            b = self._g[1]
            c = self._g[2]

            res_ope = self._operation(a, b, self._n)
            res1 = self._operation(res_ope, c, self._n)

            res_ope = self._operation(b, c, self._n)
            res2 = self._operation(a, res_ope, self._n)
            if res1 != res2:
                # raise Exception(f"{res1} is different from {res2}. g is not a group")
                return False
            return True

        def identity(self) -> bool:
            """
                Check the identity law.
                In a group, an identity element exist and must be uniq

                Returns:
                    Return a Boolean if the identity elements has been found. True if found otherwise it's False
            """
            for a in self._g:
                for b in self._g:
                    if not self._operation(a, b, self._n) == b:
                        break

                    self._identity = a
                    return True
            return False

        def getIdentity(self) -> int:
            """
                Return the identity element. The function identitu() must be called before.

                Returns:
                    Return the identity element if it has been found
            """
            return self._identity

        def reverse(self) -> bool:
            """
                Check the inverse law
                In a group, for each element belongs to G
                they must have an inverse a ^ (-1) = e (identity)

                Returns:
                    Return a Boolean if the all elements ha a reverse element. True if yes otherwise it's False
            """
            reverse = False
            for a in self._g:
                for b in self._g:
                    if self._operation(a, b, self._n) == self._identity:
                        self._reverse[a] = b
                        reverse = True
                        break
            return reverse

        def getReverses(self) -> dict:
            """
                This function return the dictionary of all reverses elements. The key is the element in G and the value is the reverse element

                Returns:
                    Return the reverse dictionary

            """
            return self._reverse

### `associative()`

Check the associative law. In a group, for any a, b and c belongs to G, they must respect this condition: (a + b) + c = a + (a + b)

Returns:

- `bool` –

  Return a boolean if the Associative law is respected. True if yes otherwise it's False

Source code in `Cryptotools/Groups/group.py`

    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70

    def associative(self) -> bool:
        """
            Check the associative law.
            In a group, for any a, b and c belongs to G,
            they must respect this condition: (a + b) + c = a + (a + b)

            Returns:
                Return a boolean if the Associative law is respected. True if yes otherwise it's False
        """
        a = self._g[0]
        b = self._g[1]
        c = self._g[2]

        res_ope = self._operation(a, b, self._n)
        res1 = self._operation(res_ope, c, self._n)

        res_ope = self._operation(b, c, self._n)
        res2 = self._operation(a, res_ope, self._n)
        if res1 != res2:
            # raise Exception(f"{res1} is different from {res2}. g is not a group")
            return False
        return True

### `closure()`

Check the closure law In a group, each element a, b belongs to G, such as a + b belongs to G

Returns:

- `bool` –

  Return a Boolean if the closure law is respected. True if yes otherwise it's False

Source code in `Cryptotools/Groups/group.py`

    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47

    def closure(self) -> bool:
        """
            Check the closure law
            In a group, each element a, b belongs to G, such as a + b belongs to G

            Returns:
                Return a Boolean if the closure law is respected. True if yes otherwise it's False
        """
        for e1 in self._g:
            for e2 in self._g:
                res = self._operation(e1, e2, self._n)
                if  not res in self._g:
                    # raise Exception(f"{res} not in g. g is not a group")
                    return False
        return True

### `getG()`

This function return the Group

Returns:

- `list()` –

  List of all elements in the Group

Source code in `Cryptotools/Groups/group.py`

    24
    25
    26
    27
    28
    29
    30
    31

    def getG(self) -> list():
        """
            This function return the Group

            Returns:
                List of all elements in the Group
        """
        return self._g

### `getIdentity()`

Return the identity element. The function identitu() must be called before.

Returns:

- `int` –

  Return the identity element if it has been found

Source code in `Cryptotools/Groups/group.py`

    89
    90
    91
    92
    93
    94
    95
    96

    def getIdentity(self) -> int:
        """
            Return the identity element. The function identitu() must be called before.

            Returns:
                Return the identity element if it has been found
        """
        return self._identity

### `getReverses()`

This function return the dictionary of all reverses elements. The key is the element in G and the value is the reverse element

Returns:

- `dict` –

  Return the reverse dictionary

Source code in `Cryptotools/Groups/group.py`

    116
    117
    118
    119
    120
    121
    122
    123
    124

    def getReverses(self) -> dict:
        """
            This function return the dictionary of all reverses elements. The key is the element in G and the value is the reverse element

            Returns:
                Return the reverse dictionary

        """
        return self._reverse

### `identity()`

Check the identity law. In a group, an identity element exist and must be uniq

Returns:

- `bool` –

  Return a Boolean if the identity elements has been found. True if found otherwise it's False

Source code in `Cryptotools/Groups/group.py`

    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87

    def identity(self) -> bool:
        """
            Check the identity law.
            In a group, an identity element exist and must be uniq

            Returns:
                Return a Boolean if the identity elements has been found. True if found otherwise it's False
        """
        for a in self._g:
            for b in self._g:
                if not self._operation(a, b, self._n) == b:
                    break

                self._identity = a
                return True
        return False

### `reverse()`

Check the inverse law In a group, for each element belongs to G they must have an inverse a ^ (-1) = e (identity)

Returns:

- `bool` –

  Return a Boolean if the all elements ha a reverse element. True if yes otherwise it's False

Source code in `Cryptotools/Groups/group.py`

     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114

    def reverse(self) -> bool:
        """
            Check the inverse law
            In a group, for each element belongs to G
            they must have an inverse a ^ (-1) = e (identity)

            Returns:
                Return a Boolean if the all elements ha a reverse element. True if yes otherwise it's False
        """
        reverse = False
        for a in self._g:
            for b in self._g:
                if self._operation(a, b, self._n) == self._identity:
                    self._reverse[a] = b
                    reverse = True
                    break
        return reverse

## Cyclic group

## `Cyclic`

Bases: `Group`

This object contain a list of the Group for a cyclic group. This class find all generator of the group. This class is inherited from Group object

Attributes:

- `G` (`list`) –

  list of all elements in the group

- `n` (`Integer`) –

  it's the value where the group has been generated

- `operation` (`Function`) –

  it's the operation generating the group

- `generators` (`list`) –

  contain all generators of the group

- `generatorChecked` (`boolean`) –

  Check if generators has been found

Source code in `Cryptotools/Groups/cyclic.py`

     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91

    class Cyclic(Group):
        """
            This object contain a list of the Group for a cyclic group. This class find all generator of the group.
            This class is inherited from Group object

            Attributes:
                G (list): list of all elements in the group
                n (Integer): it's the value where the group has been generated
                operation (Function): it's the operation generating the group
                generators (list): contain all generators of the group
                generatorChecked (boolean): Check if generators has been found
        """
        def __init__(self, G:list, n, ope):
            super().__init__(n, G, ope) # Call the Group's constructor
            self._G = G
            self._n = n
            self._operation = ope
            self._generators = list()
            self._generatorChecked = False

        def generator(self):
            """
                This function find all generators in the group G
            """

            index = 1
            G = sorted(self._g)
            for g in range(2, self._n):
                z = list()
                for entry in range(1, self._n):
                    res = self._operation(g, index, self._n)
                    if res not in z:
                        z.append(res)
                        index = index + 1

                # We check if that match with G
                # If yes, we find a generator
                if sorted(z) == G:
                    self._generators.append(g)
            self._generatorChecked = True

        def getPrimitiveRoot(self):
            """
                This function return the primitive root modulo of n

                Returns:
                    Return the primitive root of the group. None if no primitive has been found
            """

            index = 1
            G = sorted(self._g)
            for g in range(2, self._n):
                z = list()
                for entry in range(1, self._n):
                    res = self._operation(g, index, self._n)
                    if res not in z:
                        z.append(res)
                        index += 1

                # If the group is the same has G, we found a generator
                if sorted(z) == G:
                    return g
            return None

        def getGenerators(self) -> list:
            """
                This function return all generators of that group

                Returns:
                    Return the list of generators found. The function generators() must be called before to call this function
            """
            if not self._generatorChecked:
                self.generator()
                self._generatorChecked = True
            return self._generators

        def isCyclic(self) -> bool:
            """
                Check if the group is a cyclic group, means we have at least one generator

                Returns:
                    REturn a boolean, False if the group is not Cyclic otherwise return True
            """
            if len(self.getGenerators()) == 0:
                return False
            return True

### `generator()`

This function find all generators in the group G

Source code in `Cryptotools/Groups/cyclic.py`

    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45

    def generator(self):
        """
            This function find all generators in the group G
        """

        index = 1
        G = sorted(self._g)
        for g in range(2, self._n):
            z = list()
            for entry in range(1, self._n):
                res = self._operation(g, index, self._n)
                if res not in z:
                    z.append(res)
                    index = index + 1

            # We check if that match with G
            # If yes, we find a generator
            if sorted(z) == G:
                self._generators.append(g)
        self._generatorChecked = True

### `getGenerators()`

This function return all generators of that group

Returns:

- `list` –

  Return the list of generators found. The function generators() must be called before to call this function

Source code in `Cryptotools/Groups/cyclic.py`

    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80

    def getGenerators(self) -> list:
        """
            This function return all generators of that group

            Returns:
                Return the list of generators found. The function generators() must be called before to call this function
        """
        if not self._generatorChecked:
            self.generator()
            self._generatorChecked = True
        return self._generators

### `getPrimitiveRoot()`

This function return the primitive root modulo of n

Returns:

- –

  Return the primitive root of the group. None if no primitive has been found

Source code in `Cryptotools/Groups/cyclic.py`

    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68

    def getPrimitiveRoot(self):
        """
            This function return the primitive root modulo of n

            Returns:
                Return the primitive root of the group. None if no primitive has been found
        """

        index = 1
        G = sorted(self._g)
        for g in range(2, self._n):
            z = list()
            for entry in range(1, self._n):
                res = self._operation(g, index, self._n)
                if res not in z:
                    z.append(res)
                    index += 1

            # If the group is the same has G, we found a generator
            if sorted(z) == G:
                return g
        return None

### `isCyclic()`

Check if the group is a cyclic group, means we have at least one generator

Returns:

- `bool` –

  REturn a boolean, False if the group is not Cyclic otherwise return True

Source code in `Cryptotools/Groups/cyclic.py`

    82
    83
    84
    85
    86
    87
    88
    89
    90
    91

    def isCyclic(self) -> bool:
        """
            Check if the group is a cyclic group, means we have at least one generator

            Returns:
                REturn a boolean, False if the group is not Cyclic otherwise return True
        """
        if len(self.getGenerators()) == 0:
            return False
        return True

## Galois Field (Finite Field)

## `Galois`

This class contain the Galois Field (Finite Field)

Attributes:

- `q` (`Integer`) –

  it's the number of the GF

- `operation` (`Function`) –

  Function for generating the group

- `identityAdd` (`Integer`) –

  it's the identity element in the GF(n) for the addition operation

- `identityMul` (`Integer`) –

  it's the identity element in the GF(n) for the multiplicative operation

Source code in `Cryptotools/Groups/galois.py`

      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227

    class Galois:
        """
            This class contain the Galois Field (Finite Field)

            Attributes:
                q (Integer): it's the number of the GF
                operation (Function): Function for generating the group
                identityAdd (Integer): it's the identity element in the GF(n) for the addition operation
                identityMul (Integer): it's the identity element in the GF(n) for the multiplicative operation
        """
        def __init__(self, q, operation):
            self._q = q
            self._operation = operation
            self._identityAdd = 0
            self._identityMul = 1
            self._F = [x for x in range(q)]
            self._add = [[0 for x in range(q)] for y in range(q)]

            # TODO: May do we do a deep copy between all groups ?
            self._div = [[0 for x in range(q)] for y in range(q)]
            self._mul = [[0 for x in range(q)] for y in range(q)]
            self._sub = [[0 for x in range(q)] for y in range(q)]
            self._primitiveRoot = list()

        def primitiveRoot(self):
            """
                In this function, we going to find the primitive root modulo n of the galois field

                Returns:
                   Return the list of primitive root of the GF(q)
            """
            for x in range(2, self._q):
                z = list()
                for entry in range(1, self._q):
                    res = self._operation(x, entry, self._q)
                    if res not in z:
                        z.append(res)

                if self.isPrimitiveRoot(z, self._q - 1):
                    if x not in self._primitiveRoot: # It's dirty, need to find why we have duplicate entry
                        self._primitiveRoot.append(x)
            return z

        def getPrimitiveRoot(self):
            """
                Return the list of primitives root

                Returns:
                    Return the primitive root
            """
            return self._primitiveRoot

        def isPrimitiveRoot(self, z, length):
            """
                Check if z is a primitive root

                Args:
                    z (list): check if z is a primitive root
                    length (Integer): Length of the GF(q)
            """
            if len(z) == length:
                return True
            return False

        def add(self):
            """
                This function do the operation + on the Galois Field

                Returns:
                    Return a list of the group with the addition operation
            """
            for x in range(0, self._q):
                for y in range(0, self._q):
                    self._add[x][y] = (x + y) % self._q
            return self._add

        def _inverseModular(self, a, n):
            """
                This function find the reverse modular of a by n

                Returns:
                    Return the reverse modular
            """
            for b in range(1, n):
                if (a * b) % n == 1:
                    inv = b
                    break
            return inv

        def div(self):
            """
                This function do the operation / on the Galois Field

                Returns:
                    Return a list of the group with the division operation
            """
            for x in range(1, self._q):
                for y in range(1, self._q):
                    inv = self._inverseModular(y, self._q)

                    self._div[x][y] = (x * inv) % self._q
            return self._div

        def mul(self):
            """
                This function do the operation * on the Galois Field

                Returns:
                    Return a list of the group with the multiplication operation
            """
            for x in range(0, self._q):
                for y in range(0, self._q):
                    self._mul[x][y] = (x * y) % self._q
            return self._mul

        def sub(self):
            """
                This function do the operation - on the Galois Field

                Returns:
                    Return a list of the group with the subtraction operation
            """
            for x in range(0, self._q):
                for y in range(0, self._q):
                    self._sub[x][y] = (x - y) % self._q
            return self._sub

        def check_closure_law(self, arithmetic):
            """
                This function check the closure law.
                By definition, every element in the GF is an abelian group, which respect the closure law: for a and b belongs to G, a + b belongs to G, the operation is a binary operation

                Args:
                    Arithmetics (str): contain the operation to be made, must be '+', '*', '/' or /-'
            """
            if arithmetic not in ['+', '*', '/', '-']:
                raise Exception("The arithmetic need to be '+', '*', '/' or '-'")

            if arithmetic == '+':
                G = self._add
            elif arithmetic == '*':
                G = self._mul
            elif arithmetic == '/':
                G = self._div
            else:
                G = self._sub

            start = 0
            """
                In case of multiplicative, we bypass the first line, because all elements are zero, otherwise the test fail
            """
            if arithmetic == '*' or arithmetic == '/':
                start = 1

            isClosure = True
            for x in range(start, self._q):
                gr = Group(self._q, G[x], self._operation)
                if not gr.closure():
                    isClosure = False
                del gr

            if isClosure:
                print(f"The group {arithmetic} respect closure law")
            else:
                print(f"The group {arithmetic} does not respect closure law")

        def check_identity_add(self):
            """
                This function check the identity element and must satisfy this condition: $a + 0 = a$ for each element in the GF(n)
                In Group Theory, an identity element is an element in the group which do not change the value every element in the group

                Returns:

            """
            for x in self._F:
                if not self._identityAdd + x == x:
                    raise Exception(
                            f"The identity element {self._identityAdd} "\
                             "do not satisfy $a + element = a$"
                    )

        def check_identity_mul(self):
            """
                This function check the identity element and must satisfy this condition: $a * 1 = a$ for each element in the GF(n)
                In Group Theory, an identity element is an element in the group which do not change the value every element in the group

                Returns:

            """
            for x in self._F:
                if not self._identityMul * x == x:
                    raise Exception(
                            f"The identity element {self._identityAdd} "\
                             "do not satisfy $a * element = a$"
                    )

        def printMatrice(self, m):
            """
                This function print the GF(m)

                Args:
                    m (list): Matrix of the GF
            """
            header = str()
            header = "    "
            for x in range(0, self._q):
                header += f"{x} "

            header += "\n--|" + "-" * (len(header)- 3) +"\n"

            s = str()

            for x in range(0, self._q):
                s += f"{x} | "
                for y in range(0, self._q):
                    s += f"{m[x][y]} "
                s += "\n"

            s = header + s
            print(s)

### `add()`

This function do the operation + on the Galois Field

Returns:

- –

  Return a list of the group with the addition operation

Source code in `Cryptotools/Groups/galois.py`

    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82

    def add(self):
        """
            This function do the operation + on the Galois Field

            Returns:
                Return a list of the group with the addition operation
        """
        for x in range(0, self._q):
            for y in range(0, self._q):
                self._add[x][y] = (x + y) % self._q
        return self._add

### `check_closure_law(arithmetic)`

This function check the closure law. By definition, every element in the GF is an abelian group, which respect the closure law: for a and b belongs to G, a + b belongs to G, the operation is a binary operation

Parameters:

- `Arithmetics` (`str`) –

  contain the operation to be made, must be '+', '*', '/' or /-'

Source code in `Cryptotools/Groups/galois.py`

    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172

    def check_closure_law(self, arithmetic):
        """
            This function check the closure law.
            By definition, every element in the GF is an abelian group, which respect the closure law: for a and b belongs to G, a + b belongs to G, the operation is a binary operation

            Args:
                Arithmetics (str): contain the operation to be made, must be '+', '*', '/' or /-'
        """
        if arithmetic not in ['+', '*', '/', '-']:
            raise Exception("The arithmetic need to be '+', '*', '/' or '-'")

        if arithmetic == '+':
            G = self._add
        elif arithmetic == '*':
            G = self._mul
        elif arithmetic == '/':
            G = self._div
        else:
            G = self._sub

        start = 0
        """
            In case of multiplicative, we bypass the first line, because all elements are zero, otherwise the test fail
        """
        if arithmetic == '*' or arithmetic == '/':
            start = 1

        isClosure = True
        for x in range(start, self._q):
            gr = Group(self._q, G[x], self._operation)
            if not gr.closure():
                isClosure = False
            del gr

        if isClosure:
            print(f"The group {arithmetic} respect closure law")
        else:
            print(f"The group {arithmetic} does not respect closure law")

### `check_identity_add()`

This function check the identity element and must satisfy this condition: $a + 0 = a$ for each element in the GF(n) In Group Theory, an identity element is an element in the group which do not change the value every element in the group

Returns:

Source code in `Cryptotools/Groups/galois.py`

    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187

    def check_identity_add(self):
        """
            This function check the identity element and must satisfy this condition: $a + 0 = a$ for each element in the GF(n)
            In Group Theory, an identity element is an element in the group which do not change the value every element in the group

            Returns:

        """
        for x in self._F:
            if not self._identityAdd + x == x:
                raise Exception(
                        f"The identity element {self._identityAdd} "\
                         "do not satisfy $a + element = a$"
                )

### `check_identity_mul()`

This function check the identity element and must satisfy this condition: $a * 1 = a$ for each element in the GF(n) In Group Theory, an identity element is an element in the group which do not change the value every element in the group

Returns:

Source code in `Cryptotools/Groups/galois.py`

    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202

    def check_identity_mul(self):
        """
            This function check the identity element and must satisfy this condition: $a * 1 = a$ for each element in the GF(n)
            In Group Theory, an identity element is an element in the group which do not change the value every element in the group

            Returns:

        """
        for x in self._F:
            if not self._identityMul * x == x:
                raise Exception(
                        f"The identity element {self._identityAdd} "\
                         "do not satisfy $a * element = a$"
                )

### `div()`

This function do the operation / on the Galois Field

Returns:

- –

  Return a list of the group with the division operation

Source code in `Cryptotools/Groups/galois.py`

     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109

    def div(self):
        """
            This function do the operation / on the Galois Field

            Returns:
                Return a list of the group with the division operation
        """
        for x in range(1, self._q):
            for y in range(1, self._q):
                inv = self._inverseModular(y, self._q)

                self._div[x][y] = (x * inv) % self._q
        return self._div

### `getPrimitiveRoot()`

Return the list of primitives root

Returns:

- –

  Return the primitive root

Source code in `Cryptotools/Groups/galois.py`

    51
    52
    53
    54
    55
    56
    57
    58

    def getPrimitiveRoot(self):
        """
            Return the list of primitives root

            Returns:
                Return the primitive root
        """
        return self._primitiveRoot

### `isPrimitiveRoot(z, length)`

Check if z is a primitive root

Parameters:

- `z` (`list`) –

  check if z is a primitive root

- `length` (`Integer`) –

  Length of the GF(q)

Source code in `Cryptotools/Groups/galois.py`

    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70

    def isPrimitiveRoot(self, z, length):
        """
            Check if z is a primitive root

            Args:
                z (list): check if z is a primitive root
                length (Integer): Length of the GF(q)
        """
        if len(z) == length:
            return True
        return False

### `mul()`

This function do the operation * on the Galois Field

Returns:

- –

  Return a list of the group with the multiplication operation

Source code in `Cryptotools/Groups/galois.py`

    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121

    def mul(self):
        """
            This function do the operation * on the Galois Field

            Returns:
                Return a list of the group with the multiplication operation
        """
        for x in range(0, self._q):
            for y in range(0, self._q):
                self._mul[x][y] = (x * y) % self._q
        return self._mul

### `primitiveRoot()`

In this function, we going to find the primitive root modulo n of the galois field

Returns:

- –

  Return the list of primitive root of the GF(q)

Source code in `Cryptotools/Groups/galois.py`

    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49

    def primitiveRoot(self):
        """
            In this function, we going to find the primitive root modulo n of the galois field

            Returns:
               Return the list of primitive root of the GF(q)
        """
        for x in range(2, self._q):
            z = list()
            for entry in range(1, self._q):
                res = self._operation(x, entry, self._q)
                if res not in z:
                    z.append(res)

            if self.isPrimitiveRoot(z, self._q - 1):
                if x not in self._primitiveRoot: # It's dirty, need to find why we have duplicate entry
                    self._primitiveRoot.append(x)
        return z

### `printMatrice(m)`

This function print the GF(m)

Parameters:

- `m` (`list`) –

  Matrix of the GF

Source code in `Cryptotools/Groups/galois.py`

    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227

    def printMatrice(self, m):
        """
            This function print the GF(m)

            Args:
                m (list): Matrix of the GF
        """
        header = str()
        header = "    "
        for x in range(0, self._q):
            header += f"{x} "

        header += "\n--|" + "-" * (len(header)- 3) +"\n"

        s = str()

        for x in range(0, self._q):
            s += f"{x} | "
            for y in range(0, self._q):
                s += f"{m[x][y]} "
            s += "\n"

        s = header + s
        print(s)

### `sub()`

This function do the operation - on the Galois Field

Returns:

- –

  Return a list of the group with the subtraction operation

Source code in `Cryptotools/Groups/galois.py`

    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133

    def sub(self):
        """
            This function do the operation - on the Galois Field

            Returns:
                Return a list of the group with the subtraction operation
        """
        for x in range(0, self._q):
            for y in range(0, self._q):
                self._sub[x][y] = (x - y) % self._q
        return self._sub

« Previous Next »