tft每日頭條

 > 圖文

 > 哪種哈希算法保證數據完整性

哪種哈希算法保證數據完整性

圖文 更新时间:2024-07-05 12:31:00
前言

在很多網站的早期,甚至是現在仍然有一些網站,當你點擊忘記密碼功能時,你的郵箱會收到一封郵件,然後裡面赫然寫着你的密碼,很多普通用戶還會覺得慶幸,總算是找回來了,殊不知,這是多麼可怕地一件事,說明了網站是“幾乎是”明文存儲你的密碼,一旦數據用戶數據洩露或者被拖庫,那麼用戶密碼将赤裸裸的暴露了,想想之前幾次互聯網密碼洩露事件。

那麼如何解決呢?

加密

為了不讓密碼明文存儲,我們需要對密碼進行加密,這樣即使數據庫用戶密碼暴露,也是加密後的。但是如何讓加密後的數據難以解密呢?我們現在比較流行的做法就是把密碼進行Hash存儲。

Hash

哈希算法将任意長度的二進制值映射為較短的固定長度的二進制值,這個小的二進制值稱為哈希值。哈希值是一段數據唯一且極其緊湊的數值表示形式. 典型的哈希算法包括 MD2、MD4、MD5 和 SHA-1

Hash算法是給消息生成摘要,那麼什麼是摘要呢?

舉個例子:

比如你給你女朋友寫了一封郵件,确保沒被人改過,你可以生成這樣一份摘要 “第50個字是我,第100個字是愛, 第998個字是你”,那麼你女朋友收到這個摘要,檢查一下你的郵件就可以了。

Hash算法有兩個非常主要的特征:

  • 不能通過摘要來反推出原文
  • 原文的非常細小的改動,都會引起Hash結果的非常大的變化

因此,這個比較适合用來保存用戶密碼,因為不能反推出用戶密碼,Hash結果一緻就證明原文一緻,我們來用Ruby代碼試一下上面的第二點 (MD5是一種常用的Hash算法)

2.2.3 :003 > require 'digest/md5.so' => true 2.2.3 :004 > puts Digest::MD5.hexdigest('I love you') e4f58a805a6e1fd0f6bef58c86f9ceb3 => nil 2.2.3 :005 > puts Digest::MD5.hexdigest('I love you!') 690a8cda8894e37a6fff4d1790d53b33 => nil 2.2.3 :006 > puts Digest::MD5.hexdigest('I love you !') b2c63c3ca6019cff3bad64fcfa807361 => nil 2.2.3 :007 > puts Digest::MD5.hexdigest('I love you') e4f58a805a6e1fd0f6bef58c86f9ceb3 => nil 2.2.3 :008 >

那麼我們在使用MD5保存密碼時候的驗證流程是什麼呢?

  • 用戶注冊時,把用戶密碼是MD5(password)後保存到數據庫。
  • 用戶輸入用戶名和密碼
  • 服務器從數據庫查找用戶名
  • 如果有這個用戶,A=MD5(input password), B=Database password
  • 如果A==B, 那麼說明用戶密碼輸入正确,如果不相等,用戶輸入錯誤。
為什麼Hash(MD5)後仍然不夠安全?窮舉

但是,如果你認為就隻是這樣密碼就不會被人知道,那麼就不對了,這隻是比明文更安全,為什麼?

因為,大部分人的密碼都非常簡單,當拿到MD5的密碼後,攻擊者也可以通過比對的方式,比如你的密碼是4218

2.2.3 :008 > puts Digest::MD5.hexdigest('4218') d278df4919453195d221030324127a0e

那麼攻擊者可以把1到4218個數字都MD5一下,然後和你密碼的MD5對比一下,就知道你原密碼是什麼了。

曾經我的密碼箱密碼忘了,我把鎖給撬了,後來我才想起可以用窮舉法,最多就999次不就打開了?那麼問題來了,你的密碼箱還安全嗎?

彩虹表

除了窮舉法外,由于之前的密碼洩露,那麼攻擊者們,手上都有大量的彩虹表,比如"I love you",生日等等,這個表保存了這些原值以及MD5後的值,那麼使用時直接從已有庫裡就可以查出來對應的密碼。

加鹽 Salt

那麼,由于簡單的對密碼進行Hash算法不夠安全,那麼我們就可以對密碼加Salt,比如密碼是"I love you", 雖然彩虹表裡有這條數據,但是如果加上"安紅我愛你",這樣MD5結果就大不一樣.

jacks-MacBook-Air:~ jack$ irb 2.2.3 :001 > require 'digest/md5.so' => true 2.2.3 :002 > puts Digest::MD5.hexdigest('I love you') e4f58a805a6e1fd0f6bef58c86f9ceb3 => nil 2.2.3 :003 > puts Digest::MD5.hexdigest('I love you安紅我愛你') b10d890bf46b1a045eb99af5d43c7b13 => nil 2.2.3 :004 > puts Digest::MD5.hexdigest('I dont love you') c82294c9a7b6e4a372ad25ed4d6011c9 => nil 2.2.3 :005 > puts Digest::MD5.hexdigest('I dont love you安紅我愛你') dce67bcdfdf007445dd4a2c2dc3d29c1 => nil 2.2.3 :006 >

如此一來,因為攻擊者很難猜到“安紅我愛你”,那麼自然彩虹表裡是沒有的,當然我建議你在實際項目中不要使用"安紅我愛你",你應該使用一個連你自己都猜不到的較長的字符串。

加鹽了,就安全了嗎?

實際上,加鹽并不能100%保證安全,假如有人洩露了你的Salt呢?實際上通過反編譯程序很容易可以拿到這個,由于WEB程序一般放在WEB服務器上,那麼就需要保證服務器不被攻擊,當然這個是運維人員去操心。

為了讓加鹽更安全,一般情況下我們可以使用一個“鹽 鹽”,也就是為每個用戶保存一個"Salt", 然後再使用全局的鹽,我們可以對用戶的鹽使用自己的加密算法。那麼代碼就如下:

if MD5(userInputPpassword globalsalt usersalt)===user.databasePassword) { login success }

普通用戶如何做?

由于這個是寫給程序員,當然是說在前端用戶注冊時密碼應該如何設置,很簡單,我們要求用戶必須輸入強密碼!但是,我知道很多用戶覺得很煩,這樣你就失掉了一個用戶,但我們需要做一個适當的折中,比如至少有一個大寫字母,小寫字母和數字的組合。

最後

我們來看看解決了之前文章下面例子的什麼問題。

假如,明明和麗麗相互不認識,明明想給麗麗寫一封情書,讓隔壁老王送去

  1. 如何保證隔壁老王不能看到情書的内容?(保密性)
  2. 如何保證隔壁老王不修改情書的内容?(完整性)
  3. 如何保證隔壁老王不冒充明明?(身份認證)
  4. 如何保證明明不能否認情書是自己寫的?(來源的不可否認)

哪種哈希算法保證數據完整性(如何安全保存用戶密碼及哈希算法)1

通過了解hash算法,"明明" 就有辦法讓麗麗知道信的内容沒有修改,他可以對郵件進行Hash生成郵件的摘要,然後讓"隔壁的李叔叔"把摘要送給麗麗,麗麗拿到郵件的摘要後,把郵件内容也Hash一下,然後把結果和"隔壁的李叔叔"給的摘要對比一下,然後通過比較結果就知道郵件有沒有被"隔壁的王叔叔"更改過了。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关圖文资讯推荐

热门圖文资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved