• Silverlight信息加密 通过Rfc2898DeriveBytes类使用基于HMACSHA1的伪随机数生成器实现PBKDF2


    在上一篇文章当中,介绍到了通过Silverlight获取web.config中的值,最后提到了加密的问题,因此首先对该安全问题做一个简单的描述。

    问题描述

    1. 下方是我的web.config文件,当中配置这一个媒体文件服务器的IP地址

    <?xml version="1.0"?>
    
    <!--
      For more information on how to configure your ASP.NET application, please visit
      http://go.microsoft.com/fwlink/?LinkId=169433
      -->
    
    <configuration>
      <connectionStrings>
        <add name="VideoFiles_ConnectionString" connectionString="127.0.0.1"/>
      </connectionStrings>
        <system.web>
            <compilation debug="true" targetFramework="4.0" />
        </system.web>
    
    </configuration>
    

    2. 当在Silverlight程序中获取到该config中的值时,我们可以发现,通过查看页面的Source Code,是可以看到这个IP地址的,它是以明文的方式显示出来的,这样会引发安全性问题,我相信没有人愿意将自己的服务器IP地址暴露在外面

    解决方法

    在Page页面获取到web.config后,对该文件当中的内容进行加密,从而有效地解决了明文显示的问题,这样,别人就不能通过查看源代码的方式从前台获取你的服务器IP地址或者其他机密信息了,其实现方法如下:

    1. 在Page页面后台的.cs文件中,加入机密算法,使用Rfc2898DeriveBytes 获取密码、salt 值和迭代次数,然后通过调用 GetBytes 方法生成密钥:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Collections.Specialized;
    using System.Text;
    using System.Configuration;
    using System.Security.Cryptography;
    using System.IO;
    
    namespace GetWebConfig.Web
    {
        public partial class HostPage : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                //Clear the Cache
                Response.Cache.SetCacheability(HttpCacheability.NoCache);
                WriteInitParams();
            }
    
            private void WriteInitParams()
            {
                string strConn = ConfigurationManager.ConnectionStrings["VideoFiles_ConnectionString"].ToString();
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.Append("<param name=\"InitParams\" value=\"");
                stringBuilder.Append(Encrypt(strConn));
                stringBuilder.Append("\"/>");
                this.litInitParams.Text = stringBuilder.ToString();
            }
    
            /**/
            /// <summary>
            /// 加密数据
            /// </summary>
            /// <param name="input">加密前的字符串</param>
            /// <returns>加密后的字符串</returns>
            public static string Encrypt(string input)
            {
                // salt值
                string saltValue = "saltValue";
                // 密码值
                string pwdValue = "xuyue";
    
                byte[] data = System.Text.UTF8Encoding.UTF8.GetBytes(input);
                byte[] salt = System.Text.UTF8Encoding.UTF8.GetBytes(saltValue);
    
                // AesManaged - 高级加密标准(AES) 对称算法的管理类
                System.Security.Cryptography.AesManaged aes = new System.Security.Cryptography.AesManaged();
    
                // Rfc2898DeriveBytes - 通过使用基于 HMACSHA1 的伪随机数生成器,实现基于密码的密钥派生功能 (PBKDF2 - 一种基于密码的密钥派生函数)
                // 通过 密码 和 salt 派生密钥
                System.Security.Cryptography.Rfc2898DeriveBytes rfc = new System.Security.Cryptography.Rfc2898DeriveBytes(pwdValue, salt);
    
                /**/
                /*
                 * AesManaged.BlockSize - 加密操作的块大小(单位:bit)
                 * AesManaged.LegalBlockSizes - 对称算法支持的块大小(单位:bit)
                 * AesManaged.KeySize - 对称算法的密钥大小(单位:bit)
                 * AesManaged.LegalKeySizes - 对称算法支持的密钥大小(单位:bit)
                 * AesManaged.Key - 对称算法的密钥
                 * AesManaged.IV - 对称算法的密钥大小
                 * Rfc2898DeriveBytes.GetBytes(int 需要生成的伪随机密钥字节数) - 生成密钥
                 */
    
                aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
                aes.KeySize = aes.LegalKeySizes[0].MaxSize;
                aes.Key = rfc.GetBytes(aes.KeySize / 8);
                aes.IV = rfc.GetBytes(aes.BlockSize / 8);
    
                // 用当前的 Key 属性和初始化向量 IV 创建对称加密器对象
                System.Security.Cryptography.ICryptoTransform encryptTransform = aes.CreateEncryptor();
    
                // 加密后的输出流
                System.IO.MemoryStream encryptStream = new System.IO.MemoryStream();
    
                // 将加密后的目标流(encryptStream)与加密转换(encryptTransform)相连接
                System.Security.Cryptography.CryptoStream encryptor = new System.Security.Cryptography.CryptoStream
                    (encryptStream, encryptTransform, System.Security.Cryptography.CryptoStreamMode.Write);
    
                // 将一个字节序列写入当前 CryptoStream (完成加密的过程)
                encryptor.Write(data, 0, data.Length);
                encryptor.Close();
    
                // 将加密后所得到的流转换成字节数组,再用Base64编码将其转换为字符串
                string encryptedString = Convert.ToBase64String(encryptStream.ToArray());
    
                return encryptedString;
            }
        }
    }

    2. 之后,在Silverlight页面获取config数据的时候,通过解密算法进行解密,得到真正的IP地址信息:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Security.Cryptography;
    using System.IO;
    using System.Text;
    
    namespace GetWebConfig
    {
        public partial class MainPage : UserControl
        {
            private IDictionary<string, string> _config;
            public MainPage()
            {
                InitializeComponent();
                _config = (Application.Current as App).Configurations;
                if (_config.Count > 0)
                    lblWebconfig.Content = "Web.config connectionString: " + Decrypt(_config.ElementAt(0).Key.ToString() + "==");
            }
    
            /// <summary>
            /// 解密数据
            /// </summary>
            /// <param name="input">加密后的字符串</param>
            /// <returns>加密前的字符串</returns>
            public string Decrypt(string input)
            {
                // salt值(与加密时设置的值一致)
                string saltValue = "saltValue";
                // 密码值(与加密时设置的值一致)
                string pwdValue = "xuyue";
    
                byte[] encryptBytes = Convert.FromBase64String(input);
                byte[] salt = Encoding.UTF8.GetBytes(saltValue);
    
                System.Security.Cryptography.AesManaged aes = new System.Security.Cryptography.AesManaged();
    
                System.Security.Cryptography.Rfc2898DeriveBytes rfc = new System.Security.Cryptography.Rfc2898DeriveBytes(pwdValue, salt);
    
                aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
                aes.KeySize = aes.LegalKeySizes[0].MaxSize;
                aes.Key = rfc.GetBytes(aes.KeySize / 8);
                aes.IV = rfc.GetBytes(aes.BlockSize / 8);
    
                // 用当前的 Key 属性和初始化向量 IV 创建对称解密器对象
                System.Security.Cryptography.ICryptoTransform decryptTransform = aes.CreateDecryptor();
    
                // 解密后的输出流
                MemoryStream decryptStream = new MemoryStream();
    
                // 将解密后的目标流(decryptStream)与解密转换(decryptTransform)相连接
                System.Security.Cryptography.CryptoStream decryptor = new System.Security.Cryptography.CryptoStream(
                    decryptStream, decryptTransform, System.Security.Cryptography.CryptoStreamMode.Write);
    
                // 将一个字节序列写入当前 CryptoStream (完成解密的过程)
                decryptor.Write(encryptBytes, 0, encryptBytes.Length);
                decryptor.Close();
    
                // 将解密后所得到的流转换为字符串
                byte[] decryptBytes = decryptStream.ToArray();
                string decryptedString = UTF8Encoding.UTF8.GetString(decryptBytes, 0, decryptBytes.Length);
    
                return decryptedString;
            }
        }
    }

    最终实现效果如下,这时候我们通过查看源文件看到的则是被加密后的信息,而不是127.0.0.1,只有在Silverlight进行解密之后,才能看到我们想要的数据。

  • 相关阅读:
    CCF NOI1121 逆波兰表达式
    Vijos P1217 乒乓球【模拟+输入输出】
    Vijos P1304 回文数【回文+进制】
    NUC1041 数字三角形【DP】
    CCF NOI1070 汉诺塔游戏
    CCF NOI1069 分解因数
    CCF NOI1149 N皇后问题
    CCF NOI1153 素数环
    CCF NOI1170 质因数分解
    POJ NOI MATH-7832 最接近的分数
  • 原文地址:https://www.cnblogs.com/hainange/p/6153584.html
Copyright © 2020-2023  润新知