.Net使用加密升级数据安全

最近又被【现场破解共享单车系统】刷了一脸,不得不开始后怕:如何防止类似的情况发生?

想来想去,始终觉得将程序加密是最简单的做法。但是摩拜、ofo也有加密,为什么仍然被破解?那是因为请求在传输过程中被篡改了关键参数,从而导致服务器做出了错误的响应。

如何防止篡改?自然是使用加密,加密方式的不同会决定篡改的成本(开头故事里的哥们大概用了2天),目前大多数的加密方法是暴露其他参数,只加密一个token,然后服务端验证token是否有效。从我的角度来讲,这种加密方式虽然破解难度很高,但多半是用MD5、SHA1、hmacMd5或AES等方式进行加密,结果往往是不可逆的,并且固定内容加密——不管多少次结果总是相同的。

对于部分人来讲,只要你暴露出来的数据就可以做很多事情了,而且如果使用这种加密手段,那么服务端和客户端必须约定好加密手段和参与加密的字段(规则),这就相当于:我(服务端)和你(客户端)一起设计了钥匙,然后在需要的时候(发起请求)你就往指定地方(服务器)丢一个上了锁的箱子(加密后的数据),然后我制作钥匙打开锁。我也可以丢箱子,然后你用同样方式去打开。

大家可以打开的锁安全么?想想都不靠谱。

更好的是什么?我们设想一下:我(服务端)给你(客户端)制造锁的图纸,我有制造钥匙的图纸,在你需要的时候(发起请求)就做一把锁,然后把货物(原始数据)放在箱子里锁好(加密完成)丢在指定的地方(服务器),然后我制作出钥匙,开锁拿走货物(解密)。

现在感觉如何?就像情报机构,侦察员只负责按照规则传递密码,而总部按照另一套规则解读,这个过程中就算被监听到,第三方也无法解读——这种方式就是今天要说的RSA。

该怎么做呢?很简单:基于现在基本都是用http交互数据,相互传输数据用json再好不过,所以我会要求客户端将所有参数以json格式全部拼装起来,然后整串加密后传输到服务器,请求内容看上去是这样的:

完全不知道这是一串什么鬼(如果我不是服务器的话):实际上这是一次登陆请求,里面包含账户、密码、时间戳、执行方法等,在服务端解密后是这样的:

{"msg":{"method":"log_in","time":"2017-09-28 10:30:27","user_name":"test","user_pwd":"test"}}

这就完成了一次正确的数据提交。并且如果有人修改了密文都会导致服务端解密失败从而驳回请求。这种情况下,就算你破译了整套客户端,也仅仅能拿到一个公钥,而远在服务端的私钥还是好好的(除非你已经攻破了人家的服务器),从而阻止参数在传递过程中被篡改(下面上点干货)。

生成公私钥:

/// <summary>
    /// RSA 的密钥产生 产生私钥 和公钥
    /// </summary>
    /// <param name="priKeys">私钥</param>
    /// <param name="pubKey">公钥</param>
    public static void rsaKey(out string priKeys, out string pubKey)
    {
        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        priKeys = rsa.ToXmlString(true);
        pubKey = rsa.ToXmlString(false);
    }

RSA加密:

/// <summary>
    /// RSA加密(不限长度)
    /// </summary>
    /// <param name="publicKey">公钥</param>
    /// <param name="text">要加密的文本</param>
    /// <param name="enc">编码方式</param>
    /// <returns>密文</returns>
    public static string rsaEncrypt(string pubKey, string text, Encoding enc)
    {
        using (var rsaProvider = new RSACryptoServiceProvider())
        {
            var inputBytes = enc.GetBytes(text);
            rsaProvider.FromXmlString(pubKey);
            int bufferSize = (rsaProvider.KeySize / 8) - 11;
            var buffer = new byte[bufferSize];
            using (MemoryStream inputStream = new MemoryStream(inputBytes), outputStream = new MemoryStream())
            {
                while (true)
                {
                    int readSize = inputStream.Read(buffer, 0, bufferSize);
                    if (readSize <= 0)
                    {
                        break;
                    }
                    var temp = new byte[readSize];
                    Array.Copy(buffer, 0, temp, 0, readSize);
                    var encryptedBytes = rsaProvider.Encrypt(temp, false);
                    outputStream.Write(encryptedBytes, 0, encryptedBytes.Length);
                }
                return Convert.ToBase64String(outputStream.ToArray());
            }
        }
    }

