最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

最安全的加密算法Bcrypt防止數(shù)據(jù)泄露詳解

 更新時間:2022年09月14日 15:08:50   作者:碼猿技術(shù)專欄  
這篇文章主要為大家介紹了最安全的加密算法Bcrypt防止數(shù)據(jù)泄露詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

引言

這是《Spring Security 進階》專欄的第三篇文章,給大家介紹一下Spring Security 中內(nèi)置的加密算法BCrypt,號稱最安全的加密算法,究竟有著什么魔力能讓黑客聞風喪膽

哈希(Hash)與加密(Encrypt)

哈希(Hash)是將目標文本轉(zhuǎn)換成具有相同長度的、不可逆的雜湊字符串(或叫做消息摘要),而加密(Encrypt)是將目標文本轉(zhuǎn)換成具有不同長度的、可逆的密文。

  • 哈希算法往往被設(shè)計成生成具有相同長度的文本,而加密算法生成的文本長度與明文本身的長度有關(guān)。
  • 哈希算法是不可逆的,而加密算法是可逆的。

HASH 算法是一種消息摘要算法,不是一種加密算法,但由于其單向運算,具有一定的不可逆性,成為加密算法中的一個構(gòu)成部分。

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);
}

可以發(fā)現(xiàn),雖然算法不同,但經(jīng)過這些移位操作后,對于同一個值使用同一個算法,計算出來的hash值一定是相同的。

那么,hash為什么是不可逆的呢?

假如有兩個密碼3和4,我的加密算法很簡單就是3+4,結(jié)果是7,但是通過7我不可能確定那兩個密碼是3和4,有很多種組合,這就是最簡單的不可逆,所以只能通過暴力破解一個一個的試。

在計算過程中原文的部分信息是丟失了。一個MD5理論上是可以對應(yīng)多個原文的,因為MD5是有限多個而原文是無限多個的。

不可逆的MD5為什么是不安全的?

因為hash算法是固定的,所以同一個字符串計算出來的hash串是固定的,所以,可以采用如下的方式進行破解。

  • 暴力枚舉法:簡單粗暴地枚舉出所有原文,并計算出它們的哈希值,看看哪個哈希值和給定的信息摘要一致。
  • 字典法:黑客利用一個巨大的字典,存儲盡可能多的原文和對應(yīng)的哈希值。每次用給定的信息摘要查找字典,即可快速找到碰撞的結(jié)果。
  • 彩虹表(rainbow)法:在字典法的基礎(chǔ)上改進,以時間換空間。是現(xiàn)在破解哈希常用的辦法。

對于單機來說,暴力枚舉法的時間成本很高(以14位字母和數(shù)字的組合密碼為例,共有1.24×10^25種可能,即使電腦每秒鐘能進行10億次運算,也需要4億年才能破解),字典法的空間成本很高(仍以14位字母和數(shù)字的組合密碼為例,生成的密碼32位哈希串的對照表將占用5.7×10^14 TB的存儲空間)。但是利用分布式計算和分布式存儲,仍然可以有效破解MD5算法。因此這兩種方法同樣被黑客們廣泛使用。

如何防御彩虹表的破解?

雖然彩虹表有著如此驚人的破解效率,但網(wǎng)站的安全人員仍然有辦法防御彩虹表。最有效的方法就是“加鹽”,即在密碼的特定位置插入特定的字符串,這個特定字符串就是“鹽(Salt)”,加鹽后的密碼經(jīng)過哈希加密得到的哈希串與加鹽前的哈希串完全不同,黑客用彩虹表得到的密碼根本就不是真正的密碼。即使黑客知道了“鹽”的內(nèi)容、加鹽的位置,還需要對H函數(shù)和R函數(shù)進行修改,彩虹表也需要重新生成,因此加鹽能大大增加利用彩虹表攻擊的難度。

一個網(wǎng)站,如果加密算法和鹽都泄露了,那針對性攻擊依然是非常不安全的。因為同一個加密算法同一個鹽加密后的字符串仍然還是一毛一樣滴!

一個更難破解的加密算法Bcrypt

