<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
這是《Spring Security 進階》專欄的第三篇文章,給大家介紹一下Spring Security 中內建的加密演演算法BCrypt
,號稱最安全的加密演演算法,究竟有著什麼魔力能讓駭客聞風喪膽
雜湊(Hash)是將目標文字轉換成具有相同長度的、不可逆的雜湊字串(或叫做訊息摘要),而加密(Encrypt)是將目標文字轉換成具有不同長度的、可逆的密文。
HASH 演演算法是一種訊息摘要演演算法,不是一種加密演演算法,但由於其單向運算,具有一定的不可逆性,成為加密演演算法中的一個構成部分。
JDK的String的Hash演演算法。程式碼如下:
public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
從JDK的API可以看出,它的演演算法等式就是
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
其中s[i]
就是索引為i的字元,n為字串的長度。
HashMap的hash計算時先計算hashCode()
,然後進行二次hash。程式碼如下:
// 計算二次Hash int hash = hash(key.hashCode()); static int hash(int h) { h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); }
可以發現,雖然演演算法不同,但經過這些移位元運算後,對於同一個值使用同一個演演算法,計算出來的hash值一定是相同的。
那麼,hash為什麼是不可逆的呢?
假如有兩個密碼3和4,我的加密演演算法很簡單就是3+4
,結果是7,但是通過7我不可能確定那兩個密碼是3和4,有很多種組合,這就是最簡單的不可逆,所以只能通過暴力破解一個一個的試。
在計算過程中原文的部分資訊是丟失了。一個MD5
理論上是可以對應多個原文的,因為MD5是有限多個而原文是無限多個的。
因為hash演演算法是固定的,所以同一個字串計算出來的hash串是固定的,所以,可以採用如下的方式進行破解。
對於單機來說,暴力列舉法的時間成本很高(以14位元字母和數位的組合密碼為例,共有1.24×10^25種可能,即使電腦每秒鐘能進行10億次運算,也需要4億年才能破解),字典法的空間成本很高(仍以14位元字母和數位的組合密碼為例,生成的密碼32位元雜湊串的對照表將佔用5.7×10^14 TB的儲存空間)。但是利用分散式計算和分散式儲存,仍然可以有效破解MD5演演算法。因此這兩種方法同樣被駭客們廣泛使用。
雖然彩虹表有著如此驚人的破解效率,但網站的安全人員仍然有辦法防禦彩虹表。最有效的方法就是“加鹽”,即在密碼的特定位置插入特定的字串,這個特定字串就是“鹽(Salt)”,加鹽後的密碼經過雜湊加密得到的雜湊串與加鹽前的雜湊串完全不同,駭客用彩虹表得到的密碼根本就不是真正的密碼。即使駭客知道了“鹽”的內容、加鹽的位置,還需要對H函數和R函數進行修改,彩虹表也需要重新生成,因此加鹽能大大增加利用彩虹表攻擊的難度。
一個網站,如果加密演演算法和鹽都洩露了,那針對性攻擊依然是非常不安全的。因為同一個加密演演算法同一個鹽加密後的字串仍然還是一毛一樣滴!
BCrypt
是由Niels Provos和David Mazières設計的密碼雜湊函數,他是基於Blowfish密碼而來的,並於1999年在USENIX上提出。
除了加鹽來抵禦rainbow table 攻擊之外,bcrypt的一個非常重要的特徵就是自適應性,可以保證加密的速度在一個特定的範圍內,即使計算機的運算能力非常高,可以通過增加迭代次數的方式,使得加密速度變慢,從而可以抵禦暴力搜尋攻擊。
Bcrypt
可以簡單理解為它內部自己實現了隨機加鹽處理。使用Bcrypt,每次加密後的密文是不一樣的。
對一個密碼,Bcrypt每次生成的hash都不一樣,那麼它是如何進行校驗的?
在Spring Security 中 內建了Bcrypt加密演演算法,構建也很簡單,程式碼如下:
@Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); }
生成的加密字串格式如下:
$2b$[cost]$[22 character salt][31 character hash]
比如:
$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy __// ____________________/_____________________________/ Alg Cost Salt Hash
上面例子中,$2a$
表示的hash演演算法的唯一標誌。這裡表示的是Bcrypt演演算法。
10
表示的是代價因子,這裡是2的10次方,也就是1024
輪。
N9qo8uLOickgx2ZMRZoMye
是16個位元組(128bits)的salt
經過base64編碼得到的22長度的字元。
最後的IjZAgcfl7p92ldGxad68LJZdL17lhWy
是24個位元組(192bits)的hash
,經過bash64的編碼得到的31長度的字元。
這個介面是Spring Security 內建的,如下:
public interface PasswordEncoder { String encode(CharSequence rawPassword); boolean matches(CharSequence rawPassword, String encodedPassword); default boolean upgradeEncoding(String encodedPassword) { return false; } }
這個介面有三個方法:
encode
方法接受的引數是原始密碼字串,返回值是經過加密之後的hash值,hash值是不能被逆向解密的。這個方法通常在為系統新增使用者,或者使用者註冊的時候使用。matches
方法是用來校驗使用者輸入密碼rawPassword,和加密後的hash值encodedPassword是否匹配。如果能夠匹配返回true,表示使用者輸入的密碼rawPassword是正確的,反之返回fasle。也就是說雖然這個hash值不能被逆向解密,但是可以判斷是否和原始密碼匹配。這個方法通常在使用者登入的時候進行使用者輸入密碼的正確性校驗。upgradeEncoding
設計的用意是,判斷當前的密碼是否需要升級。也就是是否需要重新加密?需要的話返回true,不需要的話返回fasle。預設實現是返回false。例如,我們可以通過如下範例程式碼在進行使用者註冊的時候加密儲存使用者密碼
//將User儲存到資料庫表,該表包含password列 user.setPassword(passwordEncoder.encode(user.getPassword()));
BCryptPasswordEncoder
是Spring Security推薦使用的PasswordEncoder介面實現類
public class PasswordEncoderTest { @Test void bCryptPasswordTest(){ PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); String rawPassword = "123456"; //原始密碼 String encodedPassword = passwordEncoder.encode(rawPassword); //加密後的密碼 System.out.println("原始密碼" + rawPassword); System.out.println("加密之後的hash密碼:" + encodedPassword); System.out.println(rawPassword + "是否匹配" + encodedPassword + ":" //密碼校驗:true + passwordEncoder.matches(rawPassword, encodedPassword)); System.out.println("654321是否匹配" + encodedPassword + ":" //定義一個錯誤的密碼進行校驗:false + passwordEncoder.matches("654321", encodedPassword)); } }
上面的測試用例執行的結果是下面這樣的。(注意:對於同一個原始密碼,每次加密之後的hash密碼都是不一樣的,這正是BCryptPasswordEncoder的強大之處,它不僅不能被破解,想通過常用密碼對照表進行大海撈針你都無從下手),輸出如下:
原始密碼123456
加密之後的hash密碼:$2a$10$zt6dUMTjNSyzINTGyiAgluna3mPm7qdgl26vj4tFpsFO6WlK5lXNm
123456是否匹配$2a$10$zt6dUMTjNSyzINTGyiAgluna3mPm7qdgl26vj4tFpsFO6WlK5lXNm:true
654321是否匹配$2a$10$zt6dUMTjNSyzINTGyiAgluna3mPm7qdgl26vj4tFpsFO6WlK5lXNm:false
BCrypt
產生隨機鹽(鹽的作用就是每次做出來的菜味道都不一樣)。這一點很重要,因為這意味著每次encode將產生不同的結果。
以上就是最安全的加密演演算法Bcrypt防止資料洩露詳解的詳細內容,更多關於Bcrypt 加密演演算法的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45