RSA解密:

/// <summary>
    /// rsa解密
    /// </summary>
    /// <param name="priKey">私钥</param>
    /// <param name="encrypted">要解密的字符串</param>
    /// <param name="enc">编码方式</param>
    /// <returns>明文</returns>
    public static string rsaDecrypt(string priKey, string encrypted, Encoding enc)
    {
        if (string.IsNullOrEmpty(encrypted))
        {
            return string.Empty;
        }

        if (string.IsNullOrWhiteSpace(priKey))
        {
            throw new ArgumentException("Invalid Private Key");
        }

        using (var rsaProvider = new RSACryptoServiceProvider())
        {
            var inputBytes = Convert.FromBase64String(encrypted);
            rsaProvider.FromXmlString(priKey);
            int bufferSize = rsaProvider.KeySize / 8;
            var buffer = new byte[bufferSize];
            using (MemoryStream inputStream = new MemoryStream(inputBytes),
                 outputStream = new MemoryStream())
            {
                while (true)
                {
                    int readSize = inputStream.Read(buffer, 0, bufferSize);
                    if (readSize <= 0)
                    {
                        break;
                    }

                    var temp = new byte[readSize];
                    Array.Copy(buffer, 0, temp, 0, readSize);
                    var rawBytes = rsaProvider.Decrypt(temp, false);
                    outputStream.Write(rawBytes, 0, rawBytes.Length);
                }
                return enc.GetString(outputStream.ToArray());
            }
        }
    }

因为本人对js也有一些兴趣,所以尝试着利用js与服务器交互,然鹅发现js需要java格式的公私钥,于是找到了转换公私钥的代码,亲测有效,在这里搬运下,利己利他:

/// <summary>
    /// RSA公钥格式转换(net转java)
    /// </summary>
    /// <param name="pubKey">net格式公钥</param>
    /// <returns>java格式的公钥</returns>
    public static string rsaPubKeyNet2Java(string pubKey)
    {
        XmlDocument doc = new XmlDocument();
        doc.LoadXml(pubKey);
        BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));
        BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
        RsaKeyParameters pub = new RsaKeyParameters(false, m, p);
        SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pub);
        byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
        return Convert.ToBase64String(serializedPublicBytes);
    }

    /// <summary>
    /// RSA私钥格式转换(net转java)
    /// </summary>
    /// <param name="priKey">net格式私钥</param>
    /// <returns>java格式的私钥</returns>
    public static string rsaPriKeyNet2Java(string priKey)
    {
        XmlDocument doc = new XmlDocument();
        doc.LoadXml(priKey);
        BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));
        BigInteger exp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
        BigInteger d = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("D")[0].InnerText));
        BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("P")[0].InnerText));
        BigInteger q = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Q")[0].InnerText));
        BigInteger dp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DP")[0].InnerText));
        BigInteger dq = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DQ")[0].InnerText));
        BigInteger qinv = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("InverseQ")[0].InnerText));
        RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(m, exp, d, p, q, dp, dq, qinv);
        PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
        byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();
        return Convert.ToBase64String(serializedPrivateBytes);
    }

进行转换需要用到一个三方类库,我的百度网盘里可以下载 http://pan.baidu.com/s/1b9Wy42,可以直接使用。

js的RSA加密也要用到一个库,在这里捎带贴一下:

