Web应用中保证密码传输安全

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介:

 去年写过一篇博文《Web应用的安全的登录认证》,使用HMAC的加密算法保证了在登录时的密码安全。虽然没看到有人质疑,但这里至少会引出一个问题:登录过程不需要将密码原文提交到服务器,但注册和修改密码这两个需要将密码原文提交到服务器的过程怎么办?


  解决这一问题最佳方案当然是使用非对称加密。简单的说,非对称加密算法需要两个密钥,分别称为公钥和私钥,其中公钥会被公布出来,而私钥由个了保管(就像保管自己的密码一样)。使用公钥加密的数据是不能用公钥解密的,只能由私钥来解密。如果将私钥保存在服务器,把公钥发送给浏览器对密码原文进行加密,那么加密后的数据在传输过程中是安全的,因为私钥始终不会出现在传输过程,这个加密数据就不能轻松的解开。关于非对称加密的知识,学霸们请去各种百科上搜索,这里就不多说了。


  目前最常用的非对称加密算法是RSA算法,在服务器端.NET、Java都支持,PHP也有组件支持。在浏览器端,也有JavaScript的RSA算法包——用Google搜索“javascript rsa”第一个结果就是“RSA In JavaScript - ohdave.com”,该网站提供了三个JS文件,BitInt.js、Barrett.js和RSA.js,这三个JS文件要在见面中按顺序引用。


  下面就以C#和JavaScript为例说明一下加密传输密码和后台解密的过程。


  当然第一步是要产生公钥和私钥,自己用C#写个小小的控制台程序或者Windows程序就能解决这个问题,顺便熟悉一下C#的RSA。顺便说一下,维基百科提到,要保证安全至少得使用1024位的Key,.NET的RSA支持384到2048位的Key,这里就以1024位为例吧,下面的程序会在执行目录输出一个key.xml文件,保存了产生的公钥和私钥


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[STAThread]
static  void  Main( string [] args)
{
     string  keyFileName
         = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
             "key.xml" ;
     const  int  keySize = 1024;
     // 这个类在System.Security.Cryptography命名空间中
     RSACryptoServiceProvider sp =  new  RSACryptoServiceProvider(keySize);
     // 参数true表示XML中包含私钥。如果给false表示只生成公钥的XML
     string  str = sp.ToXmlString( true );
     using  (TextWriter writer =  new  StreamWriter(keyFileName)) {
         writer.Write(str);
     }
}


  打开生成的key.xml可以看到,这个Key值包含了如下几个部分:Modulus、Exponent、P、Q、DP、DQ、InverseQ、D。这几个部分的值都是以Base64编码保存的。其中,Modulus和Exponent就是组成公钥的部分,也就是需要传递给浏览器,简称M和E,用于加密的两个数值。


  生成key.xml之后,有两种方式使用,一种是在使用时从XML文件导入;另一种方式是把这几个值提取出来写在某个类中。导入XML需要先将XML文本读取到一个string中,再用RSACryptoServiceProvider的实例方法FromXmlString(string)导入。因为需要向浏览器提供M和E,所以还要把这两个值提取出来


1
2
3
4
5
6
RSACryptoServiceProvider rsa =  new  RSACryptoServiceProvider();
rsa.FromXmlString(xmlString);
RSAParameters rsap = rsa.ExportParameters( false );
//下面就是需要的两个值
//rsap.Exponent
//rsap.Modulus


  如果嫌每次载入费事,可以这样(其中所有字符串常量都是从key.xml中拷贝过来的)


