关于md5:一行MD5居然让小伙伴都回不了家

作者:京东批发 付伟 1. 前言大家好,当你点开这篇文章的时候兴许心想是哪个 XX 小编混到这里,先不要焦急扔臭鸡蛋,本文是一篇规范(正经)的问题复盘文章。好了,一行MD5竟然让小伙伴下不了班,到底是什么问题呢,让咱们一起来看看吧。 2. 注释2.1 需要是什么这里不再介绍具体的业务。简而言之,有两个接口(查问、确认)对前端页面提供服务。 查问接口返回的数据依赖于本地数据与内部接口计算后的后果,也就是页面展现的是数据快照。确认接口是依照页面的展现后果申请内部接口。 思考到用户关上展现页面时的数据与提交操作可能距离很久,理论申请时后果已发生变化,而这种操作会影响业务后果。因而在提交时会进行一次 check,如果发现数据发生变化须要提醒页面进行刷新。 为了不便大家了解,我简略的画了个图,毕竟下面太啰嗦了。 查问接口 确认接口 尽管这个图有点粗率,然而置信看到这里的小伙伴(默认都是聪慧的)都对需要了然于胸了。 2.2 我怎么搞得掰扯了半天,咱们的配角MD5还没有出场,别着急风雨总在彩虹后。 能够看出,这里须要前端将查问接口的返回值从新组装作为确认接口的入参。而后端须要再次走数据聚合的逻辑与前端传过来的业务值进行比拟,如果不匹配则提醒页面须要刷新。 所有看起来都牵强附会,那么小编遇到了什么问题呢? 简略来说有两点: 前端同学示意值不好传,因为这个页面比较复杂,具体起因小编也没深究,可能是被糊弄了。后端同学(也就是小编)发现,这样查问接口和确认接口耦合很重大,如果确认接口须要新的入参,那么就须要改变查问接口。随着查问接口逻辑越来越简单,确认接口的一个入参就须要一层一层的传过来。很不敌对。呵呵,机智的小编眉头一皱;计上心来,便想到了了MD5,看看百度百科怎么说 MD5 信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被宽泛应用的明码散列函数,能够产生出一个 128 位(16 字节)的散列值(hash value),用于确保信息传输残缺统一。一图胜千言 在工程,它差不多就是这么用。 String md5= Md5Utils.get(String source);可能有聪慧的小伙伴会说了,这是散列函数存在哈希碰撞,不同的字符串也有可能生成雷同的哈希值。 是的没错,然而在小编的业务场景中,这种呈现的概率微不足道,忽略不计,解释权归小编所有。 那么具体怎么做的呢,还是看图谈话: 革新后的查问接口 革新后的确认接口 咱们须要对查问接口返回的业务集要害属性进行组合哈希,这样能够生成数据快照值。确认接口无需再传入业务汇合,只须要传入数据快照值,后端进行比照即可晓得是否产生变更。 一切都是那么的美妙,接下来就到了动人心魄的编码环节。话不多说,小编的我的项目中引入了hutool包,什么你不晓得糊涂包? Hutool 是一个小而全的 Java 工具类库,通过静态方法封装,升高相干 API 的学习老本,进步工作效率,使 Java 领有函数式语言般的优雅,让 Java 语言也能够“甜甜的”。Hutool 中的工具办法来自每个用户的精雕细琢,它涵盖了 Java 开发底层代码中的方方面面,它既是大型项目开发中解决小问题的利器,也是小型我的项目中的效率担当;真不错,果然是效率担当,一行代码就搞定了。 /** * 生成数据哈希 */ private String generateSnapShotHash(AcceptListQueryWrapResultDTO wrapResultDTO) { StringBuilder builder = new StringBuilder(); for (AcceptListQueryResultDTO item : wrapResultDTO.getAllList()) { builder.append(item.getQuotationId()).append(item.getOperateType()).append(item.getPriceTypeCN()); } return MD5.create().digestHex16(builder.toString()); } ...

March 15, 2023 · 1 min · jiezi

关于md5:计算一个文件的-md5-值很费时间吗

