〇、简介
MD5 是哈希算法(散列算法)的一种应用。Hash 算法虽然被称为算法,但实际上它更像是一种思想。Hash 算法没有一个固定的公式,只要符合散列思想的算法都可以被称为是 Hash 算法。
算法目的就是,把任意长度的输入(又叫做预映射 pre-image),通过散列算法变换成固定长度的输出,该输出就是散列值。
注意,不同的输入可能会散列成相同的输出,所以不能从散列值来确定唯一的输入值。
散列函数简单的说就是:一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
Hash 算法是一个广义的算法,也可以认为是一种思想,使用 Hash 算法可以提高存储空间的利用率,可以提高数据的查询效率,因为很难找到其逆向规律,也可以做数字签名来保障数据传递的安全性。所以Hash算法被广泛地应用在互联网应用中。
散列值不同 => 原始值不同
如果两个散列值是不相同的(根据同一函数),那么这两个散列值的原始输入也是不相同的。这个特性是散列函数具有确定性的结果。
散列值相同 ≠> 原始值相同
散列函数的输入和输出不是一一对应的,如果两个散列值相同,两个输入值很可能是相同的,但不绝对肯定二者一定相等(可能出现哈希碰撞)。
关于“撞库”(Credential Stuffing Attack)
其在网络安全中是一个古老的概念,按中文的字面意思解读,就是“碰撞数据库”的意思。“碰撞”意味着碰运气,即不一定能成功;而“数据库”中往往存储着大量敏感数据,比如我们登录一个网站所需要的用户名、密码,再比如手机号、身份证号等个人隐私信息。“撞库”在英文中的表述为 Credential Stuffing(密码嗅探),也非常直白的说明了撞库的主要场景:试图获取正确的账号/密码组合,大白话就是“盗号”。
二、C# 代码实现
根据传入参数,返回分大小写的 16 位或 32 位密文,并且可自定义编码规则。
// 测试
string jiamihou16 = SecurityMD5.MD5Encrypt("TestString", 16, false); // 8828701f97fa4511
string jiamihou32 = SecurityMD5.MD5Encrypt("TestString", 32);// 5B56F40F8828701F97FA4511DDCD25FB
///
/// MD5 加密方法
///
/// 待加密字符串
/// 位数:16/32/64
/// 输出大小写:true 大写;false 小写(返回为 64 位时不区分大小写)
/// 字符编码规则,为空默认:UTF8
///
public static string MD5Encrypt(string md5instr, int digit, bool isupper = true, Encoding encoding = null)
{
string md5outstr = string.Empty;
if (encoding == null)
encoding = Encoding.UTF8;
switch (digit)
{
case 16:
// SecurityMD5.MD5Encrypt(md5instr, 16, true); // 16位大写
// SecurityMD5.MD5Encrypt(md5instr, 16, false); // 16位小写
var md5provider = new MD5CryptoServiceProvider();
var hashinstr16 = md5provider.ComputeHash(encoding.GetBytes(md5instr));
md5outstr = BitConverter.ToString(hashinstr16, 4, 8);
md5outstr = md5outstr.Replace("-", "");
if (!isupper)
md5outstr = md5outstr.ToLower();
return md5outstr;
case 32:
// SecurityMD5.MD5Encrypt(md5instr, 32, true); // 32位大写
// SecurityMD5.MD5Encrypt(md5instr, 32, false); // 32位小写
MD5 md532 = MD5.Create();
byte[] hashinstr32 = md532.ComputeHash(encoding.GetBytes(md5instr));
string upperorlowerflag = isupper ? "X2" : "x2";
for (int i = 0; i
三、js 代码实现
1/2 通过 crypto-js.js 实现
此方法调用比较简单,但是只能获取 32 位的密文。
// 先引入 js 文件
// npm(Node.js package manager)方式引入
> npm install crypto-js
// 直接调用即可
var jiemihou = CryptoJS.MD5("TestString"); // 57fe567eaa866373f851a526f07d9e26
var jiemihoudx = CryptoJS.MD5("TestString").toString().toUpperCase(); // 5B56F40F8828701F97FA4511DDCD25FB
2/2 通过 js 方法实现
根据传入参数,返回分大小写的 16 位或 32 位密文。
// 测试
md5_function("TestString",16,false)
>'8828701f97fa4511'
md5_function("TestString",32,true)
>'5B56F40F8828701F97FA4511DDCD25FB'
// MD5 加密(入参分别是:待加密内容、返回位数、是否为大写)
function md5_function(md5instr, digit, isupper){
function md5_RotateLeft(lValue, iShiftBits) {
return (lValue >> (32 - iShiftBits));
}
function md5_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 md5_F(x, y, z) {
return (x & y) | ((~x) & z);
}
function md5_G(x, y, z) {
return (x & z) | (y & (~z));
}
function md5_H(x, y, z) {
return (x ^ y ^ z);
}
function md5_I(x, y, z) {
return (y ^ (x | (~z)));
}
function md5_FF(a, b, c, d, x, s, ac) {
a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_F(b, c, d), x), ac));
return md5_AddUnsigned(md5_RotateLeft(a, s), b);
};
function md5_GG(a, b, c, d, x, s, ac) {
a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_G(b, c, d), x), ac));
return md5_AddUnsigned(md5_RotateLeft(a, s), b);
};
function md5_HH(a, b, c, d, x, s, ac) {
a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_H(b, c, d), x), ac));
return md5_AddUnsigned(md5_RotateLeft(a, s), b);
};
function md5_II(a, b, c, d, x, s, ac) {
a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_I(b, c, d), x), ac));
return md5_AddUnsigned(md5_RotateLeft(a, s), b);
};
function md5_ConvertToWordArray(md5instr) {
var lWordCount;
var lMessageLength = md5instr.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 >> 29;
return lWordArray;
};
function md5_WordToHex(lValue) {
var WordToHexValue = "", WordToHexValue_temp = "", lByte, lCount;
for (lCount = 0; lCount >> (lCount * 8)) & 255;
WordToHexValue_temp = "0" + lByte.toString(16);
WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2);
}
return WordToHexValue;
};
function md5_Utf8Encode(md5instr) {
md5instr = md5instr?.replace(/rn/g, "n");
var utftext = "";
for (var n = 0; n 127) && (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;
md5instr = md5_Utf8Encode(md5instr);
x = md5_ConvertToWordArray(md5instr);
a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
for (k = 0; k
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.e1idc.net