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(/\r\n/g,"\n");
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,c,x[k+5], S12,0x4787C62A);
c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
d=GG(d,a,b,c,x[k+10],S22,0x2441453);
c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
a=II(a,b,c,d,x[k+0], S41,0xF4292244);
d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
c=II(c,d,a,b,x[k+6], S43,0xA3014314);
b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
a=AddUnsigned(a,AA);
b=AddUnsigned(b,BB);
c=AddUnsigned(c,CC);
d=AddUnsigned(d,DD);
}
var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
return temp.toLowerCase();
}
用法
MD5("whatever");
例如可能 获取Gravatar头像。
在登录表单提交时,用md5字符串替换密码是一个好主意还是坏主意呢?
我想这会增加安全性……如果我错了,请纠正我。
我不这么认为。如果用户禁用了JavaScript,密码仍然会以明文形式发送,服务器无法知道是传递了一个md5加密字符串还是用户的密码。
是的,这是一个好主意。
@Johnathan Barett
但是服务器可以尝试这两种可能性;)
(在PHP中“$correct = $_GET[“pwd”] == $password || md5($_GET[“pwd”]) == $password;”)
只有在服务器端发生时才会很棒
MD5现在非常容易解密,使用SSL基本上可以实现相同的功能,但效果更好(并且适用于客户端和服务器之间发送和接收的所有数据)。
也就是说,模糊安全通常仍然是一个好主意。
关于JavaScript是否启用的问题,可以通过JavaScript非常轻松地向请求中添加其他数据,在这种情况下,服务器只需查找该数据是否存在(不存在表示JavaScript已禁用,并且字符串在哈希之前已发送)。
我强烈建议不要在服务器端同时检查哈希和未哈希的版本。锁只能用正确的钥匙打开,而不是尝试寻找两把不同的钥匙并接受两者。
至于megatrons的回复:这并不会改变字符串从客户端到服务器未经哈希发送的事实,因此它并没有真正回答问题。
为什么不直接使用md5() mysql函数呢?
因为他没有使用MySQL。我假设你指的是PHP MD5函数。问题在于如何获取JavaScript输入并将其通过PHP函数运行?就像获取Gravatar一样,用户输入电子邮件地址,如何在不加载另一个页面来发送结果的情况下将该值传递给PHP函数?
不,我说的是md5 MySQL函数,对于SQL Server或您使用的任何数据库管理器,都有一个等效的函数。如果您正在加密密码,我假设您将其存储在数据库中。
密码不应使用MD5存储,因为它从未被设计为加密算法。但是,客户端哈希还有其他用例,例如比较校验和。
嗯……所以你的意思是:明文密码到MD5(无论是在前端还是后端实现),然后加密MD5而不是明文密码。我认为这很聪明。
我确切地知道你在说什么,但这不是关于存储信息,而是关于通过浏览器发送信息。
嘿,谢谢大家分享这个宝贵的脚本。
@Johnathan Barrett:实际上,服务器有一种方法可以知道客户端浏览器中是否启用了JavaScript。
为此,请向表单添加一个名为“hasjavascript”的隐藏字段,其默认值为“false”,然后使用JavaScript将此字段的值设置为“true”。
然后,在服务器端代码中,检查GET变量“hasjavascript”的值。
使用JavaScript进行密码哈希的唯一效果是,如果有人获取提交的值,他们将无法知道明文密码,并且(希望)将无法使用此密码在其他网站上登录。
请注意,他仍然可以通过简单地提交拦截的哈希密码来登录您的网站,就像浏览器所做的那样。
为了防止这种情况,您必须使用非对称加密算法(如RSA)。
在此处了解更多信息:http://en.wikipedia.org/wiki/Public-key_cryptography
我已将其用于客户端不希望使用https的网站(他们疯了,我知道)。我所做的是使用挑战认证(实际上我从雅虎邮件中窃取了它:P)。很简单
1)生成一个随机“盐”(生成一个随机字符串)并将其存储在会话中。将其发送到浏览器。
2)在客户端,连接盐和密码,并对其进行md5处理。发送结果。还要发送盐。
3)在服务器上,检查盐是否相同,以及md5(salt . password)是否匹配。如果不是,则生成一个新的盐并重复。
如果需要在服务器上加密密码,请执行相同的操作,但不要比较密码,而是比较加密的密码(显然,您需要在浏览器中复制数据库密码加密过程)。
尽管如此,这与HTTPS连接并不匹配。
至于检测客户端是否启用了javascript,只需使表单在客户端未启用js的情况下不可提交。使用类似action=”javascript:;”的内容,然后对实际提交使用onsubmit(您需要创建一个不可见的表单)。
很棒的脚本
@所有人和@ROMAC
嗨,我看到上面的帖子不是最新的,但也许有人在2013年阅读它们:-)
我认为这是一个非常有趣的话题,需要关注敏感的用户数据(如密码)是否会以明文或加密/哈希形式通过互联网传输,或者不会传输。此外,它们是否以加密/哈希形式保存在数据库中。
由于我非常关心用户数据安全,因此我选择以下方法作为我设置网站的首选方法
1. – 鉴于今天没有人禁用javascript(他永远无法获得现代的网络体验,因为几乎没有网站在没有javascript的情况下运行),我假设用户完全同意使用javascript来增强他或他的数据安全。
2. – 在注册过程中,我要求电子邮件地址作为第一个用户名并将其以明文形式发送到服务器,并将密码作为md5哈希(几个月前我开始使用sha256进行哈希)。
成功注册、电子邮件验证和首次登录后,他可以设置另一个用户名(或手机号码,参见以下第6点)。
3. – 有不同的方法可以在服务器端检查发送的密码是否是哈希值(通过启用的js)还是不是。
… – a) 使用上面ROMAC的解决方案,将隐藏字段从“false”设置为“true”(或任何已知值),
… – b) 在服务器上计算字符串长度(谁会使用32个字符长的密码,或者使用sha256的64个字符长的密码?)
… – c) 在页面加载时使用js/jquery创建登录表单,而不是php/html(如果js被禁用,则不会显示登录表单)
… – d) 不要包含type=submit按钮,而是一个type=button,并使用js和onclick事件发送登录表单,即使它是用php/html创建的(没有submit按钮,ENTER键将无法提交表单)
4. – 在服务器端,传入的密码哈希将再次使用sha256与随机盐一起进行哈希。生成的哈希值和盐存储在数据库中。
5. – 登录时,传入的密码(假定为哈希值)将再次使用存储的盐进行哈希,保存在一个临时变量中,该变量将与存储在数据库中的哈希值进行比较,如果两者相等……一切正常。
6. – 再次考虑 ROMACs 的帖子(像 RSA 这样的非对称加密):我更喜欢短信密钥,就像一些网上银行机构那样。
如果网站所有者同意,因为他对安全和加密的了解有限,我会为他预订一个短信账户(我使用德国提供商 goyya.com,因为我是德国人 :-))。对于非常敏感的用户帐户数据设置,用户必须触发一个短信验证码(注册时需要手机号码),他将收到两个验证码:来自服务器数据库的盐值,以及一个存储在会话中的 4 位随机数。
现在所有敏感数据流量(仅限此流量)都将使用 AES 加密发送,并且可以通过 jQuery AES 库在本地浏览器中解密读取。密钥从未通过互联网传输,它等于数据库中经过哈希处理的密码,并再次使用随机短信密钥进行哈希处理。
听起来很糟糕?嗯,也许吧。但它运行良好。一旦实施,它易于处理并且比 RSA 或 HTTPS 更安全,因为非对称密钥根本不会通过互联网传输。
只有一个挑战是,当用户丢失或更改了他的手机号码时……在用户资料中必须分配一个或两个可靠朋友(母亲、父亲)的手机号码,用户可以使用这些号码更改用户资料设置中的自己的手机号码。当用户想要登录到其私人区域时,此朋友或至少他的手机必须在场。
在高级套餐中,1000 条短信的费用为 85 欧元,这比网站 HTTPS 证书便宜得多,假设用户不需要每天访问其个人帐户设置。
@Rick,不使用 https 的原因是,如果使用自签名证书,最近的浏览器会弹出一个巨大的红色警告,“此网站不受信任!”。
这实际上意味着 https 只能用于预算足以购买 Verisign 证书的网站,以及可以托管此类证书的网络空间。所有其他网站都必须发送明文数据。称其为适得其反的安全措施。
嗨,大家好!也许有人知道为什么我使用上面描述的 js 函数加密某些字符串,然后使用像 http://md5decrypt.net/en/ 这样的在线服务进行加密时,它会提示哈希无效?
谢谢,谢谢,谢谢
非常感谢兄弟
你救了我!
感谢这个解决方案 :)
有人可以提供这个的反向逻辑吗?我的意思是 JS 本身中的解密。
根据您的需要,您可以考虑调用 rest API 为您生成 md5,甚至尝试反转它。查看 https://crypto.apitools.zone/md5.html 和 https://crypto.apitools.zone/md5-decode.html,这两个都非常快。