zoukankan      html  css  js  c++  java
  • [转]应用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("出错: " + 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("出错: " + 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("需要解密的内容", "包含密钥的路径");
  • 相关阅读:
    ASP.NET 中Request.QueryString 中的key
    我要爱死这个markdown 了
    WindowsPhone 8 开发 之 本地数据库应用
    java对象详解
    java内存分析
    java 成长之路
    springboot hessian
    zabbix 3.0 安装 ubuntu环境
    dubbo+zookeeper简单环境搭建
    大型网站及架构演进过程
  • 原文地址:https://www.cnblogs.com/cxd4321/p/3333543.html
Copyright © 2011-2022 走看看