1
2
3
4
5
6
7
8
9
10
11
private  static  readonly  RSAParameters rsap =  new  RSAParameters
{
     Modulus = Convert.FromBase64String( @"uQlRZvfH6MMdhNRgiAlKMY88dqsU2suKNIWbHY/FiTsvDgH5DLmNmGMp85qtQwSPhBQ+/E7DQkvk1OxIN7EBL+21NRPJIaDKuJciWC940ZFVU0d5oUujKy5uCrF/rfZce8MXjoiErtc+QRjCKI8wfGdIKuclooEPiJwb1rydMuE=" ),
     Exponent = Convert.FromBase64String( @"AQAB" ),
     P = Convert.FromBase64String( @"wSwI9i+aM6h7hayvFD01iINAeZ9JK5qExBJAWDzjOQwWRE9x1dCX52jb+HrutwblfqQuOk6hazOmGTluxITXQw==" ),
     Q = Convert.FromBase64String( @"9TfkbPTexGpQ9ZHNjYnmRJLcG8wG6yzzJ/RrWIjq1IKQYMhYDq08bNbUVuXlntKW9GgmEYnuhP8smrH5y+mRCw==" ),
     DP = Convert.FromBase64String( @"s2Xx7LDIxLD0BnEZJ/KwhNdgSZNkoNof8vgASfJCE/jltQsS7T+L053OrDV+/PuqprJTPFNKFgUhfMuZ02iLgQ==" ),
     DQ = Convert.FromBase64String( @"5IfLXXO0LI78lm/khlUPAbdwZIN3qzMABat3Y1Jur9BiZ6Au2LbASprH15h3r9WJE4wAdnX6kX4SfrUBHPW20w==" ),
     InverseQ = Convert.FromBase64String( @"FhlNb2WkipUaXvuwDxEWPeE754+qM2F5otEUP9clG91yaerdsBpBmU0G6S2AqUNjr/qgfpQyl1EW2dl10rmTpw==" ),
     D = Convert.FromBase64String( @"WjhPXv/Qks7T7UiqGppA+UIoToojPH1C0VIVrEfGHp/jVRakKs6sWhF7yoHwGf22xkUi4t26efBMTn84xSLCexjQwj5AQtYk+3Qr2QjRDdn2ooIV1gWKW/C0O0+80Y6PEeszItuBVfjKC6mNEcZ1g44/wOdvIG7Olsl0F7vmQrM=" )
};


  将E和M传递给浏览器的方式,最直接就是写在HTML里,我个人比较喜欢把一些小数据写在<HEAD>标签的属性中,就像这样:<HEAD M="..." E="...">。C#代码也很简单:


1
2
Header.Attributes[ "M" ] = rsap.Modulus.HexEncode();
Header.Attributes[ "E" ] = rsap.Exponent.HexEncode();


  这里用到了一个byte[]的扩展方法HexEncode,即将byte[]转换为16进制字符串的方法,它最简单(但不一定是最快)的实现方法是


1
2
3
4
public  static  string  HexEncode( this  byte [] me)
{
     return  BitConverter.ToString(me).Replace( "-" string .Empty);
}


  现在是浏览器端的加密过程,引入需要的JS文件先:


1
2
3
4
< script  type = "text/javascript"  src = "js/BigInt.js" ></ script >
< script  type = "text/javascript"  src = "js/Barrett.js" ></ script >
< script  type = "text/javascript"  src = "js/RSA.js" ></ script >
< script  type = "text/javascript"  src = "js/jquery-2.1.0.js" ></ script >


  然后在加密密码之前当然要先得到RSAKeyPair对象,这个对象的构造函数定义在RSA.js中。不过在new RSAKeyPair之前,必须先调用setMaxDigits()函数,原因在BigInt.js中有说明,setMaxDigits()的参数值根据选用的RSA的Key大小不同,如果计算我不太清楚,不过按ohdave.com的示例(下载页面的源码就是示例),1024位的Key,应该设置setMaxDigits(130);如果是2048位的则应该设置为260。所以产生RSAKeyPair对象的代码应该是这样:


1
2
3
4
5
6
7
8
9
10
$( function () {
     var  key = ( function () {
         var  m = $( "head" ).attr( "M" );
         var  e = $( "head" ).attr( "E" );
         setMaxDigits(130);
         // 第一个参数是加密因子,第二个参数是解密因子
         // 因为浏览器端不需要解密,所以第二个参数传入空字符串
         return  new  RSAKeyPair(e,  "" , m);
     })();
})


  在提交数据之前对密码进行加密


1
var  encryptedPass = encryptedString(key, $( "#password" ).val());


  提交到后台之后,C#解密的过程


1
2
3
4
5
6
7
string  hex = Request[ "encrypted_pass" ]
byte [] data = hex.HexDecode();
RSACryptoServiceProvider rsa =  new  RSACryptoServiceProvider();
// 前面定义的private static readonly RSAParameter rsap = ...
rsa.ImportParameters(rsap);
byte [] source = rsa.Decrypt(data,  false );
string  password = Encodnig.ASCII.GetString(source);


  密码原文得到,剩下的事情就好说了,当然是保存密码,记得先使用HMAC算法加密哦。后面有示例下载,不是很明显,仔细找找。



本文转自边城__ 51CTO博客,原文链接:http://blog.51cto.com/jamesfancy/1361925,如需转载请自行联系原作者
相关文章
|
2月前
|
存储 监控 安全
如何在Python Web开发中确保应用的安全性?
如何在Python Web开发中确保应用的安全性?
|
2月前
|
前端开发 JavaScript
探索现代Web应用的微前端架构
【10月更文挑战第40天】在数字时代的浪潮中,Web应用的发展日益复杂多变。微前端架构作为一种新兴的设计理念,正逐步改变着传统的单一前端开发模式。本文将深入探讨微前端的核心概念、实现原理及其在实际项目中的应用,同时通过一个简单的代码示例,揭示如何将一个庞大的前端工程拆分成小而美的模块,进而提升项目的可维护性、可扩展性和开发效率。
|
3天前
|
Web App开发 编解码 vr&ar
使用Web浏览器访问UE应用的最佳实践
在3D/XR应用开发中,尤其是基于UE(虚幻引擎)开发的高精度场景,传统终端因硬件局限难以流畅运行高帧率、复杂效果的三维应用。实时云渲染技术,将渲染任务转移至云端服务器,降低终端硬件要求,确保用户获得流畅体验。具备弹性扩展、优化传输协议、跨平台支持和安全性等优势,适用于多种终端和场景,特别集成像素流送技术,帮助UE开发者实现低代码上云操作,简化部署流程,保留UE引擎的强大开发能力,确保画面精美且终端轻量化。
使用Web浏览器访问UE应用的最佳实践
|
25天前
|
弹性计算 Java 关系型数据库
Web应用上云经典架构实践教学
Web应用上云经典架构实践教学
Web应用上云经典架构实践教学
|
1月前
|
Kubernetes 安全 Devops
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
66 10
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
|
18天前
|
缓存 安全 搜索推荐
阿里云先知安全沙龙(北京站) ——浅谈Web快速打点
信息收集是网络安全中的重要环节,常用工具如Hunter、Fofa和扫描工具可帮助全面了解目标系统的网络结构与潜在漏洞。遇到默认Nginx或Tomcat 404页面时,可通过扫路径、域名模糊测试、搜索引擎缓存等手段获取更多信息。AllIN工具(GitHub: P1-Team/AllIN)能高效扫描网站路径,发现敏感信息。漏洞利用则需充分准备,以应对突发情况,确保快速拿下目标站点。 简介:信息收集与漏洞利用是网络安全的两大关键步骤。通过多种工具和技术手段,安全人员可以全面了解目标系统,发现潜在漏洞,并制定有效的防御和攻击策略。
|
25天前
|
弹性计算 Java 数据库
Web应用上云经典架构实战
本课程详细介绍了Web应用上云的经典架构实战,涵盖前期准备、配置ALB、创建服务器组和监听、验证ECS公网能力、环境配置(JDK、Maven、Node、Git)、下载并运行若依框架、操作第二台ECS以及验证高可用性。通过具体步骤和命令,帮助学员快速掌握云上部署的全流程。
|
27天前
|
安全 应用服务中间件 网络安全
实战经验分享:利用免费SSL证书构建安全可靠的Web应用
本文分享了利用免费SSL证书构建安全Web应用的实战经验,涵盖选择合适的证书颁发机构、申请与获取证书、配置Web服务器、优化安全性及实际案例。帮助开发者提升应用安全性,增强用户信任。
|
2月前
|
前端开发 JavaScript UED
在数字化时代,Web 应用性能优化尤为重要。本文探讨了CSS与HTML在提升Web性能中的关键作用及未来趋势
在数字化时代,Web 应用性能优化尤为重要。本文探讨了CSS与HTML在提升Web性能中的关键作用及未来趋势,包括样式表优化、DOM操作减少、图像优化等技术,并分析了电商网站的具体案例,强调了技术演进对Web性能的深远影响。
45 5
|
2月前
|
机器学习/深度学习 人工智能 JavaScript
JavaScript和TypeScript的未来发展趋势及其在Web开发中的应用前景
本文探讨了JavaScript和TypeScript的未来发展趋势及其在Web开发中的应用前景。JavaScript将注重性能优化、跨平台开发、AI融合及WebAssembly整合;TypeScript则强调与框架整合、强类型检查、前端工程化及WebAssembly的深度结合。两者结合发展,特别是在Vue 3.0中完全采用TypeScript编写,预示着未来的Web开发将更加高效、可靠。
58 4