程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> 基於私鑰加密公鑰解密的RSA算法C#實現

基於私鑰加密公鑰解密的RSA算法C#實現

編輯:關於C#

RSA算法是第一個能同時用於加密和數字簽名的算法,也易於理解和操作。 RSA是被研究得最廣泛的公鑰算法,從提出到現在已近二十年,經歷了各種攻擊的 考驗,逐漸為人們接受,普遍認為是目前最優秀的公鑰方案之一。RSA的安全性依 賴於大數的因子分解,但並沒有從理論上證明破譯RSA的難度與大數分解難度等價 。

RSA的安全性依賴於大數分解。公鑰和私鑰都是兩個大素數( 大於 100 個十進制位)的函數。據猜測,從一個密鑰和密文推斷出明文的難度等同於分解 兩個大素數的積。

密鑰對的產生。選擇兩個大素數,p 和q 。計算:

n = p * q

然後隨機選擇加密密鑰e(PS:最常用的e值有3,17和 65537,微軟就是使用的65537,采用3個中的任何一個都不存在安全問題),要求 e 和 ( p - 1 ) * ( q - 1 ) 互質。最後,利用Euclid 算法計算解密密鑰d, 滿 足

e * d = 1 ( mod ( p - 1 ) * ( q - 1 ) )

其中n和d也要互質 。數e和n是公鑰,d是私鑰。兩個素數p和q不再需要,應該丟棄,不要讓任何人知 道。

加密信息 m(二進制表示)時,首先把m分成等長數據塊 m1 ,m2,..., mi ,塊長s,其中 2^s <= n, s 盡可能的大。對應的密文是:

ci = mi^e ( mod n ) ( a )

解密時作如下計算:

mi = ci^d ( mod n ) ( b )

.NET提供常用的加密算法類,支持RSA的類是 RSACryptoServiceProvider(命名空間:System.Security.Cryptography),但 只支持公鑰加密,私鑰解密。RSACryptoServiceProvider類包括:Modulus、 Exponent、P、Q、DP、DQ、InverseQ、D等8個屬性,其中Modulus和Exponent就是 公鑰,Modulus和D就是私鑰,RSACryptoServiceProvider類提供導出公鑰的方法 ,也提供導出私鑰的方法,但導出的私鑰包含上面8個屬性,顯然要用 RSACryptoServiceProvider實現私鑰加密公鑰是不可行的。

從RSA的原理 來看,公鑰加密私鑰解密和私鑰加密公鑰解密應該是等價的,在某些情況下,比 如共享軟件加密,我們需要用私鑰加密注冊碼或注冊文件,發給用戶,用戶用公 鑰解密注冊碼或注冊文件進行合法性驗證。

本人利用網上找的一個C#版的 大整數類BigInteger(本人認為這是偶發現的效率最高的一個C#版大整數類)來 實現私鑰加密公鑰加密(事實上也完全支持公租加密私鑰解密),但沒有使用類 BigInteger的大素數生成函數,而是直接使用類RSACryptoServiceProvider來生 成大素數。其中加密函數和解密函數的實現如下:

/**//*

功能: 用指定的私鑰(n,d)加密指定字符串source

*/
         private string EncryptString(string source, BigInteger d, BigInteger n)
        ...{
             int len = source.Length;
            int len1 = 0;
            int blockLen = 0;
             if ((len % 128) == 0)
                len1 = len / 128;
            else
                 len1 = len / 128 + 1;
            string block = "";
            string temp = "";
            for (int i = 0; i < len1; i++)
            ...{
                 if (len >= 128)
                     blockLen = 128;
                else
                     blockLen = len;
                 block = source.Substring(i * 128, blockLen);
                 byte[] oText = System.Text.Encoding.Default.GetBytes(block);
                 BigInteger biText = new BigInteger(oText);
                 BigInteger biEnText = biText.modPow(d, n);
                string temp1 = biEnText.ToHexString ();
                temp += temp1;
                 len -= blockLen;
            }
            return temp;
        }
        /**//*

功能:用指定的公鑰(n,e)解密指定字符串 source

*/
        private string DecryptString(string source, BigInteger e, BigInteger n)
         ...{
            int len = source.Length;
            int len1 = 0;
             int blockLen = 0;
            if ((len % 256) == 0)
                len1 = len / 256;
             else
                len1 = len / 256 + 1;
            string block = "";
             string temp = "";
             for (int i = 0; i < len1; i++)
             ...{
                if (len >= 256)
                     blockLen = 256;
                 else
                     blockLen = len;
                block = source.Substring(i * 256, blockLen);
                 BigInteger biText = new BigInteger(block, 16);
                 BigInteger biEnText = biText.modPow(e, n);
                 string temp1 = System.Text.Encoding.Default.GetString(biEnText.getBytes());
                 temp += temp1;
                 len -= blockLen;
            }
             return temp;
        }

加密過 程和解密過程代碼如下所示:

/**//*
         加 密過程,其中d、n是RSACryptoServiceProvider生成的D、Modulus
         */
        private string EncryptProcess(string source, string d, string n)
        ...{
             byte[] N = Convert.FromBase64String(n);
             byte[] D = Convert.FromBase64String(d);
             BigInteger biN = new BigInteger(N);
             BigInteger biD = new BigInteger(D);
             return EncryptString(source, biD, biN);
        }
         /**//*
         解密過程,其中e、n是 RSACryptoServiceProvider生成的Exponent、Modulus
         */
        private string DecryptProcess(string source, string e, string n)
        ...{
             byte[] N = Convert.FromBase64String(n);
             byte[] E = Convert.FromBase64String(e);
             BigInteger biN = new BigInteger(N);
             BigInteger biE = new BigInteger(E);
            return DecryptString(source, biE, biN);
        }

以 上方法經本人實際使用,效果良好,希望對朋友們有幫助。

PS:文中所用大整數類下載地址:http://www.hugesoft.net/ContentPage.aspx?p1=010001&p2=201

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved