[轉]應用RSACryptoServiceProvider類輕松實現RSA算法


在我們現實當中經常會存在需要對某些數據進行加密保護 然后進行解密的操作,比方,我們需要對某些XML配置信息里面的某些數據進行加密,以防止任何人打開該XML配置信息都能正常的看到該配置信息里面的內容,從而被人家篡改程序,甚至致使系統崩潰.下面我就談下現在比較常用的RSA算法以及如何在Visual C#中如何實現.
 
1.首先介紹下什么是RSA算法,讓大家對RSA算法有個簡要的理解.
   RSA算法非常簡單,概述如下:
  找兩素數p和q
   取n=p*q  如:n=3*7=21
   取t=(p-1)*(q-1) 如:t = 2*6 = 12
   取任何一個數e,要求滿足e
  取d*e%t==1  如:d=7,e=7,則7*7/12剛好等於1滿足要求
  這樣最終得到三個數: n d e,即 n=21,d=7,e=7
  設消息為數M
  設c=(M**d)%n就得到了加密后的消息c
  設m=(c**e)%n則 m == M,從而完成對c的解密。
  注:**表示次方,上面兩式中的d和e可以互換。
 
  在對稱加密中:
  n d兩個數構成公鑰,可以告訴別人;
  n e兩個數構成私鑰,e自己保留,不讓任何人知道。
  給別人發送的信息使用e加密,只要別人能用d解開就證明信息是由你發送的,構成了簽名機制。
  別人給你發送信息時使用d加密,這樣只有擁有e的你能夠對其解密。
  rsa的安全性在於對於一個大數n,沒有有效的方法能夠將其分解從而在已知n d的情況無法獲得e;同樣在已知n e的情況下無法求得d。
 
