用C#Numberics庫寫的簡單RSA算法

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及更高版本

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章