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$。
最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程序那些事」,懂技術,更懂你!