[第十一週]資訊安全基礎 — 加密(Encryption)vs 雜湊(Hash function)

MiaHsu
5 min readSep 17, 2020

--

學習目標:了解什麼是加密(Encryption)、什麼是雜湊(Hash function)以及兩個的差別。

現有的網站在處理忘記密碼的功能時,通常會寄一封信到信箱,請使用者重新設定密碼,為什麼他們不直接把密碼寄給使用者就好了呢?

因為其實網站主也不知道使用者的密碼是什麼,密碼在資料庫中是不會以明文儲存,原因在於假設很不幸的資料庫被入侵,最重要的密碼也不會拿走或輕易的被猜出來。

不以明碼儲存的方式基本上有兩種:加密(Encryption)、雜湊(Hash function),以下說明兩者的基本原理

第一種方式:加密(Encryption)

  • 將明文資訊改變為難以讀取的密文,可透過「解密」還原出內容。
  • 加密跟解密都必須要透過金鑰(key)才能進行。
  • 為一對一之對應關係。
  • 缺點:只要知道金鑰(key),就可以還原出明文。
  • 又可以分為:對稱式、非對稱式兩種。

對稱式

  • 常見的加密演算法:DES, 3DES, AES
  • 也稱為秘密金鑰加密、發送者與接收者持有「相同的」金鑰來加解密訊息。
  • 只要傳遞金鑰的過程中(發送 request、response 中)被竊取資訊,再強的加密演算法都沒有用,因此產生出另一種安全性更高,應用範圍更廣的非對稱是加密。

非對稱式

  • 常見演算法: RSA, DSA, ECC
  • 每個使用者都擁有一對金鑰:一把公鑰用來加密訊息,一把私鑰用來解密。
  • 訊息由其中一把金鑰加密後,必需由另一把金鑰予以解密

小明擁有兩把鑰匙跟箱子,這兩把鑰匙,一把只能上鎖(私鑰)而另一把只能開鎖(公鑰),小明將私鑰保留給自己,將公鑰打了好多把分給班上的同學,並告訴大家:「各位同學這個是一把只能上鎖的鑰匙,所以如果有人有話想跟我說,可以把信放在箱子中上鎖」

你可能會好奇小明幹嘛這麼做?沒有什麼原因單純好玩。

隔天小明用私鑰打開箱子,很驚喜的箱子裡面真的有信!

….

從舉例中可以發現,由於至始至終能開啟箱子的私鑰都在小明手上,所以只有小明可以打開箱子,也確保了裡面的內容只有小明可以看到

相對於「對稱式」,「非對稱式」安全性更高。

上述的情況是 …私鑰「解密」、公鑰「加密」

假設把情況反過來… 私鑰「加密」、公鑰「解密」

就變成另一種有趣的用法

班上的每一位同學都提供了自己的公鑰,但只有小明的公鑰,才能解鎖小明的箱子,因此你可以公鑰對應上私鑰,就可以證明這個箱子是來自於哪一個同學 — — — 實際運用:數位簽章

但加密回歸到最基本就是…

明文 ➡️ 加密(key)➡️ 變成密文
密文 ➡️ 解密(key)➡️ 變成明文

密文(歷史本文) ➡️ 解密(羅賓)➡️ 明文 🌝

雜湊(Hash function)

  • 把明文丟進一串公式後變成秘文
  • 無論內容長短,透過雜湊演算法後都會輸出固定長度的值。
  • 當不同的內容卻輸出一樣的值時,這個情況稱為「碰撞」,但好的雜湊演算法,產生碰撞的機率是很低的。
  • 由於無法「逆向解出明文」,因此安全性相較於加密更高,也是跟加密最大的區別。
  • 常見演算法:SHA 系列、BLAKE2

PHP 內建雜湊函式

(PHP 5 >= 5.5.0, PHP 7)

password_hash()

  • 可以簡單實踐複雜的秘文
  • 語法:password_hash('password', PASSWORD_DEFAULT)
    第一個參數:原始 password
    第二個參數:演算法,建議可以直接使用 PASSWORD_DEFAULT,每次處理時,都會在背後產生隨機的SALT。
  • 舉例:將經過處理的密碼存在變數中
$password = password_hash($_POST[‘password’], PASSWORD_DEFAULT);

password_verify()

  • 將經過 password_hash() 處理的密碼,進行驗證,白話就是檢查輸入密碼對不對,用於登入功能
  • 語法:password_verify('使用者輸入的密碼','資料庫裡的密碼')
    根據回傳 boolean 值,進行操作
  • 舉例:檢查輸入的密碼是否是否存在相對應的資料中,如果有就登入導回首頁,否則導回登入頁
$password = '123456' // 原始密碼if(password_verify($password, $row['password'])) {    $_SESSION['username'] = $username;} else {    header('Location: login.php?error=2');    die();}header('Location: index.php');

以上有任何錯誤的地方歡迎指正,感謝。

--

--