BCrypt是由Niels Provos和David Mazières設(shè)計的密碼哈希函數(shù),他是基于Blowfish密碼而來的,并于1999年在USENIX上提出。

除了加鹽來抵御rainbow table 攻擊之外,bcrypt的一個非常重要的特征就是自適應(yīng)性,可以保證加密的速度在一個特定的范圍內(nèi),即使計算機的運算能力非常高,可以通過增加迭代次數(shù)的方式,使得加密速度變慢,從而可以抵御暴力搜索攻擊。

Bcrypt可以簡單理解為它內(nèi)部自己實現(xiàn)了隨機加鹽處理。使用Bcrypt,每次加密后的密文是不一樣的。

對一個密碼,Bcrypt每次生成的hash都不一樣,那么它是如何進行校驗的?

  • 雖然對同一個密碼,每次生成的hash不一樣,但是hash中包含了salt(hash產(chǎn)生過程:先隨機生成salt,salt跟password進行hash);
  • 在下次校驗時,從hash中取出salt,salt跟password進行hash;得到的結(jié)果跟保存在DB中的hash進行比對。

在Spring Security 中 內(nèi)置了Bcrypt加密算法,構(gòu)建也很簡單,代碼如下:

@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個字節(jié)(128bits)的salt經(jīng)過base64編碼得到的22長度的字符。

最后的IjZAgcfl7p92ldGxad68LJZdL17lhWy是24個字節(jié)(192bits)的hash,經(jīng)過bash64的編碼得到的31長度的字符。

PasswordEncoder 接口

這個接口是Spring Security 內(nèi)置的,如下:

public interface PasswordEncoder {
   String encode(CharSequence rawPassword);
   boolean matches(CharSequence rawPassword, String encodedPassword);
   default boolean upgradeEncoding(String encodedPassword) {
      return false;
   }
}

這個接口有三個方法:

  • encode方法接受的參數(shù)是原始密碼字符串,返回值是經(jīng)過加密之后的hash值,hash值是不能被逆向解密的。這個方法通常在為系統(tǒng)添加用戶,或者用戶注冊的時候使用。
  • matches方法是用來校驗用戶輸入密碼rawPassword,和加密后的hash值encodedPassword是否匹配。如果能夠匹配返回true,表示用戶輸入的密碼rawPassword是正確的,反之返回fasle。也就是說雖然這個hash值不能被逆向解密,但是可以判斷是否和原始密碼匹配。這個方法通常在用戶登錄的時候進行用戶輸入密碼的正確性校驗。
  • upgradeEncoding設(shè)計的用意是,判斷當前的密碼是否需要升級。也就是是否需要重新加密?需要的話返回true,不需要的話返回fasle。默認實現(xiàn)是返回false。

例如,我們可以通過如下示例代碼在進行用戶注冊的時候加密存儲用戶密碼

//將User保存到數(shù)據(jù)庫表,該表包含password列
user.setPassword(passwordEncoder.encode(user.getPassword()));

BCryptPasswordEncoder 是Spring Security推薦使用的PasswordEncoder接口實現(xiàn)類

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));
  }
}

上面的測試用例執(zhí)行的結(jié)果是下面這樣的。(注意:對于同一個原始密碼,每次加密之后的hash密碼都是不一樣的,這正是BCryptPasswordEncoder的強大之處,它不僅不能被破解,想通過常用密碼對照表進行大海撈針你都無從下手),輸出如下:

原始密碼123456
加密之后的hash密碼:$2a$10$zt6dUMTjNSyzINTGyiAgluna3mPm7qdgl26vj4tFpsFO6WlK5lXNm
123456是否匹配$2a$10$zt6dUMTjNSyzINTGyiAgluna3mPm7qdgl26vj4tFpsFO6WlK5lXNm:true
654321是否匹配$2a$10$zt6dUMTjNSyzINTGyiAgluna3mPm7qdgl26vj4tFpsFO6WlK5lXNm:false

BCrypt 產(chǎn)生隨機鹽(鹽的作用就是每次做出來的菜味道都不一樣)。這一點很重要,因為這意味著每次encode將產(chǎn)生不同的結(jié)果。

