# Galois Fields

### Galois Fields (aka Finite Fields)

* A Galois field is finite set of elements and two operations $$+$$ (addition) and $$\times$$ (multiplication), with the following properties:
  * **Closure**: if $$a$$ and $$b$$ are in the set, $$a + b$$ and $$a \times b$$ are also in the set.
  * **Additive identity**: $$a + 0 = a$$
  * **Multiplicative identity**: $$a \times 1 = a$$
  * **Additive inverse**: $$a + (-a) = 0$$&#x20;
  * **Multiplicative inverse**: $$a \times  a^-¹ = 1$$&#x20;
* Field size is the number of elements in the set.

{% hint style="info" %}
Elliptic curves that are defined over a finite field with a **prime field size** have interesting properties and are key to building of elliptic curve cryptographic protocols.
{% endhint %}

Let's define a `PrimeGaloisField` class that contains the intrinsic property of a finite field, `prime`. We also define a membership rule for a value in a given finite field, by overriding the `__contains__` method.

```python
@dataclass
class PrimeGaloisField:
    prime: int

    def __contains__(self, field_element: "FieldElement") -> bool:
        # called whenever you do: <FieldElement> in <PrimeGaloisField>
        return 0 <= field_element.value < self.prime
```

Let's also define a `FieldElement` class to make sure all mathematical operations are contained within a given `PrimeGaloisField`.

<pre class="language-python"><code class="lang-python"><strong>@dataclass
</strong>class FieldElement:
    value: int
    field: PrimeGaloisField

    def __repr__(self):
        return "0x" + f"{self.value:x}".zfill(64)
        
    @property
    def P(self) -> int:
        return self.field.prime
    
    def __add__(self, other: "FieldElement") -> "FieldElement":
        return FieldElement(
            value=(self.value + other.value) % self.P,
            field=self.field
        )
    
    def __sub__(self, other: "FieldElement") -> "FieldElement":
        return FieldElement(
            value=(self.value - other.value) % self.P,
            field=self.field
        )

    def __rmul__(self, scalar: int) -> "FieldElement":
        return FieldElement(
            value=(self.value * scalar) % self.P,
            field=self.field
        )

    def __mul__(self, other: "FieldElement") -> "FieldElement":
        return FieldElement(
            value=(self.value * other.value) % self.P,
            field=self.field
        )
        
    def __pow__(self, exponent: int) -> "FieldElement":
        return FieldElement(
            value=pow(self.value, exponent, self.P),
            field=self.field
        )

    def __truediv__(self, other: "FieldElement") -> "FieldElement":
        other_inv = other ** -1
        return self * other_inv
</code></pre>

{% hint style="info" %}
All parameters in an elliptic curve equation are actually elements in a given prime Galois field. This includes `a`,`b`,`x`, and`y`.
{% endhint %}
