/// <summary> /// Gets an array of round constants (known as rcon in literature) used by the key schedule. /// </summary> /// <param name="maxRound">The maximum number of rounds needed.</param> /// <returns>An array of round constants (known as rcon in literature) used by the key schedule.</returns> public static byte[] GetRoundConstants(int maxRound) { byte[] result = new byte[maxRound]; result[0] = 0; result[1] = 0x01; for (int i = 2; i < maxRound; i++) { result[i] = FiniteFieldMath.XTime(result[i - 1]); } return(result); }
private static byte[] CalculateSBox(out byte[] invSBox) { byte[] result = new byte[256]; invSBox = new byte[256]; // We use an int since a byte would cause this to loop forever due to overflow for (int i = 0; i < 256; i++) { byte currentByte = (byte)i; result[i] = FiniteFieldMath.F(FiniteFieldMath.G(currentByte)); invSBox[result[i]] = currentByte; } return(result); }
protected override void InverseLayer(State state) { byte[] tempVector = new byte[4]; for (int col = 0; col < state.Columns; col++) { ByteMatrixColumn currentColumn = state.GetColumn(col); // Multiply each column by d(x) which is the inverse of c(x). This means: // c(x) * d(x) ≡ 1, which expanded is // (03*x^3 ⊕ 01*x^2 ⊕ 01*x ⊕ 02) * d(x) ≡ 1 // After some derivation, we can calculate that // d(x) = 0B*x^3 ⊕ 0D*x^2 ⊕ 09*x ⊕ 0E; // This is the same as multiplication by this matrix: // | 0E 0B 0D 09 | | x0 | // | 09 0E 0B 0D | | x1 | // | 0D 09 0E 0B | * | x2 | // | 0B 0D 09 0E | | x3 | // We can perform this multiply by starting with the top row of the matrix: // [0E 0B 0D 09] and keep rotating it by 1 each column. Note that the multiply // is in the Rijndael field. for (int row = 0; row < 4; row++) { tempVector[row] = (byte)( FiniteFieldMath.Multiply(0x0E, currentColumn[row]) ^ FiniteFieldMath.Multiply(0x0B, currentColumn[(row + 1) % 4]) ^ FiniteFieldMath.Multiply(0x0D, currentColumn[(row + 2) % 4]) ^ FiniteFieldMath.Multiply(0x09, currentColumn[(row + 3) % 4])); } // Now that we have the result of the multiply in tempVector, we // copy it back to the state matrix: for (int row = 0; row < 4; row++) { currentColumn[row] = tempVector[row]; } } }
protected override void ApplyLayer(State state) { byte[] tempVector = new byte[4]; for (int col = 0; col < state.Columns; col++) { ByteMatrixColumn currentColumn = state.GetColumn(col); // Multiply each column by c(x) which is defined as // c(x) = 03*x^3 ⊕ 01*x^2 ⊕ 01*x ⊕ 02; // This is the same as multiplication by this matrix: // | 02 03 01 01 | | x0 | // | 01 02 03 01 | | x1 | // | 01 01 02 03 | * | x2 | // | 03 01 01 02 | | x3 | // We can perform this multiply by starting with the top row of the matrix: // [02 03 01 01] and keep rotating it by 1 each column. Note that the multiply // is in the Rijndael field. for (int row = 0; row < 4; row++) { tempVector[row] = (byte)( FiniteFieldMath.Multiply(0x02, currentColumn[row]) ^ FiniteFieldMath.Multiply(0x03, currentColumn[(row + 1) % 4]) ^ FiniteFieldMath.Multiply(0x01, currentColumn[(row + 2) % 4]) ^ FiniteFieldMath.Multiply(0x01, currentColumn[(row + 3) % 4])); } // Now that we have the result of the multiply in tempVector, we // copy it back to the state matrix: for (int row = 0; row < 4; row++) { currentColumn[row] = tempVector[row]; } } }
public Polynomial Sqrt(Polynomial sqr, Polynomial mod, Polynomial modDerivative, BigInteger sqrtNorm) { BigInteger max = 0; for (int i = 0; i <= sqr.Deg; i++) { if (BigInteger.Abs(sqr[i]) > max) { max = BigInteger.Abs(sqr[i]); } } var nextPrime = new NextPrime(); var bound = max * 10; var primes = new List <BigInteger>(); var sieve = new EratosthenesSieve(); var primesToCheck = sieve.GetPrimes(100000000, 110000000); BigInteger bigMod = 1; foreach (var primeToCheck in primesToCheck) { var irreducibilityTest = new IrreducibilityTest(); if (!irreducibilityTest.IsIrreducible(mod, primeToCheck)) { continue; } bigMod *= primeToCheck; primes.Add(primeToCheck); if (bigMod > bound) { break; } } var prime = 2 * primes[primes.Count - 1]; while (bigMod < bound) { prime = nextPrime.GetNext(prime); var irreducibilityTest = new IrreducibilityTest(); while (!irreducibilityTest.IsIrreducible(mod, prime)) { prime = nextPrime.GetNext(prime + 1); } bigMod *= prime; primes.Add(prime); } var sqrts = new List <Polynomial>(); foreach (var fieldChar in primes) { var polyMath = new PolynomialMath(fieldChar); var four = new Polynomial(new BigInteger[] { 4 }); Polynomial b; var isSqr = false; for (int i = 0; true; i++) { b = new Polynomial(new BigInteger[] { i }); var tmp = polyMath.ModPow(polyMath.Sub(polyMath.Mul(b, b), polyMath.Mul(four, sqr)), (BigInteger.Pow(fieldChar, mod.Deg) - 1) / 2, mod); isSqr = (tmp[0] == 1 || tmp[0] == -(fieldChar - 1)) && (tmp.Deg == 0); if (!isSqr) { break; } } var gfMath = new FiniteFieldMath(mod, fieldChar); var modPoly = new PolynomialOverFiniteField(new Polynomial[] { sqr, b, new Polynomial(new BigInteger[] { 1 }) }); var y = new PolynomialOverFiniteField(new Polynomial[] { new Polynomial(new BigInteger[] { 0 }), new Polynomial(new BigInteger[] { 1 }) }); var sqrt = gfMath.ModPow(y, (BigInteger.Pow(fieldChar, mod.Deg) + 1) / 2, modPoly)[0]; var sqrtNormMod = sqrtNorm * polyMath.ModPow(modDerivative, (BigInteger.Pow(fieldChar, mod.Deg) - 1) / (fieldChar - 1), mod)[0]; var norm = polyMath.ModPow(sqrt, (BigInteger.Pow(fieldChar, mod.Deg) - 1) / (fieldChar - 1), mod)[0]; sqrtNormMod %= fieldChar; if (sqrtNormMod < 0) { sqrtNormMod = sqrtNormMod + fieldChar; } if (norm < 0) { norm = norm + fieldChar; } if (norm != sqrtNormMod) { sqrt = polyMath.ConstMul(-1, sqrt); } sqrts.Add(sqrt); } BigInteger[] result = new BigInteger[mod.Deg]; var crt = new GarnerCrt(); for (int i = 0; i < mod.Deg; i++) { var coefficients = new List <BigInteger>(); for (int j = 0; j < primes.Count; j++) { coefficients.Add(sqrts[j][i]); } result[i] = crt.Calculate(coefficients, primes); } var resultPoly = new Polynomial(result); for (int i = 0; i <= resultPoly.Deg; i++) { var coeff = BigInteger.Abs(resultPoly[i]); if (coeff > max) { if (resultPoly[i] < 0) { resultPoly[i] += bigMod; } else { resultPoly[i] -= bigMod; } } } return(resultPoly); }