以上就是最安全的加密算法Bcrypt防止數(shù)據(jù)泄露詳解的詳細內(nèi)容,更多關(guān)于Bcrypt 加密算法的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot使用AOP統(tǒng)一日志管理的方法詳解

    SpringBoot使用AOP統(tǒng)一日志管理的方法詳解

    這篇文章主要為大家分享一個干貨:超簡潔SpringBoot使用AOP統(tǒng)一日志管理,文中的示例代碼講解詳細,感興趣的小伙伴快跟隨小編一起學習學習吧
    2022-05-05
  • Java Spring登錄練習詳解

    Java Spring登錄練習詳解

    這篇文章主要介紹了Java編程實現(xiàn)spring簡單登錄的練習,具有一定參考價值,需要的朋友可以了解下,希望能夠給你帶來幫助
    2021-10-10
  • jetty運行時無法保存文件的解決方法

    jetty運行時無法保存文件的解決方法

    這篇文章主要為大家詳細介紹了jetty運行時無法保存文件的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • 淺析Java 9 Optional API 新增方法

    淺析Java 9 Optional API 新增方法

    本文我們介紹了Java 9 Optional Api新增的三個方法。or方法在Optional為空時返回Optional對象。 ifPresentOrElse()在值存在時執(zhí)行Consumer參數(shù),反之執(zhí)行另一個參數(shù)回調(diào)參數(shù)。感興趣的朋友跟隨小編一起看看吧
    2019-12-12
  • SpringBoot中整合消息服務(wù)組件的方法

    SpringBoot中整合消息服務(wù)組件的方法

    本文介紹了消息服務(wù)組件的基本概念,以及如何在SpringBoot中整合常見的消息服務(wù)組件,如ActiveMQ、RabbitMQ和Kafka,我們探討整合消息服務(wù)組件在實際應(yīng)用場景中的優(yōu)勢,感興趣的朋友跟隨小編一起看看吧
    2023-07-07
  • 啟動springboot項目時報錯:無法訪問org.springframework.web.bind.annotation.GetMapping …具有錯誤的版本 61.0,應(yīng)為52.0?的解決方案

    啟動springboot項目時報錯:無法訪問org.springframework.web.bind.annotatio

    這篇文章給大家分享了啟動springboot項目時報錯:?無法訪問org.springframework.web.bind.annotation.GetMapping …具有錯誤的版本 61.0,應(yīng)為52.0?的解決方案,文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2023-10-10
  • Java中equals()方法實例詳解

    Java中equals()方法實例詳解

    equals方法是java.lang.Object類的方法,下面這篇文章主要給大家介紹了關(guān)于Java中equals()方法的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-12-12
  • java ClassLoader機制詳細講解

    java ClassLoader機制詳細講解

    ClassLoader一個經(jīng)常出現(xiàn)又讓很多人望而卻步的詞,本文將試圖以最淺顯易懂的方式來講解 ClassLoader,希望能對不了解該機制的朋友起到一點點作用
    2016-07-07
  • json-lib將json格式的字符串,轉(zhuǎn)化為java對象的實例

    json-lib將json格式的字符串,轉(zhuǎn)化為java對象的實例

    下面小編就為大家?guī)硪黄猨son-lib將json格式的字符串,轉(zhuǎn)化為java對象的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • 淺析Java中的 new 關(guān)鍵字

    淺析Java中的 new 關(guān)鍵字

    java中的new關(guān)鍵字是實例化對象,接下來本文通過一個案例給大家講解Java中的 new 關(guān)鍵字,感興趣的朋友可以參考下
    2016-08-08

最新評論

湖南省| 赣榆县| 平利县| 博湖县| 鲁甸县| 清流县| 宁晋县| 剑河县| 禄丰县| 敖汉旗| 浑源县| 金华市| 铜川市| 台南县| 新昌县| 杂多县| 姚安县| 新化县| 达州市| 霍山县| 绍兴市| 峨眉山市| 巴楚县| 寻乌县| 南靖县| 和静县| 五莲县| 墨玉县| 莱阳市| 普安县| 亳州市| 铜梁县| 怀化市| 若尔盖县| 外汇| 通许县| 东平县| 云林县| 株洲市| 太康县| 河东区|