2.上面就是對RSA算法的一個簡要概括,該描述在很多書本上都有介紹,這里也就不做過多解釋了,下面我們看下在.net 里面如何實現該算法.
   在.net 里面,有一個叫RSACryptoServiceProvider的類,在MSDN中,我們可以了解到該類使用加密服務提供程序 (CSP) 提供的rsa算法的實現,執行不對稱加密和解密,從繼承關系上我們了解到該類繼承自RSA類.通過該類,我們可以導出加密解密所需要的XML信息,並且能夠根據我們提供的XML信息進行加密解密計算,下面是對該類的一些具體操作,主要包括如何導出密鑰,如何用形成的密鑰進行加密和解密,完成我們一般的操作.
   public class Cyh_RSA
    {
        public Cyh_RSA()
        {
           
        }
 
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="p_inputString">需要加密的字符串信息</param>
        /// <param name="p_strKeyPath">加密用的密鑰所在的路徑(*.cyh_publickey)</param>
        /// <returns>加密以后的字符串信息</returns>
        public string Encrypt(string p_inputString, string p_strKeyPath)
        {
            string fileString = null;
            string outString = null;
            if (File.Exists(p_strKeyPath))
            {
                StreamReader streamReader = new StreamReader(p_strKeyPath, true);
                fileString = streamReader.ReadToEnd();
                streamReader.Close();
 
            }
 
            if (fileString != null)
            {
                string bitStrengthString = fileString.Substring(0, fileString.IndexOf("</BitStrength>") + 14);
                fileString = fileString.Replace(bitStrengthString, "");
                int bitStrength = Convert.ToInt32(bitStrengthString.Replace("<BitStrength>", "").Replace("</BitStrength>", ""));
                try
                {
                    outString = EncryptString(p_inputString, bitStrength, fileString);
                }
                catch (Exception Ex)
                {
                    MessageBox.Show("出錯: \n" + Ex.Message);
                }
 
            }
 
            return outString;
        }
        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="p_inputString">需要解密的字符串信息</param>
        /// <param name="p_strKeyPath">解密用的密鑰所在的路徑(*.cyh_primarykey)</param>
        /// <returns>解密以后的字符串信息</returns>
        public string Decrypt(string p_inputString, string p_strKeyPath)
        {
            string fileString = null;
            string outString = null;
            if (File.Exists(p_strKeyPath))
            {
                StreamReader streamReader = new StreamReader(p_strKeyPath, true);
                fileString = streamReader.ReadToEnd();
                streamReader.Close();
 
            }
 
            if (fileString != null)
            {
                string bitStrengthString = fileString.Substring(0, fileString.IndexOf("</BitStrength>") + 14);
                fileString = fileString.Replace(bitStrengthString, "");
                int bitStrength = Convert.ToInt32(bitStrengthString.Replace("<BitStrength>", "").Replace("</BitStrength>", ""));
                try
                {
                    outString = DecryptString(p_inputString, bitStrength, fileString);
                }
                catch (Exception Ex)
                {
                    MessageBox.Show("出錯: \n" + Ex.Message);
                }
 
            }
 
            return outString;
 
        }
 
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="p_inputString">需要加密的字符串</param>
        /// <param name="p_dwKeySize">密鑰的大小</param>
        /// <param name="p_xmlString">包含密鑰的XML文本信息</param>
        /// <returns>加密后的文本信息</returns>
        private string EncryptString(string p_inputString, int p_dwKeySize, string p_xmlString)
        {
            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider(p_dwKeySize);
            rsaCryptoServiceProvider.FromXmlString(p_xmlString);
            int keySize = p_dwKeySize / 8;
            byte[] bytes = Encoding.UTF32.GetBytes(p_inputString);
            int maxLength = keySize - 42;
            int dataLength = bytes.Length;
            int iterations = dataLength / maxLength;
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i <= iterations; i++)
            {
                byte[] tempBytes = new byte[(dataLength - maxLength * i > maxLength) ? maxLength : dataLength - maxLength * i];
                Buffer.BlockCopy(bytes, maxLength * i, tempBytes, 0, tempBytes.Length);
                byte[] encryptedBytes = rsaCryptoServiceProvider.Encrypt(tempBytes, true);
                Array.Reverse(encryptedBytes);
                stringBuilder.Append(Convert.ToBase64String(encryptedBytes));
            }
            return stringBuilder.ToString();
        }
 
        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="p_inputString">需要解密的字符串信息</param>
        /// <param name="p_dwKeySize">密鑰的大小</param>
        /// <param name="p_xmlString">包含密鑰的文本信息</param>
        /// <returns>解密后的文本信息</returns>
        private string DecryptString(string inputString, int dwKeySize, string xmlString)
        {
            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider(dwKeySize);
            rsaCryptoServiceProvider.FromXmlString(xmlString);
            int base64BlockSize = ((dwKeySize / 8) % 3 != 0) ? (((dwKeySize / 8) / 3) * 4) + 4 : ((dwKeySize / 8) / 3) * 4;
            int iterations = inputString.Length / base64BlockSize;
            ArrayList arrayList = new ArrayList();
            for (int i = 0; i < iterations; i++)
            {
                byte[] encryptedBytes = Convert.FromBase64String(inputString.Substring(base64BlockSize * i, base64BlockSize));
                Array.Reverse(encryptedBytes);
                arrayList.AddRange(rsaCryptoServiceProvider.Decrypt(encryptedBytes, true));
            }
            return Encoding.UTF32.GetString(arrayList.ToArray(Type.GetType("System.Byte")) as byte[]);
        }
 
        /// <summary>
        /// 形成並保存公開密鑰和私有密鑰
        /// </summary>
        /// <param name="p_currentBitStrength">密鑰大小</param>
        public void SaveKey(int p_currentBitStrength)
        {
            RSACryptoServiceProvider RSAProvider = new RSACryptoServiceProvider(p_currentBitStrength);
            string publicAndPrivateKeys = "<BitStrength>" + p_currentBitStrength.ToString() + "</BitStrength>" + RSAProvider.ToXmlString(true);
            string justPublicKey = "<BitStrength>" + p_currentBitStrength.ToString() + "</BitStrength>" + RSAProvider.ToXmlString(false);
            if (saveFile("Save Public/Private Keys As", "Public/Private Keys Document( *.cyh_primarykey )|*.cyh_primarykey", publicAndPrivateKeys))
            { while (!saveFile("Save Public Key As", "Public Key Document( *.cyh_publickey )|*.cyh_publickey", justPublicKey)) { ; } }
        }
 
        /// <summary>
        /// 保存信息
        /// </summary>
        /// <param name="p_title">標題</param>
        /// <param name="p_filterString">過濾條件</param>
        /// <param name="p_outputString">輸出內容</param>
        /// <returns>是否成功</returns>
        private bool saveFile(string p_title, string p_filterString, string p_outputString)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Title = p_title;
            saveFileDialog.Filter = p_filterString;
            saveFileDialog.FileName = "";
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    StreamWriter streamWriter = new StreamWriter(saveFileDialog.FileName, false);
                    if (p_outputString != null)
                    { streamWriter.Write(p_outputString); }
                    streamWriter.Close();
                    return true;
                }
                catch (Exception Ex)
                {
                    Console.WriteLine(Ex.Message);
                    return false;
                }
            }
            return false;
        }
    }
這樣,您在任何地方都可以使用該類對數據進行加密和解密,並且操作相當方便,如:
生成密鑰:
 Cyh_RSA rsa = new Cyh_RSA();
 rsa.SaveKey(1024);
加密:
Cyh_RSA rsa = new Cyh_RSA();
rsa.Encrypt("需要加密的內容", "包含密鑰的路徑");
解密:
Cyh_RSA rsa = new Cyh_RSA();
rsa.Decrypt("需要解密的內容", "包含密鑰的路徑");


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM