客户端密码加密[重复]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了客户端密码加密[重复]相关的知识,希望对你有一定的参考价值。
我必须保护我的网站用户的密码。我做的是使用MD5 加密 服务器端的哈希。但问题是密码保留为纯文本,直到它到达服务器,这意味着可以使用流量监控捕获密码。所以我想要的是使用客户端密码加密/散列机制并发送加密/散列密码。任何人都可以告诉你这样做的方法是什么?
这不安全,解释原因很简单:
如果您在客户端散列密码并使用该令牌而不是密码,则攻击者将不太可能找到密码。
但是,攻击者不需要知道密码是什么,因为您的服务器不再需要密码 - 它期待令牌。并且攻击者确实知道令牌,因为它是通过未加密的HTTP发送的!
现在,有可能将某种挑战/响应形式的加密混合在一起,这意味着相同的密码将在每个请求中产生不同的令牌。但是,这将要求密码以可解密的格式存储在服务器上,这是不理想的,但可能是一个合适的折衷方案。
最后,你真的想要用户在登录你的网站之前打开javascript吗?
在任何情况下,SSL都不再昂贵或者特别难以设置解决方案
您需要一个可以在客户端加密输入并以加密形式将其传输到服务器的库。
您可以使用以下库:
- jCryption。 Javascript上的客户端 - 服务器非对称加密
3年后更新:
4年后更新(哇哦!)
还是不相信?我也不 :)
- OpenPGP.JS - Put the OpenPGP format everywhere - 在JS中运行,因此您可以在您的网络应用程序,移动应用程序等中使用它。
我会选择this simple solution。
总结一下:
- 客户“我要登录”
- 服务器生成随机数
#S
并将其发送给客户端 - 客户
读取用户键入的用户名和密码
计算密码的哈希值,得到
h(pw)
(这是存储在数据库中的内容) 生成另一个随机数#C
连接h(pw) + #S + #C
并计算其哈希值,称之为h(all)
发送到服务器username
,#C
和h(all)
- 服务器
从DB中检索指定
h(pw)'
的username
现在它具有计算h(all')
的所有元素,就像客户那样 如果h(all)
=h(all')
然后h(pw)
=h(pw)'
,几乎肯定
没有人可以重复以指定用户身份登录的请求。 #S
每次都会向哈希添加一个变量组件(它是基础)。 #C
增加了额外的噪音。
通常使用HTTPS提供这种保护,以便加密Web服务器和客户端之间的所有通信。
有关如何实现此目标的确切说明取决于您的Web服务器。
Apache文档有一个SSL Configuration HOW-TO指南,可能会有所帮助。 (感谢用户G. Qyy的链接)
我已经列出了一个用于在底部创建MD5的完整JavaScript,但由于多种原因,没有安全连接它实际上毫无意义。
如果MD5密码并将MD5存储在数据库中,则MD5是密码。人们可以准确地告诉您数据库中的内容。您基本上只是将密码设置为较长的字符串,但如果这是您在数据库中存储的内容,则仍然不安全。
如果你说,“好吧,我将MD5 MD5”你错过了这一点。通过查看网络流量或查看您的数据库,我可以欺骗您的网站并将其发送给MD5。虽然这比仅仅重复使用纯文本密码要困难得多,但它仍然是一个安全漏洞。
最重要的是,尽管你没有在未加密的网络上发送盐,但是你不能对哈希客户端进行加盐,因此使盐析毫无意义。如果没有盐或已知的盐,我可以强行攻击哈希并找出密码是什么。
如果您要使用未加密的传输进行此类操作,则需要使用公钥/私钥加密技术。客户端使用您的公钥加密,然后使用您的私钥解密,然后MD5密码(使用用户唯一的盐)并将其存储在您的数据库中。这是a JavaScript GPL public/private key library。
无论如何,这是用于创建MD5客户端(而不是我的代码)的JavaScript代码:
/**
*
* MD5 (Message-Digest Algorithm)
* http://www.webtoolkit.info/
*
**/
var MD5 = function (string) {
function RotateLeft(lValue, iShiftBits) {
return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
}
function AddUnsigned(lX,lY) {
var lX4,lY4,lX8,lY8,lResult;
lX8 = (lX & 0x80000000);
lY8 = (lY & 0x80000000);
lX4 = (lX & 0x40000000);
lY4 = (lY & 0x40000000);
lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
if (lX4 & lY4) {
return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
}
if (lX4 | lY4) {
if (lResult & 0x40000000) {
return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
} else {
return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
}
} else {
return (lResult ^ lX8 ^ lY8);
}
}
function F(x,y,z) { return (x & y) | ((~x) & z); }
function G(x,y,z) { return (x & z) | (y & (~z)); }
function H(x,y,z) { return (x ^ y ^ z); }
function I(x,y,z) { return (y ^ (x | (~z))); }
function FF(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function GG(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function HH(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function II(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function ConvertToWordArray(string) {
var lWordCount;
var lMessageLength = string.length;
var lNumberOfWords_temp1=lMessageLength + 8;
var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
var lWordArray=Array(lNumberOfWords-1);
var lBytePosition = 0;
var lByteCount = 0;
while ( lByteCount < lMessageLength ) {
lWordCount = (lByteCount-(lByteCount % 4))/4;
lBytePosition = (lByteCount % 4)*8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition));
lByteCount++;
}
lWordCount = (lByteCount-(lByteCount % 4))/4;
lBytePosition = (lByteCount % 4)*8;
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
lWordArray[lNumberOfWords-2] = lMessageLength<<3;
lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
return lWordArray;
};
function WordToHex(lValue) {
var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
for (lCount = 0;lCount<=3;lCount++) {
lByte = (lValue>>>(lCount*8)) & 255;
WordToHexValue_temp = "0" + lByte.toString(16);
WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
}
return WordToHexValue;
};
function Utf8Encode(string) {
string = string.replace(/
/g,"
");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
};
var x=Array();
var k,AA,BB,CC,DD,a,b,c,d;
var S11=7, S12=12, S13=17, S14=22;
var S21=5, S22=9 , S23=14, S24=20;
var S31=4, S32=11, S33=16, S34=23;
var S41=6, S42=10, S43=15, S44=21;
string = Utf8Encode(string);
x = ConvertToWordArray(string);
a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
for (k=0;k<x.length;k+=16) {
AA=a; BB=b; CC=c; DD=d;
a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
d=FF(d,a,b,以上是关于客户端密码加密[重复]的主要内容,如果未能解决你的问题,请参考以下文章