本系列最开始是为了本身面试准备的.后来发现整理愈来愈多,差很少有十二万字符,最后决定仍是分享出来给你们.前端
为了分享整理出来,花费了本身大量的时间,起码是只本身用的三倍时间.若是喜欢的话,欢迎收藏,关注我!谢谢!vue
前端面试查漏补缺--Index篇(12万字符合集) 包含目前已写好的系列其余十几篇文章.后续新增值文章不会再在每篇添加连接,强烈建议议点赞,关注合集篇!!!!,谢谢!~面试
后续还会继续添加设计模式,前端工程化,项目流程,部署,闭环,vue常考知识点 等内容.若是以为内容不错的话欢迎收藏,关注我!谢谢!算法
目前本人也在准备跳槽,但愿各位大佬和HR小姐姐能够内推一份靠谱的武汉 前端岗位!邮箱:bupabuku@foxmail.com.谢谢啦!~数据库
这是一个绕不开的话题,确定有不少见解.但我看来:前端加密看起来有意义,但有时候看起来并无"意义". 但整体来看是有意义的,打个比喻:既然市面上大部分锁均可以在20分钟内撬开,那门上装锁是否还有意义?后端
有意义:
在 HTTP 协议下,数据是明文传输,传输过程当中网络嗅探可直接获取其中的数据。 如用户的密码和信用卡相关的资料,一旦被中间人获取,会给用户带来极大的安全隐患。另外一方面在非加密的传输过程当中,攻击者可更改数据或插入恶意的代码等。那么前端加密的意义: 即在数据发送前将数据进行哈希或使用公钥加密。若是数据被中间人获取,拿到的则再也不是明文。设计模式
固然还有其余一些优势:例如避免后端等打印日志直接暴露明文密码,还能够避免明文撞库等.前端工程化
没有"意义": 前端加密,其实只能防君子不能防小人。 前端系统的控制权是彻底在用户手里的,也就是说,前端作什么事情,用户有彻底的控制权。即便前端加密不能够防范中间人攻击,包括HTTPS,由于中间仍是存在着各类代理,客户端代理,服务端代理.是很难作到不被劫持的.跨域
这里简单说下:浏览器
总结一下:
这里我只是简单梳理下,若是还有疑惑想深刻探(si)讨(bi)的,能够看下逼乎上的这篇文章
• JavaScript 加密后传输(具体能够参考后面的常见加密方法)
• 浏览器插件内进行加密传输 (这个用得不是不少,这里暂不细究)
• Https 传输
不一样于哈希(后面会提到),加密(Encrypt)是将目标文本转换成具备不一样长度的、可逆的密文。也就是说加密算法是可逆的,并且其加密后生成的密文长度和明文自己的长度有关。因此若是被保护数据在之后须要被还原成明文,则须要使用加密。
在加密算法中又分为对称加密(symmetric encryption)和非对称加密(asymmetric encryption)。
对称加密采用了对称密码编码技术,它的特色是文件加密和解密使用相同的密钥加密.也就是加密和解密都是用同一个密钥,这种方法在密码学中叫作对称加密算法.
对称加密算法使用起来简单快捷,密钥较短,且破译困难,除了数据加密标准(DES),另外一个对称密钥加密系统是国际数据加密算法(IDEA),它比DES的加密性好,并且对计算机功能要求也没有那么高.
常见的对称加密算法有DES、3DES、Blowfish、IDEA、RC四、RC五、RC6和AES
注意: 由于前端的透明性,对于登陆密码等敏感信息,就不要使用JavaScript来进行对称加密. 由于别人能够从前端获得密匙后,能够直接对信息进行解密!
非对称加密算法须要两个密钥:公钥(publickey)和私钥(privatekey)。 公钥与私钥是一对,若是用公钥对数据进行加密,只有用对应的私钥才能解密;若是用私钥对数据进行加密,那么只有用对应的公钥才能解密。 由于加密和解密使用的是两个不一样的密钥,因此这种算法叫做非对称加密算法。
非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把做为公钥向其它方公开;获得该公钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用本身保存的另外一把专用密钥对加密后的信息进行解密。甲方只能用其专用密钥解密由其公钥加密后的任何信息。
常见的非对称加密算法有:RSA、ECC(移动设备用)、Diffie-Hellman、El Gamal、DSA(数字签名用)
哈希(Hash)是将目标文本转换成具备固定长度的字符串(或叫作消息摘要)。 当输入发生改变时,产生的哈希值也是彻底不一样的。从数学角度上讲,一个哈希算法是一个多对一的映射关系,对于目标文本 T,算法 H 能够将其惟一映射为 R,而且对于全部的 T,R 具备相同的长度,因此 H 不存在逆映射,也就是说哈希算法是不可逆的。
基于哈希算法的特性,其适用于该场景:被保护数据仅仅用做比较验证且不须要还原成明文形式。比较经常使用的哈希算法是 MD5 和 SHA1 。
咱们比较熟悉的使用哈希存储数据的例子是:当咱们登陆某个已注册网站时,在忘记密码的状况下须要重置密码,此时网站会给你发一个随机的密码或者一个邮箱激活连接,而不是将以前的密码发给你,这就是由于哈希算法是不可逆的。
须要注意的是:在 Web 应用中,在浏览器中使用哈希加密的同时也要在服务端上进行哈希加密。
服务端哈希加密缘由: 一方面由于不须要将密文解密成明文来比对密码,另外一方面是一旦加密算法和密钥泄露,那么整个用户资料库就至关于明文存储了。若是前端传过来的是明文,那么在注册时将其哈希,存入数据库。登陆时,将密码哈希和数据库对应的数据比对,若一致则说明密码正确。
如今,对于简单的哈希算法的攻击方法主要有:寻找碰撞法和穷举法。因此,为了保证数据的安全,能够在哈希算法的基础上进一步的加密,常见的方法有:加盐、慢哈希、密钥哈希、XOR 等。
加盐加密是一种对系统登陆口令的加密方式,它实现的方式是将每个口令同一个叫作“盐”(salt)的 n 位随机数相关联。
为了方便理解:这里引用这位同窗的文章进行说明:
使用salt加密,它的基本想法是这样的:
因为验证密码时和最初散列密码时使用相同的盐值,因此salt的存储在数据库。而且这个值是由系统随机产生的,而非硬编码。这就保证了所要保护对象的机密性。
注册时:
登录时:
PS: 其实图中的这种登陆也是不安全的. 缘由是后面要提到的盐值复用
使用加盐加密时须要注意如下两点:
若是盐值过短,攻击者能够预先制做针对全部可能的盐值的查询表。例如,若是盐值只有三个 ASCII 字符,那么只有 95x95x95=857,375 种可能性,加大了被攻击的可能性。还有,不要使用可预测的盐值,好比用户名,由于针对某系统用户名是惟一的且被常常用于其余服务。
在项目开发中,有时会遇到将盐值写死在程序里或者只有第一次是随机生成的,以后都会被重复使用,这种加盐方法是不起做用的。以登陆密码为例,若是两个用户有相同的密码,那么他们就会有相同的哈希值,攻击者就可使用反向查表法对每一个哈希值进行字典攻击,使得该哈希值更容易被破解。
因此正确的加盐方法以下:
(1)盐值应该使用加密的安全伪随机数生成器( Cryptographically Secure Pseudo-Random Number Generator,CSPRNG )产生,好比 C 语言的 rand() 函数,这样生成的随机数高度随机、彻底不可预测;
(2)盐值混入目标文本中,一块儿使用标准的加密函数进行加密;
(3)盐值要足够长(经验代表:盐值至少要跟哈希函数的输出同样长)且永不重复;
(4)盐值最好由服务端提供,前端取值使用。
顾名思义,慢哈希函数是将哈希函数变得很是慢,使得攻击方法也变得很慢,慢到足以令攻击者放弃,而每每由此带来的延迟也不会引发用户的注意。下降攻击效率用到了密钥扩展( key stretching)的技术,而密钥扩展的实现使用了一种 CPU 密集型哈希函数( CPU-intensive hash function)。看起来有点晕~仍是关注下该函数怎么用吧!
若是想在一个 Web 应用中使用密钥扩展,则须要设定较低的迭代次数来下降额外的计算成本。咱们通常直接选择使用标准的算法来完成,好比 PBKDF2 或 bcrypt 。PHP、斯坦福大学的 JavaScript 加密库都包含了 PBKDF2 的实现,浏览器中则能够考虑使用 JavaScript 完成,不然这部分工做应该由服务端进行计算。
密钥哈希是将密钥添加到哈希加密,这样只有知道密钥的人才能够进行验证。目前有两种实现方式:使用 ASE 算法对哈希值加密、使用密钥哈希算法 HMAC 将密钥包含到哈希字符串中。为了保证密钥的安全,须要将其存储在外部系统(好比一个物理上隔离的服务端)。
即便选择了密钥哈希,在其基础上进行加盐或者密钥扩展处理也是颇有必要。目前密钥哈希用于服务端比较多,例如来应对常见的 SQL 注入攻击。
XOR 你们都不陌生,它指的是逻辑运算中的 “异或运算”。两个值相同时,返回 false,不然返回 true,用来判断两个值是否不一样。
JavaScript 语言的二进制运算,有一个专门的 XOR 运算符,写做^。
1 ^ 1 // 0
0 ^ 0 // 0
1 ^ 0 // 1
0 ^ 1 // 1
复制代码
XOR 运算有一个特性:若是对一个值连续作两次 XOR,会返回这个值自己。这也是其能够用于信息加密的根本。
message XOR key // cipherText
cipherText XOR key // message
复制代码
目标文本 message,key 是密钥,第一次执行 XOR 会获得加密文本;在加密文本上再用 key 作一次 XOR 就会还原目标文本 message。为了保证 XOR 的安全,须要知足如下两点:
(1)key 的长度大于等于 message ;
(2)key 必须是一次性的,且每次都要随机产生。
下面以登陆密码加密为例介绍下 XOR 的使用:
第一步:使用 MD5 算法,计算密码的哈希;
const message = md5(password);
复制代码
第二步:生成一个随机 key 值;
第三步:进行 XOR 运算,求出加密后的 message。
function getXOR(message, key)
const arr = [];
//假设 key 是32位的
for (let i = 0; i < 32; i++) {
const m = parseInt(message.substr(i, 1), 16);
const k = parseInt(key.substr(i, 1), 16);
arr.push((m ^ k).toString(16));
}
return arr.join('');
}
复制代码
如上所示,使用 XOR 和一次性的密钥 key 对密码进行加密处理,只要 key 没有泄露,目标文本就不会被破解。
上面说了那么多,问题就来了:咱们应该使用什么样的哈希算法呢?
(1)选择通过验证的成熟算法,如 PBKDF2 等 ;
(2)crypt 的安全版本;
(3)避免使用本身设计的加密算法。
对于HMAC算法,我也不是太了解.看了几篇文章,感受和加盐很像,就是salt换成后端随机生成的(好像能够防止重放攻击).而后再经过HMAC算法,获得摘要.
关于HMAC算法部分能够详细看这篇文章,我是学渣,看了半天也不是太懂.=.=
大概过程以下:
好处:
前端先将密码哈希,而后和用户输入的验证码进行哈希,获得的结果做为密码字段发送给服务器。服务器先确认验证码正确,而后再进行密码验证,不然直接返回验证码错误信息。
这种实践保证了密码在传输过程当中的资料安全,即便攻击者拿到了数据也没法重放。图形化验证码更是增长了难度。另外一方面该实践大大增长了撞库的成本。
前端加密必定程度保障了传输过程当中的资料安全,那么会不会有对两端(客户端和服务器)有安全帮助呢?
有帮助,使用一些前端加密手段,能够增长拖库后的数据破解难度。可是验证码方法不具备这样的功能,由于数据库存的还是明文密码哈希后的结果,那么攻击者能够绕过前端加密,能够直接暴力破解。
你们常常说的是 Base64 加密,有 Base64 加密吗?真木有,只有 Base64 编码。
Base64 是一种基于 64 个可打印字符来表示二进制数据的表示方法。经常使用于在一般处理文本数据的场合,表示、传输、存储一些二进制数据,包括 MIME 的 email,email via MIME,在 XML 中存储复杂数据;主要用来解决把不可打印的内容塞进可打印内容的需求。js中 base64 方法使用以下:
//1.编码
var result = Base.encode('shotCat好帅!'); //--> "c2hvdENhdOWlveW4hSE="
//2.解码
var result2 = Base.decode(result); //--> 'shotCat好帅!' 没错,我就是这么不要脸!!!
复制代码
所以,Base64 适用于小段内容的编码,好比数字证书签名、Cookie的内容等;并且 Base64 也是一种经过查表的编码方法,不能用于加密,若是须要加密,请使用专业的加密算法。
PS: 对于前端来讲,base64用得最多的也就是图片转码吧.
数字签名主要用于:确认信息来源于特定的主体且信息完整、未被篡改,发送方生成签名,接收方验证签名。
发送方: 首先计算目标文本的摘要(哈希值),经过私钥对摘要进行签名,将目标文本和电子签名发送给接收方。
接收方: 验证签名的步骤以下:
数字签名与非对称加密区别:
为了不重复,这部份内容在本系列-HTTP与HTTPS有详细介绍