using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Numerics;
using System.Security.Cryptography;
namespace RSA
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public const int K_MIN = 10000000;
public const int K_MAX = 1000000000;
public BigInteger p, q, n, fi, e, d;
public BigInteger[] CText;
private void button1_Click(object sender, EventArgs e_)
{
Random ra = new Random();
while (true)
{
p = new BigInteger(ra.Next(K_MIN, K_MAX));
q = new BigInteger(ra.Next(K_MIN, K_MAX));
p = BigInteger.Multiply(p, p);
q = BigInteger.Multiply(q, q);
while (true)
{
if (IsProbablePrime(p) == true)
{
break;
}
p = BigInteger.Add(p, 1);
}
while (true)
{
if (IsProbablePrime(q) == true && BigInteger.Compare(p, q) != 0)
{
break;
}
q = BigInteger.Add(q, 1);
}
fi = BigInteger.Multiply(p - 1, q - 1);
e = 2;
while (true)
{
if (BigInteger.Compare(BigInteger.GreatestCommonDivisor(e, fi), 1) == 0 && BigInteger.Compare(e, fi) < 0)
{
break;
}
e = BigInteger.Add(e, 1);
}
d = ExtendedEuclid(fi, e);
if (d > 0)
{
break;
}
}
n = BigInteger.Multiply(p, q);
textBox1.Text = Convert.ToString(p);
textBox2.Text = Convert.ToString(q);
textBox3.Text = Convert.ToString(n);
textBox4.Text = Convert.ToString(fi);
textBox5.Text = Convert.ToString(e);
textBox6.Text = Convert.ToString(d);
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
}
public bool IsProbablePrime(BigInteger source)
{
int certainty = 2;
if (source == 2 || source == 3)
{
return true;
}
if (source < 2 || source % 2 == 0)
{
return false;
}
BigInteger d = source - 1;
int s = 0;
while (d % 2 == 0)
{
d /= 2;
s += 1;
}
RandomNumberGenerator rng = RandomNumberGenerator.Create();
byte[] bytes = new byte[source.ToByteArray().LongLength];
BigInteger a;
for (int i = 0; i < certainty; i++)
{
do
{
rng.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;
}
private void textBox3_TextChanged(object sender, EventArgs e)
{
}
private void button3_Click(object sender, EventArgs e)//解密
{
for (int i = 0; i < textBox7.Text.Length; i++)
{
CText[i] = BigInteger.ModPow(CText[i], d, n);
}
string temp = null;
for (int i = textBox7.Text.Length - 1; i >= 0; i--)
{
temp = Convert.ToString((char)CText[i]) + temp;
}
textBox9.Text = temp;
}
private BigInteger ExtendedEuclid(BigInteger f, BigInteger d)
{
BigInteger x1, x2, x3, y1, y2, y3, t1, t2, t3, q, result;
x1 = y2 = 1;
x2 = y1 = 0;
x3 = (f >= d) ? f : d;
y3 = (f >= d) ? d : f;
while (true)
{
if (y3 == 0)
{
return 0;
}
if (y3 == 1)
{
result = y2;
return result;
}
q = x3 / y3;
t1 = x1 - q * y1;
t2 = x2 - q * y2;
t3 = x3 - q * y3;
x1 = y1;
x2 = y2;
x3 = y3;
y1 = t1;
y2 = t2;
y3 = t3;
}
}//扩展欧几里得算法
private void textBox5_TextChanged(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e_)//加密
{
CText = new BigInteger[textBox7.Text.Length];
int m = textBox7.Text.Length;
for (int i = 0; i < textBox7.Text.Length; i++)
{
BigInteger k = Convert.ToInt64(textBox7.Text[i]);
BigInteger mm = BigInteger.ModPow(k, e, n);
CText[i] = mm;
}
string temp = null;
for (int i = textBox7.Text.Length - 1; i >= 0 ; i--)
{
temp = Convert.ToString(CText[i]) + temp;
}
textBox8.Text = temp;
}
}
}
注意 Numberics库需要.Net 4.0及更高版本