<script type="text/javascript" src="https://passport.cnblogs.com/scripts/jsencrypt.min.js"></script>
    <script>
        //实例化对象
        var crypt = new JSEncrypt();
        //设置私钥
        crypt.setPrivateKey('你的RSA公钥');

        $('#log_in').click(function () {
            //拼装发送数据
            var post_data = crypt.encrypt('{"msg":{"method":"log_in","time":"' + Tool.getNowTime() + '","user_name":"' + $('.name').val() + '","user_pwd":"' + $('.pwd').val() + '"}}');
            //在这里发起你的请求
        });
    </script>

因为js可以被看到,所以你更需要RSA,因为全部被看到也无所谓了。

到此这篇关于.Net使用加密升级数据安全的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们

(0)

相关推荐

  • 在asp.net中使用加密数据库联接字符串保证数据安全

    在我们发布网站时,加密web.config,这样可以有效保证数据库用户和密码安全,其步骤如下: 1.添加密钥 执行:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pc "hnlaw" -exp 其中"hnlaw"为密钥名称 2.添加web.config节点 在web.config的<configuration></configuration>之间添加: <con

  • asp.net2.0如何加密数据库联接字符串

    asp.net2.0如何加密数据库联接字符串 在asp.net2.0中,发布网站时,加密web.config,这样可以有效保证数据库用户和密码安全,其步骤如下: 1.添加密钥 执行:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pc "hnlaw" -exp 其中"hnlaw"为密钥名称 2.添加web.config节点 在web.config的<configuration>&l

  • asp.net core常见的4种数据加密算法

    0. 前言 这一篇我们将介绍一下.net core 的加密和解密.在Web应用程序中,用户的密码会使用MD5值作为密码数据存储起来.而在其他的情况下,也会使用加密和解密的功能. 常见的加密算法分为对称加密和非对称加密.所谓的对称加密是指加密密钥和解密密钥是同一个,非对称加密是值加密密钥和解密迷药不同.而我们常应用在保存用户登录密码这个过程中的MD5本质上并不是加密算法,而是一种信息摘要算法.不过MD5尽量保证了每个字符串最后计算出来的值都不一样,所以在密码保存中常用MD5做为保密值. 1. 常见

  • ASP.NET web.config中 数据库连接字符串加密解密

    虽然不怎么新鲜,但相信还是有许多人不知道,好,不说废话,直接给方法:开始--->运行,输入cmd,接着输入以下内容 加密: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -pef "connectionStrings" "你的Web项目路径" 解密: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -

  • .Net使用加密升级数据安全

    最近又被[现场破解共享单车系统]刷了一脸,不得不开始后怕:如何防止类似的情况发生? 想来想去,始终觉得将程序加密是最简单的做法.但是摩拜.ofo也有加密,为什么仍然被破解?那是因为请求在传输过程中被篡改了关键参数,从而导致服务器做出了错误的响应. 如何防止篡改?自然是使用加密,加密方式的不同会决定篡改的成本(开头故事里的哥们大概用了2天),目前大多数的加密方法是暴露其他参数,只加密一个token,然后服务端验证token是否有效.从我的角度来讲,这种加密方式虽然破解难度很高,但多半是用MD5.S

  • 揭秘SQL Server 2014有哪些新特性(4)-原生备份加密

    SQL Server 2014 CTP2之后公布了一项针对备份的特性,那就是原生备份加密.考虑到之前网络上影响很坏的数据库泄漏事件,本质上都是数据库备份泄漏给第三方导致,SQL Server的原声数据备份可以使得即使备份本身被盗,在没有加密证书的情况下也无法使用,这有效的解决了上述数据泄漏问题.原先的解决方案 在SQL Server 2014之前,如果希望实现对备份实现加密,会通过如下两种方式之一实现: 使用透明数据加密(TDE)加密整个数据库,从而使得备份和事务日志也会被加密 使用第三方备份加

  • https证书选择之DV型、OV型、EV型证书的主要区别

    DV型和OV型证书的区别 DV和OV型证书最大的差别是:DV型证书不包含企业名称信息:而OV型证书包含企业名称信息,以下是两者差别对比表:   DV OV  包含企业名称信息 否 是   验证公司名称合法性 否  是   通过第三方查询电话验证 否  是   域名验证方式  管理员邮箱批准 查询whois信息是否一致   验证时间 最快10分钟签发  一般2-3天完成签发   证书可信度  低  较高 DV和OV型证书在用户查看证书的详情是,OV型证书会在证书的Subject中显示域名+单位名称

  • Spring Security如何实现升级密码加密方式详解

    目录 本章内容 密码加密方式怎么升级? 升级方案源码 实战 第一种方式: Spring Bean 他是怎么自动升级到BCrypt加密方式的? 第二种方式: 多继承接口方式 第三种方式: HttpSecurity直接添加 本章内容 密码加密方式怎么升级? spring security底层怎么实现的密码加密方式升级? 密码加密方式怎么升级? 前面我们学过DelegatingPasswordEncoder类,但是不清楚他到底是做什么的,我也没讲的很清楚.所以呢,我们就重新再讲一讲它的另一个实际应用.

  • 一个简单的后台与数据库交互的登录与注册[sql注入处理、以及MD5加密]

    一.工具:  vs2013[因为我现在用的也是2013,版本随便你自己开心]  sql2008[准备过久升级] 二.用到的语言 HTML+CSS+Jquery+Ajax+sqlserver HTML[相当于一个人] css[要穿衣服] Jquery[人要做一些动作,Jquery是对js一些常用方法的封装] Ajax[建立前端页面与数据库的交互] sqlserver[数据库] 三.过程 html部分代码: <body> <div id="header"> <

  • 在ASP.Net中实现RSA加密的方法

    在我们实际运用中,加密是保证数据安全的重要手段.以前使用ASP时,对数据加密可以使用MD5和SHA1算法,这两种算法虽然快捷有效,但是无法对通过它们加密的密文进行反运算,即是解密.因此需要解密数据的场合,这两种方法就不太适合了.当然你也可以自己编写适用的加密和解密程序,不过这对编写者的数学水平有很高的要求,一般人是很难做到的. 现在,随着ASP.Net的推出,彻底改变了以前ASP下的编程模式.我们能够利用.Net Framework中的类提供的加密服务来保证数据安全.目前应用较为广泛的加密方法是

  • asp.net的加密解密技巧

    对于加密和解密,我们都知道.下面主要介绍的是ASP.NET中的加密和解密. 一.数据加密/编码算法列表 常见用于保证安全的加密或编码算法如下: 1.常用密钥算法 密钥算法用来对敏感数据.摘要.签名等信息进行加密,常用的密钥算法包括: DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合: 3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高: RC2和 RC4:用变长密钥对大量数据进行加密,比 D

  • SCP远程VPS快速搬家和WDCP升级php5.3安装memcached和eaccelerator教程

    VPS搬家是一件非常累人的事情,对于空间放在国外的朋友,将数据打包下载到本地然后又由本地上传到新的空间上,这是一个非常痛苦的过程.国外的空间虽然带宽大,但是连接到国内的下载速度顶多就是几百KB/s,远远无法满足我们将网站快速搬家的需要. 另外,有些网站的数据非常多,打包起来可能有几个GB以上,对于这样的网站搬家如果采取传统的"打包-本地-上传"这样的方式,显然是不行的.最好的办法就是省掉数据经过本地的环节,直接在新旧VPS之间进行数据传输,这样可以最大限度地利用机房高带宽的搬家优势.

  • 对MD5加密方式使用者的建议

    根据MD5算法的特点,我们可以把MD5加密过程看作是一个函数调用过程,建议必须做如下方式修改,这样可以保证一定程度上你的网站用户和数据安全:  1.修改MD5算法重的4个常数,这是最捷径的作法,其特点是加密后的数据和加密前非常类似,但是不会被破解  2.多次加密,对MD5加密过的数据进行二次或三次加密,或者在每次加密后从重抽取部分值进行在加密,比如"我爱你",加密后"1E6986ACEC7BAE541AB7B37B99260DAF",我们可以取任意一部分进行再加密,

随机推荐