public string Decrypt(VectorND cipher) { List <char> result = new List <char>(); int blockCount = cipher.dim / dim; for (int i = 0; i < blockCount; i++) { MatrixND cipherVector = new MatrixND(dim, 1); for (int j = 0; j < dim; j++) { cipherVector[j, 0] = (double)cipher.values[i * dim + j]; } MatrixND babai = privateKeyR1 * cipherVector; for (int j = 0; j < dim; j++) { babai[j, 0] = Math.Round(babai[j, 0]); } MatrixND messageVector = publicKeyB1 * privateKeyR * babai; for (int j = 0; j < dim; j++) { int messageInt = (int)Math.Round(messageVector[j, 0]); if (messageInt == 0) { break; } result.Add(Convert.ToChar(messageInt)); } } return(new string(result.ToArray())); }
public VectorND Encrypt(string message) { char[] chars = message.ToCharArray(); int rem; int blockCount = Math.DivRem(chars.Length, dim, out rem); if (rem > 0) { blockCount++; } VectorND cipher = new VectorND(dim * blockCount); for (int i = 0; i < blockCount; i++) { MatrixND messagePart = new MatrixND(dim, 1); for (int j = 0; j < dim && chars.Length > i * dim + j; j++) { messagePart[j, 0] = chars[i * dim + j]; } MatrixND cipherPart = publicKeyB * messagePart + errorVectorIntern; for (int j = 0; j < dim; j++) { cipher.values[i * dim + j] = (int)cipherPart[j, 0]; } } return(cipher); }
public GGHModel(int dim, int l, VectorND errorVector) { this.dim = dim; this.l = l; k = (int)Math.Round(l * Math.Sqrt(dim)); do { GeneratePrivateKey(); GeneratePublicKey(); } while (privateKeyR.Det() == 0 || publicKeyB.Det() == 0); privateKeyR1 = privateKeyR.Invert(); publicKeyB1 = publicKeyB.Invert(); GenerateLattice(); if (errorVector == null || errorVector.dim != dim) { GenerateErrorVector(); } else { this.errorVector = errorVector; errorVectorIntern = new MatrixND(dim, 1); for (int i = 0; i < dim; i++) { errorVectorIntern[i, 0] = (double)errorVector.values[i]; } } }
public MerkleHellmanModel(VectorND privateKey, BigInteger r, BigInteger mod) { dim = privateKey.dim; this.privateKey = privateKey; this.r = r; this.mod = mod; rI = ModInverse(r, mod); ComputePublicKey(); }
public VectorND Add(VectorND v2) { VectorND result = new VectorND(values.Length); for (int i = 0; i < dim; i++) { result.values[i] = values[i] + v2.values[i]; } return(result); }
public void SetErrorVectorManually(VectorND newErrorVector) { errorVector = newErrorVector; dim = newErrorVector.dim; errorVectorIntern = new MatrixND(dim, 1); for (int i = 0; i < dim; i++) { errorVectorIntern[i, 0] = (int)errorVector.values[i]; } }
public VectorND Multiply(BigInteger scalar) { VectorND result = new VectorND(values.Length); for (int i = 0; i < dim; i++) { result.values[i] = values[i] * scalar; } return(result); }
public BigInteger Multiply(VectorND v2) { BigInteger result = 0; for (int i = 0; i < dim; i++) { result += values[i] * v2.values[i]; } return(result); }
public VectorND GetMinimalReducedVector() { VectorND minimalVector = ReducedVectors[0]; foreach (VectorND reducedVector in ReducedVectors.Where(reducedVector => reducedVector.Length < minimalVector.Length)) { minimalVector = reducedVector; } return(minimalVector); }
public string Decrypt(VectorND vector) { BigInteger[] decryptVector = new BigInteger[vector.dim]; for (int i = 0; i < vector.dim; i++) { BigInteger bigInt = (vector.values[i] * rI) % mod; decryptVector[i] = bigInt; } string messageBinary = ""; for (int i = 0; i < decryptVector.Length; i++) { string blockPart = ""; for (int j = privateKey.dim - 1; j >= 0; j--) { if (decryptVector[i] >= privateKey.values[j]) { decryptVector[i] -= privateKey.values[j]; blockPart += "1"; } else { blockPart += "0"; } } //Beim letzten Block kürzen if (i == decryptVector.Length - 1) { int redudandBits = (messageBinary.Length + blockPart.Length) % maxBitLength; if (redudandBits > 0) { blockPart = blockPart.Remove(0, redudandBits); } if (blockPart.Length >= maxBitLength && blockPart.Substring(0, maxBitLength).IndexOf('1') == -1) { blockPart = blockPart.Remove(0, maxBitLength); } } blockPart = new string(blockPart.Reverse().ToArray()); messageBinary += blockPart; } List <byte> bytes = new List <byte>(); for (int i = 0; i < messageBinary.Length; i += maxBitLength) { bytes.Add(Convert.ToByte(messageBinary.Substring(i, maxBitLength), 2)); } return(Encoding.UTF8.GetString(bytes.ToArray())); }
private void ComputePublicKey() { publicKey = new VectorND(dim); for (int i = 0; i < dim; i++) { BigInteger bigInt = (privateKey.values[i] * r) % mod; publicKey.values[i] = bigInt; } Debug.WriteLine(publicKey); }
public LatticeND(int n, int m, bool transpose) { Vectors = new VectorND[n]; ReducedVectors = new VectorND[n]; N = n; M = m; for (int i = 0; i < N; i++) { Vectors[i] = new VectorND(M); } UseRowVectors = transpose; }
public void GaussianReduce() { ReductionMethod = ReductionMethods.reduceGauss; VectorND v1 = Vectors[0]; VectorND v2 = Vectors[1]; ReductionSteps = new List <VectorND[]>(); UnimodTransVectors = new VectorND[2]; VectorND u1 = new VectorND(new BigInteger[] { 1, 0 }); VectorND u2 = new VectorND(new BigInteger[] { 0, 1 }); BigInteger rem; do { if (v1.Length > v2.Length) { Util.Swap(ref v1, ref v2); Util.Swap(ref u1, ref u2); ReductionSteps.Add(new[] { v1, v2 }); } BigInteger t = BigInteger.DivRem(v1 * v2, v1.LengthSquared, out rem); //Bei der Division von BigIntegers muss noch auf korrektes Runden geprüft werden if (BigInteger.Abs(rem) > v1.LengthSquared / 2) { t += rem.Sign; } v2 = v2 - v1 * t; u2 = u2 - u1 * t; ReductionSteps.Add(new[] { v1, v2 }); } while (v1.Length > v2.Length); //Damit ein spitzer Winkel entsteht if (Settings.Default.forceAcuteAngle) { BigInteger.DivRem(v1 * v2, v1.LengthSquared, out rem); if (rem.Sign == -1) { v2 = v2 * -1; u2 = u2 * -1; ReductionSteps.Add(new[] { v1, v2 }); } } ReducedVectors[0] = v1; ReducedVectors[1] = v2; UnimodTransVectors = new[] { u1, u2 }; AngleReducedVectors = ReducedVectors[0].AngleBetween(ReducedVectors[1]); CalculateDensity(); }
public void GenerateErrorVector() { Random random = new Random(); errorVector = new VectorND(dim); errorVectorIntern = new MatrixND(dim, 1); for (int i = 0; i < dim; i++) { int randomSigma = random.NextDouble() < 0.5 ? sigma : -sigma; errorVector.values[i] = randomSigma; errorVectorIntern[i, 0] = randomSigma; } }
public LatticeND(VectorND[] vectors, bool useRowVectors) { Vectors = vectors; UseRowVectors = useRowVectors; N = vectors.Length; M = vectors[0].dim; ReducedVectors = new VectorND[N]; if (N == M) { Determinant = CalculateDeterminant(Vectors); } if (Vectors.Length == 2) { AngleBasisVectors = Vectors[0].AngleBetween(Vectors[1]); } }
public void GenerateLattice() { lattice = new LatticeND(dim, dim, false); //Umwandlung der Matrizeneinträge von double zu BigInt und damit Umwandlung der Matrizen zu einem Gitter VectorND[] privateVectors = new VectorND[dim]; for (int i = 0; i < dim; i++) { BigInteger[] privateBigInts = new BigInteger[dim]; for (int j = 0; j < dim; j++) { privateBigInts[j] = new BigInteger(privateKeyR[j, i]); } privateVectors[i] = new VectorND(privateBigInts); } lattice.ReducedVectors = privateVectors; VectorND[] publicVectors = new VectorND[dim]; for (int i = 0; i < dim; i++) { BigInteger[] publicBigInts = new BigInteger[dim]; for (int j = 0; j < dim; j++) { publicBigInts[j] = new BigInteger(publicKeyB[j, i]); } publicVectors[i] = new VectorND(publicBigInts); } lattice.Vectors = publicVectors; if (transU == null) { return; } VectorND[] transVectors = new VectorND[dim]; for (int i = 0; i < dim; i++) { BigInteger[] transBigInts = new BigInteger[dim]; for (int j = 0; j < dim; j++) { transBigInts[j] = new BigInteger(transU[j, i]); } transVectors[i] = new VectorND(transBigInts); } lattice.UnimodTransVectors = transVectors; }
public GGHModel(int dim, MatrixND privateKeyR, MatrixND publicKeyB, VectorND errorVector) { this.dim = dim; this.privateKeyR = privateKeyR; this.publicKeyB = publicKeyB; privateKeyR1 = privateKeyR.Invert(); publicKeyB1 = publicKeyB.Invert(); GenerateLattice(); this.errorVector = errorVector; errorVectorIntern = new MatrixND(dim, 1); for (int i = 0; i < dim; i++) { errorVectorIntern[i, 0] = (double)errorVector.values[i]; } }
public void GenerateRandomVectors(bool checkForGoodBasis, BigInteger codomainStart, BigInteger codomainEnd) { VectorND[] newVectorNds = new VectorND[N]; BigInteger det = 0; int counter = 0; while (true) { for (int i = 0; i < N; i++) { BigInteger[] vector = new BigInteger[M]; newVectorNds[i] = new VectorND(M); for (int j = 0; j < M; j++) { vector[j] = Util.ComputeRandomBigInt(codomainStart, codomainEnd); } for (int k = 0; k < vector.Length; k++) { newVectorNds[i].values[k] = vector[k]; } } if (N == M) { det = CalculateDeterminant(newVectorNds); } if ((N != M || det != 0) && (!checkForGoodBasis || IsGoodBasis(newVectorNds))) { break; } counter++; if (counter > 1024) { throw new Exception(Languages.errorFailedToGenerateLattice); } } Vectors = (VectorND[])newVectorNds.Clone(); Determinant = det; if (Vectors.Length == 2) { AngleBasisVectors = Vectors[0].AngleBetween(Vectors[1]); } }
public void Transpose() { VectorND[] tempVectors = (VectorND[])Vectors.Clone(); int tempN = N; N = M; M = tempN; Vectors = new VectorND[N]; for (int i = 0; i < N; i++) { Vectors[i] = new VectorND(M); for (int j = 0; j < M; j++) { Vectors[i].values[j] = tempVectors[j].values[i]; } } }
private void GenerateSuperincreasingSequence() { List <BigInteger> values = new List <BigInteger>(dim); BigInteger tempGenMult = generatingMultiplicator; bool sequenceFound = false; while (!sequenceFound) { for (int i = 0; i < dim; i++) { BigInteger sum = Util.Sum(values); if (sum == 0) { sum = 1; } values.Add(Util.ComputeRandomBigInt(sum + 1, sum * tempGenMult)); } double density = dim / BigInteger.Log(values[dim - 1], 2); if (density > 0.646 || !IsSuperincreasingSequence(values)) { tempGenMult *= 2; values = new List <BigInteger>(dim); } else { sequenceFound = true; } } //Könnte hier weg und stattdessen in der dazugehörigen Test-Methode verwendet werden //if (!IsSuperincreasingSequence(values)) // throw new Exception(Languages.errorGeneratingSuperincSequence); privateKey = new VectorND(values.ToArray()); Debug.WriteLine(privateKey); }
public string Cryptanalysis(VectorND cipher, Paragraph paragraph) { string messageBinary = ""; foreach (BigInteger value in cipher.values) { //BigInteger tempValue = value; LatticeND lattice = TransformToLattice(value); //Anmerkung: Der zweite Versuch nach LAGARIAS/ODLYZKO, S.232 funktioniert leider nicht, //daher wurde dieser Teil auskommentiert //for (int j = 0; j <= 1; j++) //{ lattice.LLLReduce(); BigInteger[] vector = FindBinaryVector(lattice.ReducedVectors, value); // if (vector != null) // break; // //Zweiter Versuch // tempValue = Util.Sum(publicKey.ToList()) - tempValue; // lattice = TransformToLattice(tempValue); //} if (vector == null) { throw new Exception(); } if (paragraph != null) { paragraph.Inlines.Add("--------------------\r\n"); paragraph.Inlines.Add(new Bold(new Run(Languages.labelCurrentBlock))); paragraph.Inlines.Add(" " + value + "\r\n"); paragraph.Inlines.Add(new Bold(new Run(Languages.labelLatticeBasis))); paragraph.Inlines.Add(" " + lattice.LatticeToString() + "\r\n"); paragraph.Inlines.Add(new Bold(new Run(Languages.labelReducedLatticeBasis))); paragraph.Inlines.Add(" " + lattice.LatticeReducedToString() + "\r\n"); paragraph.Inlines.Add(new Bold(new Run(Languages.labelFoundVector))); paragraph.Inlines.Add(" " + new VectorND(vector) + "\r\n"); } for (int k = 0; k < dim; k++) { messageBinary += vector[k]; } } int redudandBits = (messageBinary.Length) % maxBitLength; if (redudandBits > 0) { messageBinary = messageBinary.Remove(messageBinary.Length - redudandBits); } if (messageBinary.Length >= maxBitLength && messageBinary.Substring(messageBinary.Length - maxBitLength).IndexOf('1') == -1) { messageBinary = messageBinary.Remove(messageBinary.Length - maxBitLength); } if (paragraph != null) { paragraph.Inlines.Add("--------------------\r\n"); paragraph.Inlines.Add(new Bold(new Run(Languages.labelPlainTextBinary))); paragraph.Inlines.Add(" " + messageBinary + "\r\n"); } List <byte> bytes = new List <byte>(); for (int i = 0; i < messageBinary.Length; i += maxBitLength) { bytes.Add(Convert.ToByte(messageBinary.Substring(i, maxBitLength), 2)); } string messageUTF8 = Encoding.UTF8.GetString(bytes.ToArray()); if (paragraph != null) { paragraph.Inlines.Add(new Bold(new Run(Languages.labelPlainTextUTF8))); paragraph.Inlines.Add(" " + messageUTF8 + "\r\n"); } return(messageUTF8); }
public double AngleBetween(VectorND v2) { return(Math.Acos(((double)Multiply(v2) / (Length * v2.Length))) * (180 / Math.PI)); }
public void LLLReduce() { ReductionMethod = ReductionMethods.reduceLLL; BigInteger[,] basisArray = new BigInteger[N, M]; BigInteger[,] transArray = new BigInteger[N, N]; List <BigInteger[, ]> stepList = new List <BigInteger[, ]>(); for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { basisArray[i, j] = Vectors[i].values[j]; } } using (var nativeObject = new NTL_Wrapper()) { nativeObject.LLLReduce(basisArray, transArray, stepList, N, M, 0.99); } ReducedVectors = new VectorND[N]; for (int i = 0; i < N; i++) { ReducedVectors[i] = new VectorND(M); for (int j = 0; j < M; j++) { ReducedVectors[i].values[j] = basisArray[i, j]; } } if (M == 2 && N == 2) { AngleReducedVectors = ReducedVectors[0].AngleBetween(ReducedVectors[1]); CalculateDensity(); } UnimodTransVectors = new VectorND[N]; for (int i = 0; i < N; i++) { UnimodTransVectors[i] = new VectorND(N); for (int j = 0; j < N; j++) { UnimodTransVectors[i].values[j] = transArray[i, j]; } } ReductionSteps = new List <VectorND[]>(); foreach (var step in stepList) { VectorND[] stepVectors = new VectorND[N]; for (int i = 0; i < N; i++) { stepVectors[i] = new VectorND(M); for (int j = 0; j < M; j++) { stepVectors[i].values[j] = step[i, j]; } } ReductionSteps.Add(stepVectors); } }