/// <summary> /// This function generates a pair of public and private keys by following the /// steps to come up with values for p, q, N, r, E and D and combining them to /// make the respective keys. /// </summary> /// <param name="keySize">Bit size of keys to be generated </param> private void KeyGen(int keySize) { BigInteger p = msgOptions.Generate(keySize, 1); BigInteger q = msgOptions.Generate(1024 - keySize, 1); BigInteger N = BigInteger.Multiply(p, q); BigInteger r = BigInteger.Multiply(BigInteger.Subtract (p, 1), BigInteger.Subtract(q, 1)); BigInteger E = 65537; BigInteger D = PrimeCheckExtension.modInverse(E, r); var eBytes = E.ToByteArray(); var nBytes = N.ToByteArray(); var dBytes = D.ToByteArray(); var eByteLength = eBytes.Length; var nByteLength = nBytes.Length; var dByteLength = dBytes.Length; var eByteSize = BitConverter.GetBytes(eByteLength); var nByteSize = BitConverter.GetBytes(nByteLength); var dByteSize = BitConverter.GetBytes(dByteLength); if (BitConverter.IsLittleEndian) { Array.Reverse(eByteSize); Array.Reverse(nByteSize); Array.Reverse(dByteSize); } var publicKeyList = new List <byte[]>(); var privateKeyList = new List <byte[]>(); publicKeyList.Add(eByteSize); publicKeyList.Add(eBytes); publicKeyList.Add(nByteSize); publicKeyList.Add(nBytes); privateKeyList.Add(dByteSize); privateKeyList.Add(dBytes); privateKeyList.Add(nByteSize); privateKeyList.Add(nBytes); var publicKeyArray = publicKeyList.SelectMany(a => a).ToArray(); var privateKeyArray = privateKeyList.SelectMany(a => a).ToArray(); var privateKey = Convert.ToBase64String(privateKeyArray); var publicKey = Convert.ToBase64String(publicKeyArray); //Write these Base64 encoded files to disk var pos = Directory.GetCurrentDirectory().LastIndexOf("\\"); var pvtPath = Directory.GetCurrentDirectory().Substring(0, pos) + "\\private.key"; var pubPath = Directory.GetCurrentDirectory().Substring(0, pos) + "\\public.key"; var pvtPathJson = Directory.GetCurrentDirectory().Substring(0, pos) + "\\private.txt"; var pubPathJson = Directory.GetCurrentDirectory().Substring(0, pos) + "\\public.txt"; //Console.WriteLine(pvtPath); KeyMessage pvtKeyObj = new KeyMessage(); KeyMessage pubKeyObj = new KeyMessage(); pvtKeyObj.email = new List <string>(); pubKeyObj.email = new List <string>(); pvtKeyObj.key = privateKey; pubKeyObj.key = publicKey; var pvtJsonObj = JObject.FromObject(pvtKeyObj); var pubJsonObj = JObject.FromObject(pubKeyObj); //Console.WriteLine("Generating public key...\n" + pubJsonObj.ToString()); //Console.WriteLine("Generating private key ... \n" + pvtJsonObj.ToString()); File.WriteAllText(pvtPath, privateKey); File.WriteAllText(pubPath, publicKey); File.WriteAllText(pvtPathJson, pvtJsonObj.ToString()); File.WriteAllText(pubPathJson, pubJsonObj.ToString()); }
/// <summary> /// A parallel foreach loop instantiates a BigInteger using the RNGCryptoServiceProvider. /// This function also uses the isProbablyPrime() function from the PrimeCheckExtension class. /// Parallel options has been used to modify how the ForEach loop runs and doesnt crash due to running /// out of memory. For every BigInteger, it is checked for prime and once the number of primes found is /// equal to the required number (count), the process is terminated. /// </summary> /// <param name="bits">BitLength of the numbers to be checked</param> /// <param name="count">The number of prime numbers to be generated</param> public BigInteger Generate(int bits, int count) { CancellationTokenSource cts = new CancellationTokenSource(); ParallelOptions po = new ParallelOptions(); // to avoid running out of memory po.MaxDegreeOfParallelism = 20; // to facilitate termination of all threads if the condition (required number of primes) // has been met po.CancellationToken = cts.Token; BigInteger primeNum = 0; //counter for number of primes found. Will be compared to [count] to check if requirement has been met var cnt = 0; RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider(); // to run maximum number of threads possible. The code crashes (runs out of memory) // in the case of List <int> thread_ids = Enumerable.Range(1, Int16.MaxValue).ToList(); try { Parallel.ForEach(thread_ids, po, (id, state) => { //instantiation of BigInteger var byteArray = new byte[(bits / 8)]; provider.GetBytes(byteArray); BigInteger bigNum = new BigInteger(byteArray); // if bigInteger generated is negative if (bigNum < 0) { bigNum *= -1; } var isPrime = PrimeCheckExtension.IsProbablyPrime(bigNum); //Making updation of counter and printing thread safe lock (myLock) { if (isPrime) { primeNum = bigNum; cnt = cnt + 1; //To terminate all OTHER threads if the required number of threads has been reached cts.Token.ThrowIfCancellationRequested(); //Printing prime numbers as they are found //Console.WriteLine("\n{0}: {1}", cnt, bigNum); if (cnt == count) { cts.Cancel(); } } } }); } catch (OperationCanceledException) { //Console.WriteLine("Wooho "); //return 0; return(primeNum); } return(primeNum); }