public void McElieseGenericFormTest(int n, int k, int d, int t, int fieldPower, MatrixInt message, MatrixInt errorVector, MatrixInt scrambler, int[] permutation, int[] mask) { var galoisField = new GaloisField(2, fieldPower); var generator = new ParityCheckMatrixGeneratorEllyptic(2); var linearCode = new LinearCode(n, k, d, t, galoisField); while (true) { linearCode.ParityCheckMatrix = generator.Generate(linearCode); if (Helper.Weight(linearCode.ParityCheckMatrix) < Math.Ceiling(linearCode.ParityCheckMatrix.RowCount * linearCode.ParityCheckMatrix.ColumnCount * 0.7)) { continue; } try { linearCode.GeneratorMatrix = GeneratorMatrixCalculator.CalculateGeneratorMatrixAlt(linearCode); } catch (LinearCodeException ex) { Console.WriteLine(ex.Message); continue; } if (Helper.Weight(MatrixAlgorithms.DotMultiplication(linearCode.GeneratorMatrix, linearCode.ParityCheckMatrix.Transpose(), galoisField)) == 0) { linearCode.GeneratorMatrix = linearCode.GeneratorMatrix; break; } } var crytptogram = McElieseGenericForm.Encrypt(linearCode, scrambler, permutation, mask, generator, message, errorVector); var decryptedMessage = McElieseGenericForm.Decrypt(linearCode, permutation, mask, scrambler, generator, crytptogram); Assert.True(message == decryptedMessage); }
public static int[] LocateErrors(ILinearCode linearCode, MatrixInt syndrome, ParityCheckMatrixGeneratorEllyptic generator) { #region Error locator polynomial var rowCount = linearCode.T; var columnCount = linearCode.T + 1; var system = new int[rowCount, columnCount]; for (int row = 0; row < rowCount; row++) { for (int col = 0; col < columnCount - 1; col++) { system[row, col] = syndrome[0, generator.Terms[(row + col), linearCode.T - 2]]; } system[row, columnCount - 1] = syndrome[0, generator.Terms[row, linearCode.T - 1]]; } var coefficients = MatrixAlgorithms.Solve(new MatrixInt(system), linearCode.GaloisField).Transpose(); #endregion #region Calculate Error Positions var errorLocators = new int[linearCode.N]; for (int position = 0; position < linearCode.N; position++) { var sum = 0; for (int i = 0; i < linearCode.T; i++) { var wordToAdd = linearCode.GaloisField.MultiplyWords(coefficients[0, i], linearCode.GaloisField.Power(generator.Points[position].x, i)); sum = linearCode.GaloisField.AddWords(sum, wordToAdd); } sum = linearCode.GaloisField.AddWords(sum, generator.Points[position].y); errorLocators[position] = sum; } #endregion return(errorLocators); }
public static MatrixInt DecodeAndCorrect(ILinearCode linearCode, MatrixInt message, ParityCheckMatrixGeneratorEllyptic generator) { if (message.ColumnCount != linearCode.ParityCheckMatrix.ColumnCount) { throw new DimensionMismatchException("Incorrect length of message. Meesage length should be equal number of columns in parity check matrix."); } #region Calculate syndrome var syndrome = MatrixAlgorithms.DotMultiplication(message, linearCode.ParityCheckMatrix.Transpose(), linearCode.GaloisField); #endregion #region Locate errors var errorLocators = ErrorLocatorEllyptic.LocateErrors(linearCode, syndrome, generator); var errorCount = errorLocators.Where(v => v == 0).Count(); #endregion Debug.WriteLine(linearCode.ParityCheckMatrix); #region Caclulate Error vector var system = new MatrixInt(linearCode.D, errorCount); for (int row = 0; row < linearCode.D; row++) { for (int col = 0, i = 0; col < linearCode.N; col++) { if (errorLocators[col] == 0) { system[row, i] = linearCode.ParityCheckMatrix[row, col]; i++; } } } Debug.WriteLine(system); system |= syndrome.Transpose(); Debug.WriteLine(system); var errorVectorValues = MatrixAlgorithms.Solve(system, linearCode.GaloisField); var errorVector = new int[errorLocators.Length]; for (int i = 0, j = 0; i < errorVector.Length; i++) { if (errorLocators[i] == 0) { errorVector[i] = errorVectorValues[j, 0]; j++; } else { errorVector[i] = 0; } } #endregion var rawOriginalMessage = new int[linearCode.K]; for (int i = 0; i < linearCode.K; i++) { rawOriginalMessage[i] = linearCode.GaloisField.AddWords(message.Data[0, i + linearCode.D], errorVector[i + linearCode.D]); } var originalMessage = new MatrixInt(rawOriginalMessage); return(originalMessage); }
public static MatrixInt Decrypt(ILinearCode linearCode, IList <int> permutation, IList <int> mask, MatrixInt scramblerMatrix, ParityCheckMatrixGeneratorEllyptic generator, MatrixInt encryptedMessage) { var message = encryptedMessage.Clone(); #region Unmask for (int col = 0; col < message.ColumnCount; col++) { for (int row = 0; row < message.RowCount; row++) { message[row, col] = linearCode.GaloisField.MultiplyWords(message[row, col], linearCode.GaloisField.GetMultiplicativeInverse(mask[col])); } } #endregion Debug.WriteLine(message); #region Inverse permutation var inversePermutation = Helper.InversePermutation(permutation); message = message.PermuteColumns(inversePermutation); #endregion Debug.WriteLine(message); #region Correct Errors var correctedMessage = DecoderEllyptic.DecodeAndCorrect(linearCode, message, generator); #endregion Debug.WriteLine(correctedMessage); #region Apply the inverse scrambler matrix var inverseScramblerMatrix = MatrixAlgorithms.MatrixInverse(scramblerMatrix, linearCode.GaloisField); var decryptedMessage = MatrixAlgorithms.DotMultiplication(correctedMessage, inverseScramblerMatrix, linearCode.GaloisField); #endregion return(decryptedMessage); }
public static MatrixInt Encrypt(ILinearCode linearCode, MatrixInt scramblerMatrix, IList <int> permutation, IList <int> mask, ParityCheckMatrixGeneratorEllyptic generator, MatrixInt message, MatrixInt errorVector) { var encryptionMatrix = MatrixAlgorithms.DotMultiplication(scramblerMatrix, linearCode.GeneratorMatrix, linearCode.GaloisField); Debug.WriteLine(encryptionMatrix); encryptionMatrix = encryptionMatrix.PermuteColumns(permutation); Debug.WriteLine(encryptionMatrix); for (int col = 0; col < encryptionMatrix.ColumnCount; col++) { for (int row = 0; row < encryptionMatrix.RowCount; row++) { encryptionMatrix[row, col] = linearCode.GaloisField.MultiplyWords(encryptionMatrix[row, col], mask[col]); } } Debug.WriteLine(encryptionMatrix); var encryptedMessage = MatrixAlgorithms.DotMultiplication(message, encryptionMatrix, linearCode.GaloisField); for (int i = 0; i < encryptedMessage.ColumnCount; i++) { encryptedMessage[0, i] = linearCode.GaloisField.AddWords(encryptedMessage[0, i], errorVector[0, i]); } return(encryptedMessage); }
public McElieseEllyptic(int n, int k, int d, int t, GaloisField galoisField, MatrixInt scramblerMatrix = null, IList <int> permutation = null, IList <int> mask = null) { _generator = new ParityCheckMatrixGeneratorEllyptic(2); LinearCode = new LinearCode(n, k, d, t, galoisField); MatrixInt parityCheckMatrix = null; MatrixInt generatorMatrix = null; while (true) { parityCheckMatrix = _generator.Generate(LinearCode); LinearCode.ParityCheckMatrix = parityCheckMatrix; Debug.WriteLine(parityCheckMatrix); var minValueFillPercentage = 0.7; if (Helper.Weight(parityCheckMatrix) < Math.Ceiling(parityCheckMatrix.RowCount * parityCheckMatrix.ColumnCount * minValueFillPercentage)) { continue; } try { generatorMatrix = GeneratorMatrixCalculator.CalculateGeneratorMatrixAlt(LinearCode); Debug.WriteLine(generatorMatrix); } catch (LinearCodeException ex) { Debug.WriteLine(ex.Message); continue; } if (IsGeneratorMatrixValid(parityCheckMatrix, generatorMatrix, galoisField)) { LinearCode.GeneratorMatrix = generatorMatrix; break; } } if (scramblerMatrix is null) { scramblerMatrix = Helper.GenerateScramblerMatrix(LinearCode.K); while (true) { try { MatrixAlgorithms.MatrixInverse(scramblerMatrix, galoisField); break; } catch (SolveMatrixException) { Debug.WriteLine("Reattempting to generate scrambler matrix"); } } } if (permutation is null) { permutation = Helper.GeneratePermutaionList(LinearCode.N); } if (mask is null) { mask = Helper.GenerateMask(LinearCode.N, LinearCode.GaloisField); } var inverseMask = new List <int>(LinearCode.N); for (int i = 0; i < LinearCode.N; i++) { inverseMask.Add(LinearCode.GaloisField.GetMultiplicativeInverse(mask[i])); } PrivateKey = new PrivateKey { GeneratorMatrix = LinearCode.GeneratorMatrix, ScramblerMatrix = scramblerMatrix, InverseScramblerMatrix = MatrixAlgorithms.MatrixInverse(scramblerMatrix, galoisField), Permutation = permutation, InversePermutation = Helper.InversePermutation(permutation), Mask = mask, InverseMask = inverseMask }; var encryptionMatrix = MatrixAlgorithms.DotMultiplication(PrivateKey.ScramblerMatrix, generatorMatrix, LinearCode.GaloisField); Debug.WriteLine(encryptionMatrix); encryptionMatrix = encryptionMatrix.PermuteColumns(PrivateKey.Permutation); Debug.WriteLine(encryptionMatrix); for (int col = 0; col < encryptionMatrix.ColumnCount; col++) { for (int row = 0; row < encryptionMatrix.RowCount; row++) { encryptionMatrix[row, col] = LinearCode.GaloisField.MultiplyWords(encryptionMatrix[row, col], PrivateKey.Mask[col]); } } Debug.WriteLine(encryptionMatrix); PublicKey = new PublicKey { EncryptionMatrix = encryptionMatrix, }; }