偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

安全的加密算法 Bcrypt,再也不用擔(dān)心數(shù)據(jù)泄密了

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

哈希(Hash)與加密(Encrypt)

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

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

HASH 算法是一種消息摘要算法,不是一種加密算法,但由于其單向運(yùn)算,具有一定的不可逆性,成為加密算法中的一個(gè)構(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為字符串的長(zhǎng)度。

HashMap的hash計(jì)算時(shí)先計(jì)算hashCode(),然后進(jìn)行二次hash。代碼如下:

// 計(jì)算二次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)過這些移位操作后,對(duì)于同一個(gè)值使用同一個(gè)算法,計(jì)算出來的hash值一定是相同的。

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

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

在計(jì)算過程中原文的部分信息是丟失了。一個(gè)MD5理論上是可以對(duì)應(yīng)多個(gè)原文的,因?yàn)镸D5是有限多個(gè)而原文是無限多個(gè)的。

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

因?yàn)閔ash算法是固定的,所以同一個(gè)字符串計(jì)算出來的hash串是固定的,所以,可以采用如下的方式進(jìn)行破解。

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

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

如何防御彩虹表的破解?

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

一個(gè)網(wǎng)站,如果加密算法和鹽都泄露了,那針對(duì)性攻擊依然是非常不安全的。因?yàn)橥粋€(gè)加密算法同一個(gè)鹽加密后的字符串仍然還是一毛一樣滴!

一個(gè)更難破解的加密算法Bcrypt

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

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

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

對(duì)一個(gè)密碼,Bcrypt每次生成的hash都不一樣,那么它是如何進(jìn)行校驗(yàn)的?

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

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

@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}

生成的加密字符串格式如下:

$2b$[cost]$[22 character salt][31 character hash]

比如:

$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
\__/\/ \____________________/\_____________________________/
Alg Cost Salt Hash

上面例子中,$2a$ 表示的hash算法的唯一標(biāo)志。這里表示的是Bcrypt算法。

10 ?表示的是代價(jià)因子,這里是2的10次方,也就是1024輪。

N9qo8uLOickgx2ZMRZoMye ?是16個(gè)字節(jié)(128bits)的salt經(jīng)過base64編碼得到的22長(zhǎng)度的字符。

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

PasswordEncoder 接口

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

public interface PasswordEncoder {
String encode(CharSequence rawPassword);

boolean matches(CharSequence rawPassword, String encodedPassword);

default boolean upgradeEncoding(String encodedPassword) {
return false;
}
}

這個(gè)接口有三個(gè)方法:

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

例如,我們可以通過如下示例代碼在進(jìn)行用戶注冊(cè)的時(shí)候加密存儲(chǔ)用戶密碼

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

BCryptPasswordEncoder 是Spring Security推薦使用的PasswordEncoder接口實(shí)現(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 + ":" //密碼校驗(yàn):true
+ passwordEncoder.matches(rawPassword, encodedPassword));

System.out.println("654321是否匹配" + encodedPassword + ":" //定義一個(gè)錯(cuò)誤的密碼進(jìn)行校驗(yàn):false
+ passwordEncoder.matches("654321", encodedPassword));
}
}

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

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

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

責(zé)任編輯:武曉燕 來源: 碼猿技術(shù)專欄
相關(guān)推薦

2015-05-29 09:01:48

2021-12-21 09:05:46

命令Linux敲錯(cuò)

2020-06-15 08:03:17

大文件OOM內(nèi)存

2021-08-13 22:38:36

大數(shù)據(jù)互聯(lián)網(wǎng)技術(shù)

2021-06-04 12:05:03

Redis Bitmap 數(shù)據(jù)庫

2021-06-08 07:48:26

數(shù)據(jù) Python開發(fā)

2019-09-04 10:00:07

手機(jī)人臉識(shí)別

2015-10-22 10:38:43

Wi-Fi燃?xì)鈭?bào)警器

2020-04-30 09:01:27

路由器安全網(wǎng)絡(luò)安全路由器

2021-06-11 07:14:04

QQ音樂微信翻譯

2018-09-19 05:01:01

2016-08-09 16:17:37

高德地圖TFBOYS大數(shù)據(jù)

2024-04-29 12:13:43

2020-04-10 09:55:28

Git 工具黑魔法

2023-11-27 17:11:02

數(shù)據(jù)庫oracle

2024-04-15 00:08:00

MySQLInnoDB數(shù)據(jù)庫

2023-07-29 22:02:06

MyBatis數(shù)據(jù)庫配置

2024-01-26 07:00:11

Python工具無向圖

2018-10-11 15:51:32

ChromeGoogle瀏覽器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)