有一个 1.2 GB 是视频文件 (svddb_sdk) ╭─pon@admini ~/code/vobile/svddb_sdk ‹master*› ╰─➤ ls -alh /home/pon/Downloads/svddb/meta/video_rename/1d0143aa-1d38-11ed-85a5-42010a800101.mp4-rw-rw-r-- 1 pon pon 1.2G Dec 6 11:17 /home/pon/Downloads/svddb/meta/video_rename/1d0143aa-1d38-11ed-85a5-42010a800101.mp4让咱们来看看应用 md5sum 计算该文件的 md5 值须要多久! ╰─➤ time md5sum /home/pon/Downloads/svddb/meta/video_rename/1d0143aa-1d38-11ed-85a5-42010a800101.mp46d8572d156db4b180a49d03f6bbf0c1a /home/pon/Downloads/svddb/meta/video_rename/1d0143aa-1d38-11ed-85a5-42010a800101.mp4md5sum 3.60s user 0.48s system 99% cpu 4.084 total花了 3.6s 哦

December 20, 2022 · 1 min · jiezi

关于md5:信息安全数据加密实战对项目中数据使用MD5算法进行加密

MD5加密算法的实现原理Java中MD5加密算法的实现: public class MD5 { // 全局数组 private final static String[] strDigit = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}; public class MD5 { } // 返回模式为数字和字符串 private static String byteToArrayString(byte bByte) { int iRet = bByte; if (iRet < 0) { iRet += 256; } int iD1 = iRet / 16; int iD2 = iRet % 16; return strDigits[iD1] + strDigits[iD2]; } // 返回模式只为数字 private static String byteToNum(byte bByte) { int iRet = bByte; if (iRet < 0) { iRet += 256; } return String.valueOf(iRet); } // 将字节数组转换成为16进制的字符串 private static String byteToString(byte[] bByte) { StringBuffer stringBuffer = new StringBuffer(); for (int i; i < bByte.length; i++) { StringBuffer.append(byteToArrayString(bByte[i])); } return stringBuffer.toString(); } // 获取MD5值 public static String GetMD5Code(String strObj) { String resultString = null; try { resultString = new String(); MessageDigest md5 = MessageDigest.getInstance("MD5"); // md5.digest() - 返回值为寄存Hash值后果的byte数组 resultString = byteToString(md5.digest(strObj.getBytes())); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return resultString; }} MessageDigest类MessageDigest类: ...

February 10, 2022 · 3 min · jiezi

angular使用md5CryptoJS-des加密

在业务系统中,通常需要对用户的密码进行加密,再时行http的请求。加强系统登录的安全验证。 常用的加密方式有MD5, Base64, CryptoJS的 AES DES等。下面介绍我常用的几种加密方法的使用: MD5加密1. 安装模块 ts-md5$ npm install ts-md5 --save2. 使用md5进行加密import { Md5 } from 'ts-md5';// ...// 密码password: string = "12345";// 加密方法 - md5加密decode() { const passwordMd5 = Md5.hashStr(this.password).toString(); // 结果:827ccb0eea8a706c4c34a16891f84e7b}Base64加密1.安装模块 js-base64$ npm install js-base64 --save2.使用md5进行加密import { Base64 } from 'js-base64';// ...// 密码password: string = "12345";// 加密方法 - Base64加密decode() { const passwordBase64 = Base64.encode(password); // 结果:MTIzNDU=}DES加密DES对称加密,是一种比较传统的加密方式,其加密运算、解密运算使用的是同样的密钥key,信息的发送者和信息的接收者在进行信息的传输与处理时,必须共同持有该密码(称为对称密码),是一种对称加密算法。crypto-js Github: https://github.com/brix/crypt... 1.安装模块 crypto-js$ npm install crypto-js --save2.使用DES进行加密import CryptoJS from 'crypto-js';// ...// 密钥key: string = "abcdefg";// 密码password: string = "12345";// 加密方法 - des加密decode() { // key编码 const keyHex = CryptoJS.enc.Utf8.parse(this.key); console.log(keyHex.toString()); // 结果:61626364656667 // 加密 const passwordDES = CryptoJS.DES.encrypt(this.password, keyHex, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }).toString(); console.log(passwordDES); // 结果:zYGeIdaZpEM=}3. 使用AES进行加密加密用法基本与des一致。 ...

June 3, 2019 · 1 min · jiezi

「 加密算法 」MD5

一.简介MD5是一种信息摘要算法(Message-Digest Algorithm),可以产生出一个128位(8位(bit)=1字节(byte),16字节)的散列值(hash).12345 MD5===> e10adc3949ba59abbe56e057f20f883e// 说好的128位,为什么有32个字符.//这串码是16进制表示,1位==4位二进制.112345 MD5===> e10adc3949ba59abbe56e057f20f883e2// 说好的128位,为什么有32个字符.3//这串码是16进制表示,1位==4位二进制.源于其算法,不管是对于多大的文件数据进行MD5加密,所得到结果的长度都是32个字符(1个中文字符等于2个字节,一个字母字符等于一个字节).对于内容相同的数据进行加密,得到的结果必然是相同的,如果内容有改动,哪怕是一个字节,其MD5值也会改动.所以也可以说MD5是有损算法,在一定程度有丢失.举一个假设就是压缩文件,前后可以进行压缩和解压,并且内容是不可以丢失的,如果采用MD5来做,那么解压后肯定有一部分的数据丢失了,肯定不可取.所以MD5的结果是不可逆运算的,也就是几乎不可能通过MD5值去逆推出原始数据.因为不管是多大的文件最终都是转化成128位的值,所以现实是可能存在有不同的原始数据被转化成同样的MD5值的.但是想主动搜寻两个不同的数据,让他们具有相同的MD5值,是非常困难.或者有一个原始数据和它的MD5数据,想再找一个和其MD5数据一样的原始数据也几乎是不可能的.但是并不是说MD5是完全不可破解的.有专业的黑客甚至普通黑客也可以利用MD5值实际是有损压缩技术这一原理,将MD5的逆运算的值作为一张表俗称彩虹表的散列表来破解密码。市面上也有不少的MD5破解网站,大体的原理类似,通过查字典的方式去查找.二.应用01. 一致性检验比如说在进行文件下载的时候,会生成文件内容的MD5值.等到文件完整下载的时候,再用该文件得出MD5值和之前的文件的MD5值进行对比,用以确认文件的内容的一致性.有很多时候,你会发现网络上的很多文件的命名都是一段hash值加后缀名的方式.这样处理的好处是能在一定的程度上避免同名,更大的用处是能够根据其文件内容来获取专属的MD5值来命名.这样做,可以算是以内容来命名,可以一定程度上避免资源的浪费,重复的文件.所以说,MD5有点类似"指纹",每一个都独一无二.只要内容不一致,就产生不一样的MD5值.利用MD5算法来进行文件校验的方案被大量应用到软件下载站、论坛数据库、系统文件安全等方面.02. 数字签名MD5的典型应用是对一段字符串(重要隐私信息)产生,以防止被“篡改”。你将一段话写在一个文件中,并产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内容,你对这个文件重新计算MD5时就会发现(两个MD5值不相同)。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。03. 安全访问认证在现实的大部分场景都有登录的需要.当用户登录的时候,系统把用户输入的密码进行MD5 Hash运算,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这可以避免用户的密码被具有系统管理员权限的用户知道。三. 原理MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。引用自-刘俊辉. MD5 消息摘要算法实现及改进[J]. 福建电脑, 2007 (4): 92-93.function md5(string) { function md5_RotateLeft(lValue, iShiftBits) { return (lValue << iShiftBits) | (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(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 md5_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 md5_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 = md5_Utf8Encode(string); x = md5_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 = md5_FF(a, b, c, d, x[k + 0], S11, 0xD76AA478); d = md5_FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756); c = md5_FF(c, d, a, b, x[k + 2], S13, 0x242070DB); b = md5_FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE); a = md5_FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF); d = md5_FF(d, a, b, c, x[k + 5], S12, 0x4787C62A); c = md5_FF(c, d, a, b, x[k + 6], S13, 0xA8304613); b = md5_FF(b, c, d, a, x[k + 7], S14, 0xFD469501); a = md5_FF(a, b, c, d, x[k + 8], S11, 0x698098D8); d = md5_FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF); c = md5_FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1); b = md5_FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE); a = md5_FF(a, b, c, d, x[k + 12], S11, 0x6B901122); d = md5_FF(d, a, b, c, x[k + 13], S12, 0xFD987193); c = md5_FF(c, d, a, b, x[k + 14], S13, 0xA679438E); b = md5_FF(b, c, d, a, x[k + 15], S14, 0x49B40821); a = md5_GG(a, b, c, d, x[k + 1], S21, 0xF61E2562); d = md5_GG(d, a, b, c, x[k + 6], S22, 0xC040B340); c = md5_GG(c, d, a, b, x[k + 11], S23, 0x265E5A51); b = md5_GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA); a = md5_GG(a, b, c, d, x[k + 5], S21, 0xD62F105D); d = md5_GG(d, a, b, c, x[k + 10], S22, 0x2441453); c = md5_GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681); b = md5_GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8); a = md5_GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6); d = md5_GG(d, a, b, c, x[k + 14], S22, 0xC33707D6); c = md5_GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87); b = md5_GG(b, c, d, a, x[k + 8], S24, 0x455A14ED); a = md5_GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905); d = md5_GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8); c = md5_GG(c, d, a, b, x[k + 7], S23, 0x676F02D9); b = md5_GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A); a = md5_HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942); d = md5_HH(d, a, b, c, x[k + 8], S32, 0x8771F681); c = md5_HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122); b = md5_HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C); a = md5_HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44); d = md5_HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9); c = md5_HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60); b = md5_HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70); a = md5_HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6); d = md5_HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA); c = md5_HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085); b = md5_HH(b, c, d, a, x[k + 6], S34, 0x4881D05); a = md5_HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039); d = md5_HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5); c = md5_HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8); b = md5_HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665); a = md5_II(a, b, c, d, x[k + 0], S41, 0xF4292244); d = md5_II(d, a, b, c, x[k + 7], S42, 0x432AFF97); c = md5_II(c, d, a, b, x[k + 14], S43, 0xAB9423A7); b = md5_II(b, c, d, a, x[k + 5], S44, 0xFC93A039); a = md5_II(a, b, c, d, x[k + 12], S41, 0x655B59C3); d = md5_II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92); c = md5_II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D); b = md5_II(b, c, d, a, x[k + 1], S44, 0x85845DD1); a = md5_II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F); d = md5_II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0); c = md5_II(c, d, a, b, x[k + 6], S43, 0xA3014314); b = md5_II(b, c, d, a, x[k + 13], S44, 0x4E0811A1); a = md5_II(a, b, c, d, x[k + 4], S41, 0xF7537E82); d = md5_II(d, a, b, c, x[k + 11], S42, 0xBD3AF235); c = md5_II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB); b = md5_II(b, c, d, a, x[k + 9], S44, 0xEB86D391); a = md5_AddUnsigned(a, AA); b = md5_AddUnsigned(b, BB); c = md5_AddUnsigned(c, CC); d = md5_AddUnsigned(d, DD); } return (md5_WordToHex(a) + md5_WordToHex(b) + md5_WordToHex(c) + md5_WordToHex(d)).toLowerCase();}四. 前端的应用目前在GitHub上找到两个有MD5功能还不错的库(基于JavaScript)1.JavaScript-MD5功能单一,专门处理MD5.star数目前3k+,使用非常简单,并且前后端都可用.//前端<script src=“js/md5.min.js”></script>var hash = md5(“value”); // “2063c1608d6e0baf80249c42e2be5804”//后端npm install blueimp-md5require(“http”).createServer(function (req, res) { // The md5 module exports the md5() function: var md5 = require("./md5"), // Use the following version if you installed the package with npm: // var md5 = require(“blueimp-md5”), url = require(“url”), query = url.parse(req.url).query; res.writeHead(200, {“Content-Type”: “text/plain”}); // Calculate and print the MD5 hash of the url query: res.end(md5(query));}).listen(8080, “localhost”);console.log(“Server running at http://localhost:8080/”);2.crypto-js功能强大,不止处理MD5,支持的模块非常多,star数目前6k+,前后端可用.//后端 npm包管理npm install crypto-jsimport sha256 from ‘crypto-js/sha256’;import hmacSHA512 from ‘crypto-js/hmac-sha512’;import Base64 from ‘crypto-js/enc-base64’;const message, nonce, path, privateKey; // …const hashDigest = sha256(nonce + message);const hmacDigest = Base64.stringify(hmacSHA512(path + hashDigest, privateKey));//前端 Brower管理bower install crypto-js五. “加盐"如果想提高你的安全性,那么可以采取再进一步对原始数据进行“加盐”,“盐”就是一串比较复杂的字符串。你所添加的"盐"越长越复杂,加密后破解起来就越麻烦.你可以尝试下在原始数据上加一串复杂的字符串,然后再去进行MD5加密.这样即使解开MD5,也不能知道你的原始数据到底是那一段.但是即使这样也不可能绝对是绝对安全.这个“盐”还是有泄漏的风险。比如苹果端、安卓端、前端、后台等等那些个技术人员都是知道的,都有可能泄漏出去。放在服务器也不绝对安全,也有手段去抓取.但是相对的还是进一步的提高了加密的安全性. ...

April 20, 2019 · 7 min · jiezi