This page uses content from Wikipedia and is licensed under CC BY-SA.
In mathematics, finite field arithmetic is arithmetic in a finite field (a field containing a finite number of elements) as opposed to arithmetic in a field with an infinite number of elements, like the field of rational numbers.
While no finite field is infinite, there are infinitely many different finite fields. Their number of elements is necessarily of the form p^{n} where p is a prime number and n is a positive integer, and two finite fields of the same size are isomorphic. The prime p is called the characteristic of the field, and the positive integer n is called the dimension of the field over its prime field.
Finite fields are used in a variety of applications, including in classical coding theory in linear block codes such as BCH codes and Reed–Solomon error correction and in cryptography algorithms such as the Rijndael (AES) encryption algorithm.
The finite field with p^{n} elements is denoted GF(p^{n}) and is also called the Galois Field, in honor of the founder of finite field theory, Évariste Galois. GF(p), where p is a prime number, is simply the ring of integers modulo p. That is, one can perform operations (addition, subtraction, multiplication) using the usual operation on integers, followed by reduction modulo p. For instance, in GF(5), 4 + 3 = 7 is reduced to 2 modulo 5. Division is multiplication by the inverse modulo p, which may be computed using the extended Euclidean algorithm.
A particular case is GF(2), where addition is exclusive OR (XOR) and multiplication is AND. Since the only invertible element is 1, division is the identity function.
Elements of GF(p^{n}) may be represented as polynomials of degree strictly less than n over GF(p). Operations are then performed modulo R where R is an irreducible polynomial of degree n over GF(p), for instance using polynomial long division. The addition of two polynomials P and Q is done as usual; multiplication may be done as follows: compute W = P⋅Q as usual, then compute the remainder modulo R (there exist better ways to do this).
When the prime is 2, it is conventional to express elements of GF(p^{n}) as binary numbers, with each term in a polynomial represented by one bit in the corresponding element's binary expression. Braces ( "{" and "}" ) or similar delimiters are commonly added to binary numbers, or to their hexadecimal equivalents, to indicate that the value is an element of a field. For example, the following are equivalent representations of the same value in a characteristic 2 finite field:
Addition and subtraction are performed by adding or subtracting two of these polynomials together, and reducing the result modulo the characteristic.
In a finite field with characteristic 2, addition modulo 2, subtraction modulo 2, and XOR are identical. Thus,
Under regular addition of polynomials, the sum would contain a term 2x^{6}. This term becomes 0x^{6} and is dropped when the answer is reduced modulo 2.
Here is a table with both the normal algebraic sum and the characteristic 2 finite field sum of a few polynomials:
p_{1} | p_{2} | p_{1} + p_{2} (normal algebra) | p_{1} + p_{2} in GF(2^{n}) |
---|---|---|---|
x^{3} + x + 1 | x^{3} + x^{2} | 2x^{3} + x^{2} + x + 1 | x^{2} + x + 1 |
x^{4} + x^{2} | x^{6} + x^{2} | x^{6} + x^{4} + 2x^{2} | x^{6} + x^{4} |
x + 1 | x^{2} + 1 | x^{2} + x + 2 | x^{2} + x |
x^{3} + x | x^{2} + 1 | x^{3} + x^{2} + x + 1 | x^{3} + x^{2} + x + 1 |
x^{2} + x | x^{2} + x | 2x^{2} + 2x | 0 |
In computer science applications, the operations are simplified for finite fields of characteristic 2, also called GF(2^{n}) Galois fields, making these fields especially popular choices for applications.
Multiplication in a finite field is multiplication modulo an irreducible reducing polynomial used to define the finite field. (I.e., it is multiplication followed by division using the reducing polynomial as the divisor—the remainder is the product.) The symbol "•" may be used to denote multiplication in a finite field.
Rijndael uses the characteristic 2 finite field with 256 elements, which can also be called the Galois field GF(2^{8}). It employs the following reducing polynomial for multiplication:
For example, {53} • {CA} = {01} in Rijndael's field because
and
11111101111110 (mod) 100011011 ^100011011 01110000011110 ^100011011 0110110101110 ^100011011 010101110110 ^100011011 00100011010 ^100011011 000000001
(The elements {53} and {CA} are multiplicative inverses of one another since their product is 1.)
Multiplication in this particular finite field can also be done using a modified version of the "peasant's algorithm". Each polynomial is represented using the same binary notation as above. Eight bits is sufficient because only degrees 0 to 7 are possible in the terms of each (reduced) polynomial.
This algorithm uses three variables (in the computer programming sense), each holding an eight-bit representation. a and b are initialized with the multiplicands; p accumulates the product and must be initialized to 0.
At the start and end of the algorithm, and the start and end of each iteration, this invariant is true: a b + p is the product. This is obviously true when the algorithm starts. When the algorithm terminates, a or b will be zero so p will contain the product.
This algorithm generalizes easily to multiplication over other fields of characteristic 2, changing the lengths of a, b, and p and the value 0x1b appropriately.
The multiplicative inverse for an element a of a finite field can be calculated a number of different ways:
When developing algorithms for Galois field computation on small Galois fields, a common performance optimization approach is to find a generator g and use the identity:
to implement multiplication as a sequence of table look ups for the log_{g}(a) and g^{y} functions and an integer addition operation. This exploits the property that every finite field contains generators. In the Rijndael field example, the polynomial x + 1 (or {03}) is one such generator. A necessary but not sufficient condition for a polynomial to be a generator is to be irreducible.
This same strategy can be used to determine the multiplicative inverse with the identity:
Here, the order of the generator, |g|, is the number of non-zero elements of the field. In the case of GF(2^{8}) this is 2^{8} − 1 = 255. That is to say, for the Rijndael example: (x + 1)^{255} = 1. So this can be performed with two look up tables and an integer subtract. Using this idea for exponentiation also derives benefit:
This requires two table look ups, an integer multiplication and an integer modulo operation.
However, in cryptographic implementations, one has to be careful with such implementations since the cache architecture of many microprocessors leads to variable timing for memory access. This can lead to implementations that are vulnerable to a timing attack.
Here is some C code which will add, subtract, and multiply numbers in the characteristic 2 finite field of order 2^{8}, used for example by Rijndael algorithm or Reed–Solomon, using the Russian Peasant Multiplication algorithm:
/* Add two numbers in the GF(2^8) finite field */
uint8_t gadd(uint8_t a, uint8_t b) {
return a ^ b;
}
/* Subtract two numbers in the GF(2^8) finite field */
uint8_t gsub(uint8_t a, uint8_t b) {
return a ^ b;
}
/* Multiply two numbers in the GF(2^8) finite field defined
* by the polynomial x^8 + x^4 + x^3 + x + 1 = 0
* using the Russian Peasant Multiplication algorithm
* (the other way being to do carry-less multiplication followed by a modular reduction)
*/
uint8_t gmul(uint8_t a, uint8_t b) {
uint8_t p = 0; /* the product of the multiplication */
while (a && b) {
if (b & 1) /* if b is odd, then add the corresponding a to p (final product = sum of all a's corresponding to odd b's) */
p ^= a; /* since we're in GF(2^m), addition is an XOR */
if (a & 0x80) /* GF modulo: if a >= 128, then it will overflow when shifted left, so reduce */
a = (a << 1) ^ 0x11b; /* XOR with the primitive polynomial x^8 + x^4 + x^3 + x + 1 (0b1_0001_1011) – you can change it but it must be irreducible */
else
a <<= 1; /* equivalent to a*2 */
b >>= 1; /* equivalent to b // 2 */
}
return p;
}
This example has cache, timing, and branch prediction side-channel leaks, and is not suitable for use in cryptography.
This D program will multiply numbers in Rijndael's finite field and generate a PGM image:
/**
Multiply two numbers in the GF(2^8) finite field defined
by the polynomial x^8 + x^4 + x^3 + x + 1.
*/
ubyte gMul(ubyte a, ubyte b) pure nothrow {
ubyte p = 0;
foreach (immutable ubyte counter; 0 .. 8) {
p ^= -(b & 1) & a;
auto mask = -((a >> 7) & 1);
// 0b1_0001_1011 is x^8 + x^4 + x^3 + x + 1.
a = (a << 1) ^ (0b1_0001_1011 & mask);
b >>= 1;
}
return p;
}
void main() {
import std.stdio, std.conv;
enum width = ubyte.max + 1, height = width;
auto f = File("rijndael_finite_field_multiplication.pgm", "wb");
f.writefln("P5\n%d %d\n255", width, height);
foreach (immutable y; 0 .. height)
foreach (immutable x; 0 .. width) {
immutable char c = gMul(x.to!ubyte, y.to!ubyte);
f.write(c);
}
}
This example does not use any branches or table lookups in order to avoid side channels and is therefore suitable for use in cryptography.