RSA 在C#裏簡單實現

1.選擇兩個大素數:p,q;
2.計算所得n:n=p*q;
3.計算中間結果t:t=(p-1)*(q-1);
4.選擇一個e:要求e和t的最大公因數是1(也就是e與t互素);
5.計算所得d:d*e mod t=1,就是說要求d和e的乘積除以t餘1;
(n,e)就是公鑰,(n,d)就是私鑰 dom

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int p = 3;              //質數
            int q = 17;             //質數

            if (!IsSuShu(p) || !IsSuShu(q))
            {
                Console.WriteLine("選擇的數字必須是素數");
            }

            int n = p * q;
            int r = (p - 1) * (q - 1); //歐拉函數

            var keyList = GetKeyList(r);
            var key = keyList.Where(k => k.Item1 != p && k.Item1 != q && k.Item2 != p && k.Item2 != q).LastOrDefault();
            int e = key.Item1;  //公鑰
            int d = key.Item2;  //私鑰

            long msg = new Random().Next(1, n); //msg必須小於n
            double encodeMsg = RSA(n, e, msg);
            double decodeMsg = RSA(n, d, encodeMsg);
            Console.WriteLine("加密前:" + msg);
            Console.WriteLine("加密後:" + encodeMsg);
            Console.WriteLine("解密後:" + decodeMsg);
            Console.Read();
        }

        private static List<Tuple<int, int>> GetKeyList(int r)
        {
            var list = new List<Tuple<int, int>>();
            int e = r;
            int d = 0;
            while (true)
            {
                if (e <= 1)
                {
                    break;
                }
                if (IsSuShu(e))
                {
                    if (!IsHaveGongYueShu(r, e)) //r與e互質
                    {
                        d = GetE2(r, e);
                        if (d > 0)
                        {
                            list.Add(new Tuple<int, int>(e, d));
                        }
                    }
                }
                e--;
            }
            if (list.Count == 0)
            {
                throw new Exception("找不到合適的數字用來當作公鑰");
            }
            return list;
        }

        private static int GetE2(int r, int e)
        {
            for (int d = r; d > 0; d--)
            {
                if ((d * e) % r == 1 && d != e) //求e關於r的模反元素
                {
                    return d;
                }
            }
            return 0;
        }

        private static bool IsHaveGongYueShu(int r, int e)
        {
            var rList = new List<int>();
            var dList = new List<int>();
            for (int i = 2; i < r; i++)
            {
                if (r % i == 0)
                {
                    rList.Add(i);
                }
            }
            for (int i = 2; i < e; i++)
            {
                if (e % i == 0)
                {
                    dList.Add(i);
                }
            }
            int result = rList.Where(p => dList.Contains(p)).Count();
            if (result > 0) //兩個數字是否有公約數
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private static bool IsSuShu(int num)
        {
            bool bl = true;
            for (int i = 2; i <= Math.Sqrt(num) && bl == true; i++) //數字是不是素數
            {
                if (num % i == 0)
                {
                    bl = false;
                }
            }
            return bl;
        }


        public static double RSA(int n, int key, double message)
        {
            if (n < 1 || key < 1)
            {
                return 0;
            }
            double rsaMessage = 0L;
            rsaMessage = Math.Pow(message, key) % n;
            return rsaMessage;
        }
    }
}
測試代碼
相關文章
相關標籤/搜索