citizen-VM
54e5729954
* keygen and input checking functionality is provided by a simplified version of the KRY-0x03 logic
377 lines
12 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
}
|