直接引入

// 用于计算MD5的常量表
const MD5_CONSTANT_TABLE = [
  0x07, 0x12, 0x17, 0x93, 0x29, 0x3d, 0xca, 0xde,
  0x5b, 0x5e, 0x6d, 0x70, 0x98, 0x9c, 0xaf, 0xb0,
  0xbd, 0xd3, 0xe0, 0xf3, 0x10d, 0x136, 0x146, 0x168,
  0x199, 0x1bd, 0x1c3, 0x1d2, 0x277, 0x28d, 0x298, 0x2b0,
  0x2c5, 0x2f2, 0x323, 0x32e, 0x340, 0x3f7, 0x425, 0x44c,
  0x461, 0x4cc, 0x4ea, 0x513, 0x56f, 0x5b6, 0x5f1, 0x62c,
  0x644, 0x6a6, 0x6d3, 0x6de, 0x6f0, 0x718, 0x732, 0x74f,
  0x77a, 0x7a7, 0x7e4, 0x7f0, 0x800, 0x819, 0x853, 0x85f
];

// 用于计算MD5的变化表
const MD5_CHANGE_TABLE = [
  [ 0,  1,  2,  3], [ 4,  5,  6,  7], [ 8,  9, 10, 11], [12, 13, 14, 15],
  [ 1,  6, 11,  0], [ 5, 10, 15,  4], [ 9, 14,  3,  8], [13,  2,  7, 12],
  [ 5,  8, 11, 14], [ 1,  4,  7, 10], [13,  0,  3,  6], [ 9, 12, 15,  2],
  [ 0,  7, 14,  5], [10, 13,  4, 15], [ 6,  9,  8, 11], [ 3,  2, 12,  1]
];

/**
 * 将一个二进制数转换为16进制字符串
 * @param {number} byte - 二进制数
 * @returns {string} 16进制字符串
 * @private
 */
function _byteToHex(byte) {
  return byte < 16 ? '0' + byte.toString(16) : byte.toString(16);
}

/**
 * 将一个字节数组转换为16进制字符串
 * @param {Array<number>} bytes - 字节数组
 * @returns {string} 16进制字符串
 * @private
 */
function _bytesToHex(bytes) {
  return bytes.map(_byteToHex).join('');
}

/**
 * 在字符串末尾填充bit位的0,使其长度为length的倍数
 * @param {string} str - 原始字符串
 * @param {number} bit - 每次填充的位数
 * @param {number} length - 填充后字符串的长度
 * @returns {string} 填充后的字符串
 * @private
 */
function _pad(str, bit, length) {
  let targetLength = length * bit;
  let padLength = targetLength - str.length;
  if (padLength < 0) {
    // 字符串已经足够长,无需填充
    return str;
  }
  let padStr = '';
  while (padLength--) {
    padStr += '0';
  }
  return str + padStr;
}

/**
 * 对字符串进行MD5加密
 * @param {string} data - 待加密的字符串
 * @returns {string} 加密后的字符串(16进制)
 */
function md5(data) {
  // 将字符串转换为UTF8的二进制数组
  let utf8Bytes = unescape(encodeURIComponent(data))
    .split('')
    .map(char => char.charCodeAt(0));
  let length = utf8Bytes.length * 8; // 字符串长度
  utf8Bytes.push(0x80); // 添加一个1
  let padLength = Math.ceil((utf8Bytes.length * 8 + 64) / 512) * 16 - utf8Bytes.length;// 填充长度(字节数)

  for (let i = 0; i < padLength; i++) {
    utf8Bytes.push(0x00);
  }

  let bitLength = length.toString(2).split('');
  bitLength = _pad(bitLength, 1, 64).split('');// 将长度转换为64位的二进制数
  bitLength.forEach(bit => utf8Bytes.push(parseInt(bit, 2))); // 将长度添加到末尾

  let a = 0x67452301;
  let b = 0xefcdab89;
  let c = 0x98badcfe;
  let d = 0x10325476;
  let chunks = [];

  // 将每个512位(64字节)的块分成16个32位(4字节)的小块
  for (let i = 0, len = utf8Bytes.length; i < len; i += 64) {
    chunks.push(utf8Bytes.slice(i, i + 64));
  }

  // 对每个小块进行处理
  for (let i = 0, len = chunks.length; i < len; i++) {
    let [ A, B, C, D ] = [ a, b, c, d ];
    let chunk = chunks[i];

    // 循环64次进行加密
    for (let j = 0; j < 64; j++) {
      let f, g;

      if (j < 16) {
        f = (B & C) | ((~B) & D);
        g = j;
      } else if (j < 32) {
        f = (D & B) | ((~D) & C);
        g = (5 * j + 1) % 16;
      } else if (j < 48) {
        f = B ^ C ^ D;
        g = (3 * j + 5) % 16;
      } else {
        f = C ^ (B | (~D));
        g = (7 * j) % 16;
      }

      let index1 = MD5_CHANGE_TABLE[j][0];
      let index2 = MD5_CHANGE_TABLE[j][1];
      let index3 = MD5_CHANGE_TABLE[j][2];
      let index4 = MD5_CHANGE_TABLE[j][3];
      let x = chunk[index4] << 24 | chunk[index3] << 16 | chunk[index2] << 8 | chunk[index1];
      let y = (f + A + MD5_CONSTANT_TABLE[j] + x) & 0xffffffff;
      A = D;
      D = C;
      C = B;
      B = (B + (y << g | y >>> (32 - g))) & 0xffffffff;
    }

    a = (a + A) & 0xffffffff;
    b = (b + B) & 0xffffffff;
    c = (c + C) & 0xffffffff;
    d = (d + D) & 0xffffffff;
  }

  let result = [ a, b, c, d ]
    .map(num => _pad(num.toString(2), 8, 4)) // 将数字转换为二进制字符串,并补齐到32位
    .join(''); // 将四个32位二进制字符串拼接
  return _bytesToHex(result.match(/\d{8}/g).map(byte => parseInt(byte, 2))); // 将二进制字符串转换为16进制字符串
}
// 使用
md5(加密内容)

npm导入

npm i --save js-md5
// 全局定义
import md5 from 'js-md5'
Vue.prototype.$md5 = md5

// 使用方法
this.$md5(加密内容)
文章目录