KRY-0x04-netcore/rsa.cs
citizen-VM 54e5729954
feat: added RSA keygen functionality
* keygen and input checking functionality is provided by a simplified
version of the KRY-0x03 logic
2020-08-17 23:20:07 +02:00

377 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Numerics;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
namespace KRY_0x04_netcore
{
class rsa
{
RandomNumberGenerator rng = new RNGCryptoServiceProvider();
static int block_size = 32;
static int b1024 = 8;
static int b2048 = 14;
static int b3072 = 21;
static int b4096 = 27;
static int randbytesize = 0;
//byte[] block = new byte[block_size];
static byte[] partOfMessage = new byte[8 * block_size];
static BigInteger P = 0;
static BigInteger Q = 0;
static BigInteger E = 0;
static BigInteger D = 0;
static BigInteger N = 0;
static bool isprime_p, isprime_q;
static int primes_tried;
static DateTime gp_start, gp_finish;
static int numThreads = 3;
int custom_threads = 0;
public void gen_primes()
{
if (randbytesize == 0)
{
randbytesize = block_size * b1024; // default to something
}
byte[] random = new byte[randbytesize];
BigInteger rand_int = 0;
primes_tried = 0;
isprime_p = false;
isprime_q = false;
while (!isprime_p || !isprime_q)
{
primes_tried++;
rng.GetBytes(random);
rand_int = new BigInteger(random);
rand_int = BigInteger.Abs(rand_int);
if (!is_prime(rand_int))
{
Console.WriteLine($"[*] rand_int is not a_prime! (tried: {primes_tried}:\n{rand_int})");
continue;
}
Console.WriteLine($"[*] rand_int: {rand_int} \tis a prime!\n");
if (P != 0)
{
if (rand_int != P)
{
Form qq = new Form1();
lock (qq)
{
Q = rand_int;
isprime_q = true;
}
Console.WriteLine("[*] found q!\n");
break;
}
Console.WriteLine("\n[!] q cannot equal p");
continue;
}
Form pp = new Form1();
lock (pp)
{
P = rand_int;
isprime_p = true;
}
Console.WriteLine("[*] found p!\n");
}
}
bool is_prime(BigInteger source)
{
if (source == 2 || source == 3)
{
return true;
}
if (source < 2 || source % 2 == 0 || source % 3 == 0 || source % 5 == 0 || source % 7 == 0)
return false;
BigInteger d = source - 1;
int s = 0;
while (d % 2 == 0)
{
d /= 2;
s += 1;
}
RandomNumberGenerator rnd = RandomNumberGenerator.Create();
byte[] bytes = new byte[source.ToByteArray().LongLength];
BigInteger a;
for (int i = 0; i < (block_size * 2); i++)
{
do
{
rnd.GetBytes(bytes);
a = new BigInteger(bytes);
}
while (a < 2 || a >= source - 2);
BigInteger x = BigInteger.ModPow(a, d, source);
if (x == 1 || x == source - 1)
continue;
for (int r = 1; r < s; r++)
{
x = BigInteger.ModPow(x, 2, source);
if (x == 1)
return false;
if (x == source - 1)
break;
}
if (x != source - 1)
return false;
}
return true;
}
BigInteger mmi(BigInteger a, BigInteger nn)
{
BigInteger i = nn, v = 0, d = 1;
while (a > 0)
{
BigInteger t = i / a, x = a;
a = i % x;
i = x;
x = d;
d = v - t * x;
v = x;
}
v %= nn;
if (v < 0) v = (v + nn) % nn;
return v;
}
static (string, double) rsaPadding(string message)
{
string s = message;
double n = Math.Ceiling(message.Length / (double)partOfMessage.Length);
int nn = message.Length % partOfMessage.Length;
int chars_to_add = partOfMessage.Length - nn;
int i = 0;
while (i != chars_to_add)
{
s += " ";
i++;
}
return (s, n);
}
public void genprimes_handler(TextBox tb, TextBox tb_N, TextBox tb_E, TextBox tb_D, Label lb)
{
ManualResetEvent resetEvent = new ManualResetEvent(false);
int toProcess = 0;
tb_check(tb, lb);
bool is_invalid = Regex.IsMatch(tb.Text, @"^\D+$");
if (is_invalid)
{
toProcess = numThreads;
tb_check(tb, lb);
return;
}
if (threads_valid(tb.Text) == 1 || threads_valid(tb.Text) == 2)
{
tb_check(tb, lb);
MessageBox.Show("threads number needs to be 0 < n < 4", "check your numbah");
return;
}
else if (threads_valid(tb.Text) == 0)
{
bool is_whitespace = Regex.IsMatch(tb.Text, @"\s+$");
if (is_whitespace)
{
toProcess = numThreads;
}
else if (tb.Text == "")
{
toProcess = numThreads;
}
else
{
custom_threads = Convert.ToInt32(tb.Text);
}
}
if (custom_threads != 0)
{
numThreads = custom_threads;
}
/* Start workers. */
gp_start = DateTime.Now;
Console.WriteLine($"\n[*] spawning genprimes threads \t({gp_start})");
for (int i = 0; i < numThreads; i++)
{
new Thread(delegate ()
{
Thread.CurrentThread.Priority = ThreadPriority.Highest;
Console.WriteLine($"[*] genprimes thread id:{Thread.CurrentThread.ManagedThreadId} here, priority:{Thread.CurrentThread.Priority}");
gen_primes();
Console.WriteLine($"[*] genprimes thread id:{Thread.CurrentThread.ManagedThreadId} exiting...");
/* If we're the last thread, signal */
if (Interlocked.Decrement(ref toProcess) == 0)
resetEvent.Set();
}).Start();
}
/* Wait for workers. */
resetEvent.WaitOne();
gp_finish = DateTime.Now;
Console.WriteLine($"[*] genprimes finished.\t({gp_finish})\n");
Console.WriteLine($"[*] p:\n{P}");
Console.WriteLine($"[*] q:\n{Q}\n");
N = P * Q;
Console.WriteLine($"[*] n:\n{N}\n");
tb_N.Text = Convert.ToString(N);
Console.WriteLine("[*] eulerFunction = (p - 1) * (q - 1)");
BigInteger eulerFunction = (P - 1) * (Q - 1);
Console.WriteLine($"[*] eulerFunction:\n{eulerFunction}\n");
do
{
using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider())
{
byte[] random = new byte[4 * block_size];
rg.GetBytes(random);
E = new BigInteger(random);
E = BigInteger.Abs(E);
}
} while (!(E > 1) || !(E < eulerFunction) || !(BigInteger.GreatestCommonDivisor(E, eulerFunction) == 1));
Console.WriteLine($"[*] gcd(e, eulerFunction) = {BigInteger.GreatestCommonDivisor(E, eulerFunction)}");
Console.WriteLine($"[*] e:\n{E}\n");
tb_E.Text = Convert.ToString(E);
Console.WriteLine($"d = e exp -1");
D = mmi(E, eulerFunction);
Console.WriteLine($"[*] d:\n{D}\n");
tb_D.Text = Convert.ToString(D);
Console.WriteLine("[*] check inverse: e * d mod eulerFunction = 1");
Console.WriteLine($"{E} * {D} mod {eulerFunction} = {(E * D) % eulerFunction}\n");
Console.WriteLine("***********\n* summary *\n***********");
Console.WriteLine($"[*] p size: {P.ToString().Length} bits");
Console.WriteLine($"[*] q size: {Q.ToString().Length} bits");
Console.WriteLine($"[*] n size: {N.ToString().Length} bits");
Console.WriteLine($"[*] e size: {E.ToString().Length} bits");
Console.WriteLine($"[*] d size: {D.ToString().Length} bits");
Console.WriteLine($"[*] tried primes: {primes_tried}");
Console.WriteLine($"[*] gp_start: {gp_start}");
Console.WriteLine($"[*] gp_finish: {gp_finish}");
Console.WriteLine($"[*] generating primes took: {gp_finish - gp_start}");
Console.WriteLine("\n");
MessageBox.Show("got primes y'all", "info");
}
private int threads_valid(string input)
{
int returnme = 0;
bool is_whitespace = Regex.IsMatch(input, @"\s");
bool is_invalid = Regex.IsMatch(input, @"\D");
bool has_num = Regex.IsMatch(input, @"\d");
if (input == "" || is_whitespace)
{
returnme = 0;
}
if (is_invalid)
{
returnme = 2;
}
else if (is_invalid)
{
if (has_num)
{
returnme = 1;
}
else if (Convert.ToInt32(input) <= 0 || Convert.ToInt32(input) > 3)
{
returnme = 1;
}
}
else if (has_num)
{
if (is_invalid)
{
returnme = 2;
}
else if (Convert.ToInt32(input) <= 0 || Convert.ToInt32(input) > 3)
{
returnme = 1;
}
}
return returnme;
}
void tb_invalid_input(TextBox tb)
{
tb.BackColor = Color.PaleVioletRed;
}
void tb_valid_input(TextBox tb)
{
tb.BackColor = Color.White;
}
private void tb_check(TextBox tb, Label lb)
{
if (threads_valid(tb.Text) == 0)
{
tb_valid_input(tb);
lb.Text = "";
lb.Enabled = false;
}
else if (threads_valid(tb.Text) == 1)
{
tb_invalid_input(tb);
lb.Enabled = true;
lb.Text = "needs to be 0 < n < 4";
return;
}
else if (threads_valid(tb.Text) == 2)
{
tb_invalid_input(tb);
lb.Enabled = true;
lb.Text = "needs to be a number";
return;
}
}
public void keysize_handler(Button b)
{
if (b.Text == "1024b")
{
b.Text = "2048b";
randbytesize = block_size * b2048;
}
else if (b.Text == "2048b")
{
b.Text = "3072b";
randbytesize = block_size * b3072;
MessageBox.Show("gen_primes will likely take some time", "caution");
}
else if (b.Text == "3072b")
{
b.Text = "4096b";
randbytesize = block_size * b4096;
MessageBox.Show("gen_primes will likely take some time", "cautioncautioncautioncautioncaution");
}
else
{
b.Text = "1024b";
randbytesize = block_size * b1024;
}
}
}
}