A. Vue3问题:如何实现密码加密登录前后端!
Vue3密码加密登录实现教程
在前端开发中,用户密码的加密和安全传输至关重要。本文将深入探讨如何在前后端实现密码加密,确保数据安全。以下是本文的主要内容概要:
首要目标是确保用户密码在登录和注册请求中不暴露明文,以及后端数据库不存储明文密码。为了达到这个目标,我们通常采取前端加密传输,后端再加密存储的方式。
在实际项目中,常用的加密方式包括对称加密、非对称加密和哈希函数。其中,对称加密(如BCrypt)是首选,因为它既安全又易于使用。前端需要将用户密码加密后发送,后端同样使用BCrypt加密存储。
在模板中引入必要的加密库,如Vue的BCrypt插件,然后在逻辑层处理用户密码加密。
后端接口接收加密后的密码,再进行一次加密操作,确保存储在数据库中的密码是加密状态。
不同的加密算法有其优缺点,AES、RSA、MD5、SHA、BCrypt、PBKDF2和SCrypt都是可能的选择,其中BCrypt因其安全性和性能平衡而常被推荐。
密码学中的不可逆性意味着无法通过哈希值直接获取原始数据,这在保护数据完整性和验证一致性时至关重要。MD5加盐处理可以进一步提高安全性。
Base64编码用于数据传输,不是加密手段,它只是将二进制数据转为ASCII字符,不适合加密大文件。
本教程旨在帮助开发者理解密码加密在Vue3项目中的应用,通过合理的加密策略保护用户数据安全。希望本文内容对您有所帮助,如有任何问题,欢迎加入我们的技术交流群。
B. 十大常见密码加密方式
一、密钥散列
采用MD5或者SHA1等散列算法,对明文进行加密。严格来说,MD5不算一种加密算法,而是一种摘要算法。无论多长的输入,MD5都会输出一个128位(16字节)的散列值。而SHA1也是流行的消息摘要算法,它可以生成一个被称为消息摘要的160位(20字节)散列值。MD5相对SHA1来说,安全性较低,但是速度快;SHA1和MD5相比安全性高,但是速度慢。
二、对称加密
采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密。对称加密算法中常用的算法有:DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK等。
三、非对称加密
非对称加密算法是一种密钥的保密方法,它需要两个密钥来进行加密和解密,这两个密钥是公开密钥和私有密钥。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。非对称加密算法有:RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)。
四、数字签名
数字签名(又称公钥数字签名)是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。它是一种类似写在纸上的普通的物理签名,但是在使用了公钥加密领域的技术来实现的,用于鉴别数字信息的方法。
五、直接明文保存
早期很多这样的做法,比如用户设置的密码是“123”,直接就将“123”保存到数据库中,这种是最简单的保存方式,也是最不安全的方式。但实际上不少互联网公司,都可能采取的是这种方式。
六、使用MD5、SHA1等单向HASH算法保护密码
使用这些算法后,无法通过计算还原出原始密码,而且实现比较简单,因此很多互联网公司都采用这种方式保存用户密码,曾经这种方式也是比较安全的方式,但随着彩虹表技术的兴起,可以建立彩虹表进行查表破解,目前这种方式已经很不安全了。
七、特殊的单向HASH算法
由于单向HASH算法在保护密码方面不再安全,于是有些公司在单向HASH算法基础上进行了加盐、多次HASH等扩展,这些方式可以在一定程度上增加破解难度,对于加了“固定盐”的HASH算法,需要保护“盐”不能泄露,这就会遇到“保护对称密钥”一样的问题,一旦“盐”泄露,根据“盐”重新建立彩虹表可以进行破解,对于多次HASH,也只是增加了破解的时间,并没有本质上的提升。
八、PBKDF2
该算法原理大致相当于在HASH算法基础上增加随机盐,并进行多次HASH运算,随机盐使得彩虹表的建表难度大幅增加,而多次HASH也使得建表和破解的难度都大幅增加。
九、BCrypt
BCrypt 在1999年就产生了,并且在对抗 GPU/ASIC 方面要优于 PBKDF2,但是我还是不建议你在新系统中使用它,因为它在离线破解的威胁模型分析中表现并不突出。
十、SCrypt
SCrypt 在如今是一个更好的选择:比 BCrypt设计得更好(尤其是关于内存方面)并且已经在该领域工作了 10 年。另一方面,它也被用于许多加密货币,并且我们有一些硬件(包括 FPGA 和 ASIC)能实现它。 尽管它们专门用于采矿,也可以将其重新用于破解。
C. 密码学系列之:bcrypt加密算法详解
简介今天要给大家介绍的一种加密算法叫做bcrypt,bcrypt是由NielsProvos和DavidMazières设计的密码哈希函数,他是基于Blowfish密码而来的,并于1999年在USENIX上提出。
除了加盐来抵御rainbowtable攻击之外,bcrypt的一个非常重要的特征就是自适应性,可以保证加密的速度在一个特定的范围内,即使计算机的运算能力非常高,可以通过增加迭代次数的方式,使得加密速度变慢,从而可以抵御暴力搜索攻击。
bcrypt函数是OpenBSD和其他系统包括一些Linux发行版(如SUSELinux)的默认密码哈希算法。
bcrypt的工作原理我们先回顾一下Blowfish的加密原理。blowfish首先需要生成用于加密使用的K数组和S-box,blowfish在生成最终的K数组和S-box需要耗费一定的时间,每个新的密钥都需要进行大概4KB文本的预处理,和其他分组密码算法相比,这个会很慢。但是一旦生成完毕,或者说密钥不变的情况下,blowfish还是很快速的一种分组加密方法。
那么慢有没有好处呢?
当然有,因为对于一个正常应用来说,是不会经常更换密钥的。所以预处理只会生成一次。在后面使用的时候就会很快了。
而对于恶意攻击者来说,每次尝试新的密钥都需要进行漫长的预处理,所以对攻击者来说要破解blowfish算法是非常不划算的。所以blowfish是可以抵御字典攻击的。
Provos和Mazières利用了这一点,并将其进一步发展。他们为Blowfish开发了一种新的密钥设置算法,将由此产生的密码称为"Eksblowfish"("expensivekeyscheleBlowfish")。这是对Blowfish的改进算法,在bcrypt的初始密钥设置中,salt和password都被用来设置子密钥。然后经过一轮轮的标准Blowfish算法,通过交替使用salt和password作为key,每一轮都依赖上一轮子密钥的状态。虽然从理论上来说,bcrypt算法的强度并不比blowfish更好,但是因为在bcrpyt中重置key的轮数是可以配置的,所以可以通过增加轮数来更好的抵御暴力攻击。
bcrypt算法实现简单点说bcrypt算法就是对字符串OrpheanBeholderScryDoubt进行64次blowfish加密得到的结果。有朋友会问了,bcrypt不是用来对密码进行加密的吗?怎么加密的是一个字符串?
别急,bcrpyt是将密码作为对该字符串加密的因子,同样也得到了加密的效果。我们看下bcrypt的基本算法实现:
FunctionbcryptInput:cost:Number(4..31)log2(Iterations).e.g.12==>212=4,096iterationssalt:arrayofBytes(16bytes)randomsaltpassword:arrayofBytes(1..72bytes)UTF-8encodedpasswordOutput:hash:arrayofBytes(24bytes)////P:arrayof18subkeys(UInt32[18])//S:Foursubstitutionboxes(S-boxes),S0...S3.EachS-boxis1,024bytes(UInt32[256])P,S<-EksBlowfishSetup(cost,salt,password)//Repeatedlyencryptthetext"OrpheanBeholderScryDoubt"64timesctext<-"OrpheanBeholderScryDoubt"//24bytes==>three64-bitblocksrepeat(64)ctext<-EncryptECB(P,S,ctext)////24-(cost,salt,ctext)上述函数bcrypt有3个输入和1个输出。
在输入部分,cost表示的是轮循的次数,这个我们可以自己指定,轮循次数多加密就慢。
salt是加密用盐,用来混淆密码使用。
password就是我们要加密的密码了。
最后的输出是加密后的结果hash。
有了3个输入,我们会调用EksBlowfishSetup函数去初始化18个subkeys和4个1K大小的S-boxes,从而达到最终的P和S。
然后使用P和S对"OrpheanBeholderScryDoubt"进行64次blowfish运算,最终得到结果。
接下来看下EksBlowfishSetup方法的算法实现:
FunctionEksBlowfishSetupInput:password:arrayofBytes(1..72bytes)UTF-8encodedpasswordsalt:arrayofBytes(16bytes)randomsaltcost:Number(4..31)log2(Iterations).e.g.12==>212=4,096iterationsOutput:P:arrayofUInt32arrayof18per-roundsubkeysS1..S4:;eachSBoxis256UInt32(i.e.1024KB)//InitializeP(Subkeys),andS(Substitutionboxes)withthehexdigitsofpiP,S<-InitialState()//,S<-ExpandKey(P,S,salt,password)//Thisisthe"Expensive"partofthe"ExpensiveKeySetup".//.repeat(2cost)P,S<-ExpandKey(P,S,0,password)P,S<-ExpandKey(P,S,0,salt)returnP,S代码很简单,EksBlowfishSetup接收上面我们的3个参数,返回最终的包含18个子key的P和4个1k大小的Sbox。
首先初始化,得到最初的P和S。
然后调用ExpandKey,传入salt和password,生成第一轮的P和S。
然后循环2的cost方次,轮流使用password和salt作为参数去生成P和S,最后返回。
最后看一下ExpandKey的实现:
FunctionExpandKeyInput:password:arrayofBytes(1..72bytes)UTF-8encodedpasswordsalt:Byte[16]randomsaltP:..S4:UInt32[1024]Four1KBSBoxesOutput:P:arrayofUInt32Arrayof18per-roundsubkeysS1..S4:UInt32[1024]Four1KBSBoxes//<-1to18doPn<-Pnxorpassword[32(n-1)..32n-1]//treatthepasswordascyclic//Treatthe128-bitsaltastwo64-bithalves(theBlowfishblocksize).saltHalf[0]<-salt[0..63]//Lower64-bitsofsaltsaltHalf[1]<-salt[64..127]//Upper64-bitsofsalt//Initializean8-byte(64-bit)bufferwithallzeros.block<-0//MixinternalstateintoP-boxesforn<-1to9do//xor64-bitblockwitha64-bitsalthalfblock<-blockxorsaltHalf[(n-1)mod2]//[0],andsaltHalf[1]//<-Encrypt(P,S,block)P2n<-block[0..31]//lower32-bitsofblockP2n+1<-block[32..63]//upper32-bitsblock//-boxesofstatefori<-1to4doforn<-0to127doblock<-Encrypt(state,blockxorsalt[64(n-1)..64n-1])//asaboveSi[2n]<-block[0..31]//lower32-bitsSi[2n+1]<-block[32..63]//upper32-bitsreturnstateExpandKey主要用来生成P和S,算法的生成比较复杂,大家感兴趣的可以详细研究一下。
bcrypthash的结构我们可以使用bcrypt来加密密码,最终以bcrypthash的形式保存到系统中,一个bcrypthash的格式如下:
$2b$[cost]$[22charactersalt][31characterhash]比如:
$2a$10$\__//\____________________/\_____________________________/AlgCostSaltHash上面例子中,$2a$表示的hash算法的唯一标志。这里表示的是bcrypt算法。
10表示的是代价因子,这里是2的10次方,也就是1024轮。
N9qo8uLOickgx2ZMRZoMye是16个字节(128bits)的salt经过base64编码得到的22长度的字符。
最后的是24个字节(192bits)的hash,经过bash64的编码得到的31长度的字符。
hash的历史这种hash格式是遵循的是OpenBSD密码文件中存储密码时使用的MolarCryptFormat格式。最开始的时候格式定义是下面的:
$1$:MD5-basedcrypt('md5crypt')
$2$:Blowfish-basedcrypt('bcrypt')
$sha1$:SHA-1-basedcrypt('sha1crypt')
$5$:SHA-256-basedcrypt('sha256crypt')
$6$:SHA-512-basedcrypt('sha512crypt')
但是最初的规范没有定义如何处理非ASCII字符,也没有定义如何处理null终止符。修订后的规范规定,在hash字符串时:
String必须是UTF-8编码
必须包含null终止符
因为包含了这些改动,所以bcrypt的版本号被修改成了$2a$。
但是在2011年6月,因为PHP对bcypt的实现crypt_blowfish中的一个bug,他们建议系统管理员更新他们现有的密码数据库,用$2x$代替$2a$,以表明这些哈希值是坏的(需要使用旧的算法)。他们还建议让crypt_blowfish对新算法生成的哈希值使用头$2y$。当然这个改动只限于PHP的crypt_blowfish。
然后在2014年2月,在OpenBSD的bcrypt实现中也发现了一个bug,他们将字符串的长度存储在无符号char中(即8位Byte)。如果密码的长度超过255个字符,就会溢出来。
因为bcrypt是为OpenBSD创建的。所以当他们的库中出现了一个bug时,他们决定将版本号升级到$2b$。
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:“程序那些事”,懂技术,更懂你!