向普通人加密 用PHP程式保護資料

來源:互聯網
上載者:User

在這個日漸虛擬互連網世界中,您必須小心保護自已的資料。本文將介紹編碼和加密一些重要訊息(比如密碼、信用卡號、甚至整個訊息)的基礎知識。並通過使用 PHP 的內建功能,瞭解加密和解密資訊的意義,並且將瞭解一些涉及密碼和其他資料的實際樣本。
瞭解當今現實世界與 20 年前的現實世界的不同。在 20 世紀 80 年代,加密是一種特工人員的行為 —— 是您在 Tom Clancy 的偵探小說中才可以讀到的情節。如果某人想保持少量私人資訊,那麼他必須使用密碼、密碼短語或其他基本方法對資料進行加密。

而現在,加密遍布各個領域。密碼也被加密儲存在資料庫中。電腦空間中的加密的通道可能是通過 SSL、SSH 和其他技術加密的 —— 更不必說擬虛專用網路。人們平常可以而且一定能夠使用 Pretty Good Privacy (PGP) 來保護敏感的檔案和電子郵件。

作為一名 PHP 開發人員,您應該知道,強有力的安全做法並不是只將安全保護用於獨特的應用程式 —— 還可以將其用於您當前從事的項目。使用者要樹立從一般加密方法(例如,在登入頁上的密碼欄位中不顯示明文)過渡到各種進階加密方法(如 DES、MD5、SHA1 和 Blowfish)的意識。

因時間和篇幅所限,這裡無法討論加密的各個方面,但是您將從這裡瞭解涵蓋適用於您的多數情況的基本內容。我們通過使用 PHP 內建功能先瞭解加密和解密資訊的意義,進而瞭解涉及密碼和其他資料的一些實際樣本。在本文中,加密是在更大的安全上下文中進行討論的。最後,將介紹其他 PHP 擴充和外掛程式。

加密技術的初級讀本

作為希臘的詞根資產,加密技術是一種 “神秘編寫” 藝術。凱撒密碼 是最古老的一種密碼,形式也最為簡單。它採用明文訊息,將字母移動 n 個位置,從而產生暗文。例如:

明文:Veni Vidi Vici
暗文:Xgpk Xkfk Xkek
通過檢查暗文並藉助一些啟發學習法的技巧,您可以知道,明文實際上是移動了兩個字元。凱撒密碼很容易破解。例如:檢查上述資訊,可知 X 重複了多次,且 k 也是如此。這就變成猜迷,確定多少個四字母的詞有那樣多的母音。知道了這些帶母音的詞後,您就知道了移動其餘字的方法。它還可以協助您判斷明文是否為拉丁文,讓您對其有大致的瞭解。

現代加密技術的功能非常強大,使用了超越統一移動字母和符號的演算法。本文不打算詳細介紹這些演算法,僅介紹一些 PHP 安裝,它包括您需要適度(或特別)保持資料安全的所有內容。

不存在 100% 不受攻擊的絕對完整的加密方法。大概每隔一個月,一些駭客及其朋友就會集合 1,000 台電腦,在最初的幾天裡強力進行計算破壞,從而使最新的加密方法崩潰。不過,您可以密封您的系統和資料,不讓駭客幹擾和非法闖入。他們將在其他地方尋找可乘之機。

瞭解這些內容之後,讓我們轉而瞭解那些受簡單登入形式保護的樣本 PHP 應用程式。

沒有安全保障或加密的 PHP 形式處理

假定您是一位新的 Web 應用程式開發人員,沒有更多的機會使用安全功能。您建立了您的第一個應用程式,它可以在專用使用者表中儲存使用者名稱和密碼,但是,您沒有對這些密碼進行加密。這些密碼以一眼就看明白的形式存在,任何人都可以使用它們訪問資料庫。您可以構建一個如下所示的登入頁面。

清單 1. 簡單的登入頁面

<form action="verify.php" method="post">
<p><label for='username'>Username</label>
<input type='text' name='username' id='username'/>
</p>
<p><label for='password'>Password</label>
<input type='text' name='password' id='password'/>
</p>
<p><input type="submit" name="submit" value="log in"/>
</p>
</form>

此 HTML 標籤存在什麼問題?為密碼欄位選擇的輸入類型為 text,這意味著使用者鍵入該欄位的任何內容都會以明文形式顯示在螢幕上。

您可以方便地將該類型更改為 password,並將該欄位中的使用者輸入替換為一串星號。可靠嗎?絕對可靠。不過,這一步驟在很多應用程式中會被忽略。事情雖小,但在安全方面會使人們感到不安。您願意將錢存入休息大廳的視窗被嚴重毀壞的銀行嗎?也許您會。但是您可能更期望銀行是完好無損的。對於應用程式來說,道理相同。

讓我們繼續介紹處理表單提交的 verify.php 檔案。

清單 2. 簡單的 PHP 登入驗證

<?php
$user = $_POST['user'];
$pw = $_POST['password'];

$sql = "select user,password from users
where user='$user'
and password='$pw'
limit 1';
$result = mysql_query($sql);

if (mysql_num_rows($result)){
//we have a match!
}else{
//no match
}

?>

讀閱到此,您會露出滿意的微笑。等待閱讀本文加密部分的部分讀者可能變得不耐煩了,但是加密僅為安全問題的一部分。您還必須聰明地處理引入的使用者資料。developerWorks 教程 “鎖定您的 PHP 應用程式”(請參閱參考資料)討論了 SQL 注射:將不正常的資料發送到資料庫可導致有害或無根據的訪問。無論您使用多少個加密,公開弱點沒有一點好處。

您應遵循下面的傳統安全原則:“不信任使用者提供的資料” 和 “深層防禦”;清除傳入資料並通過轉義傳入的字串保護資料庫(參見清單 3)。深層防禦是將多餘的安全方法都妥善保管 —— 不僅包括加密,還包括使用者所提供資料的智能處理。
清單 3. 保護 PHP 形式解析免受使用者資料操作的影響

<?php
$user = strip_tags(substr($_POST['user'],0,32));
$pw = strip_tags(substr($_POST['password'],0,32));

$sql = "select user,password from users
where user='". mysql_real_escape_string($user)."'
and password='". mysql_real_escape_string($pw)."'
limit 1';
$result = mysql_query($sql);

if (mysql_num_rows($result)){
//we have a match!
}else{
//no match
}
?>


通過合理使用 strip_tags()、substr() 和 mysql_real_escape_string(),可以刪除任何潛在的有害命令,將字串減少到 32 個字元,並去掉所有特殊字元,資料庫可能將這些字元解釋為非預期命令字串的一部分。

在這一過程結束時,資料庫中仍有一個純文字密碼。您不能顯示它。最容易的修複方法是使用 PHP 的內建 crypt() 功能。

使用 crypt()

PHP 的內建 crypt() 功能可實現單向加密 或單向散列。它只所以是單向的,是因為在對某內容進行加密後,您永遠不能將其反轉為明文。乍一看,此想法似乎很荒謬。使用加密主要是保護資訊,隨後能夠使用該資訊,後者通常意味著能夠對它進行解密。

不要絕望。單向加密方案和 crypt() 特別受歡迎。可以使保護資訊的方法更安全。如果您的使用者密碼列表落入不法之徒之手,他們實際上沒有將密碼解密為明文的方法。

讓我們返回到密碼樣本。注釋 (notational) PHP 應用程式可能包括讓系統管理員建立、編輯和刪除使用者的模組。例如,在將使用者記錄儲存到使用者表之前,PHP 指令碼可以使用 crypt() 對密碼加密。

清單 4. 使用 crypt() 加密密碼

<?php
$user = strip_tags(substr($_POST['user'],0,32));
$pw = strip_tags(substr($_POST['password'],0,32));

$cleanpw = crypt($pw);

$sql = "insert into users (username,password)
values('".mysql_real_escape_string($user)."',
'".mysql_real_escape_string($cleanpw)."')";
//.....etc....
?>

crypt() 將一串明文作為它的第一個參數字,對它應用 salt 會影響密碼編譯演算法的隨機性,並產生輸入明文的單向暗文。如果不提供 salt,則 PHP 通常預設其系統 salt,它可以是以下值和長度之一:
演算法 Salt
CRYPT_STD_DES 2 個字元(預設)
CRYPT_EXT_DES 9 個字元
CRYPT_MD5 12 個字元,以 $1$開頭
CRYPT_BLOWFISH 16 個字元,以 $2$開頭


許多現代 PHP 安裝使用 MD5 或更高的 salt,它們使用強大的 12 個字元的 salt,但是,不要對任何事情想當然。您最好知道系統正在使用哪一個值。您可以使用以下 PHP 程式碼片段檢查伺服器的設定:

<?php echo "System salt size: ". CRYPT_SALT_LENGTH; ?>

返回的答案將是 2、9、12 或 16,它告訴您系統正在使用的值。要使用 MD5 或更高版本的 salt,您可以顯式調用明文和 salt 參數中的 crypt() 函數以及 md5() 函數,以擷取隨機暗文(參見清單 5)。md5() 函數可以散列反饋的任何字串,並將其轉變為固定長度為 32 個字元的字串。您可能更喜歡其他方法,具體的使用取決於安全需求和個人愛好。

清單 5. 使用 crypt() 和 md5() 加密密碼

<?php
$user = strip_tags(substr($_POST['user'],0,32));
$pw = strip_tags(substr($_POST['password'],0,32));

$cleanpw = crypt(md5($pw),md5($user));

$sql = "insert into users (username,password)
values('".mysql_real_escape_string($user)."',
'".mysql_real_escape_string($cleanpw)."')";
//.....etc....
?>

現在資料庫中已經擁有一個已加密的密碼,但是沒有對其進行解密的方法。如何使之有用?一個比較容易的方法是:對使用者提供的任何傳入密碼都使用相同的加密方法,並將結果與您儲存的密碼比較。

清單 6. 重訪 verify.php

<?php
$user = strip_tags(substr($_POST['user'],0,32));
$pw = strip_tags(substr($_POST['password'],0,32));
$cleanpw = crypt(md5($pw),md5($user));

$sql = "select user,password from users
where user='". mysql_real_escape_string($user)."'
and password='". mysql_real_escape_string($cleanpw)."'
limit 1';
$result = mysql_query($sql);

if (mysql_num_rows($result)){
//we have a match!
}else{
//no match
}
?>
例如,如果儲存的加密密碼是 i83Uw28jKzBrZF,則加密儲存傳入的密碼,並將它與儲存的密碼進行比較。攻擊者破壞加密的惟一方法是將一個非常長的字串列表與您的加密密碼進行比較,每次比較一個,直到找到匹配項。這也稱為字典攻擊,因此您的密碼最好不應該是密碼 或 Star Trek 字元名,甚至您的呢稱。因為在加密 Fido 後,它會變成一堆亂語,但這並不表明它對於此種攻擊是安全的。確保您的密碼具有某一長度(八個或更多字元),並包含大寫字母、數字和特定的字元,如 ! 和 $,這樣猜測您的資料會更加困難。在短語中,f1D0! 是一個較好的密碼,它勝於 GandalftheGray 之類的長密碼,由於後者使用小寫字母,並且是 “Lord of the Rings” 的字元名稱。

使用 crypt() 的一種不太好的方法

還有使用 crypt() 的另一種方法,這種方法不太好:將明文的前 n 個字元用作 salt。

清單 7. 將明文字元用於 salt

<?php
$user = strip_tags(substr($_POST['user'],0,32));
$pw = strip_tags(substr($_POST['password'],0,32));
$cleanpw =crypt($pw, substr($user,0,2));

$sql = "select user,password from users
where user='". mysql_real_escape_string($user)."'
and password='". mysql_real_escape_string($cleanpw)."'
limit 1';
$result = mysql_query($sql);

if (mysql_num_rows($result)){
//we have a match!
}else{
//no match
}
?>

如果您的使用者名稱是 tmyer,則 salt 預置為 tm,它會使某人很容易推斷 salt 的內容。這不是一個好方法。

使用 PHP 進行加密和解密

本文的大部分篇幅討論了使用 crypt() 的單向加密。但是,如果您要將訊息發送給某人,並提供對該訊息解密的方法,又該如何辦呢?請使用 PHP 支援的公開金鑰加密技術。

使用公開金鑰加密的使用者擁有一個私密金鑰和一個公開金鑰,並且他們與其他使用者共用公開金鑰。如果您要將一封私人簡訊發送給您的朋友 John Doe,您可以使用 John Doe 的公開金鑰(您已經將其儲存在自已的 keyring 中)加密該訊息。John Doe 收到該訊息後,只有他可以使用他的私密金鑰對其解密。任何給定使用者的公開金鑰和私密金鑰在數學上是不能相關的。對於 PGP 和其他公開金鑰加密方法,不存在從公開金鑰推斷某人私密金鑰的方法。

PGP 的附加特性是:私密金鑰的密碼實際上不是密碼,它是一個密碼短語。它可以是整句話,包括標點符號、空格和所有字元樣式。

使用基於 PGP 的公開金鑰加密的一種方法是使用 GNU Privacy Guard (GPG)。使用 GPG 加密的任何訊息都可以使用 GPG、PGP 或支援任一程式的任何數量的電子郵件客戶機外掛程式來解密。在樣本中,聯機表接受使用者輸入(包括訊息);使用 GPG 為特定的接收方加密訊息;然後發送訊息。
清單 8. 使用 GPG

<?php
//set up users
$from = "webforms@example.com";
$to = "you@example.com";

//cut the message down to size, remove HTML tags
$messagebody = strip_tags(substr($_POST['msg'],0,5000));
$message_body = escapeshellarg($messagebody);

$gpg_path = '/usr/local/bin/gpg';
$home_dir = '/htdocs/www';
$user_env = 'web';

$cmd = "echo $message_body   HOME=$home_dir USER=$user_env $gpg_path" .
"--quiet --no-secmem-warning --encrypt --sign --armor " .
"--recipient $to --local-user $from";

$message_body = `$cmd`;

mail($to,'Message from Web Form', $message_body,"From:$from\r\n");

?>

在此樣本中,PHP 調用 /usr/local/bin/gpg(此位置因伺服器而異),以便使用發送方的私密金鑰和接收方的公開金鑰加密訊息。結果,只有接收方可以解密該訊息,並且知道來自發送方的訊息。此外,還可以設定 HOME 和 USER 環境變數,以通知 GPG 在何處尋找儲存這些密鑰的 keyring。其他標誌的功能如下:

--quiet 和 --no-secmem-warning 抑制來自 GPG 的警告。
--encrypt 執行加密。
--sign 添加簽名,以驗證發送方的身份。
--armor 產生非二進位的 ASCII 輸出,這樣,易於通過電子郵件將其發送。
正常情況下,正如前面提到的,機密密鑰受密碼短語的保護。本特定執行個體沒有使用密碼短語,因為在每次表單提交時它都需要手工輸入。當然,在下列情況下您還可以選擇其他選項:在單獨檔案中提供短語,或使用它自已的身分識別驗證方案防止表單公用(例如,如果它是一個只能由公司銷售代表訪問的表單)。

另請注意,除非您正在對允許使用者輸入電子郵件訊息的表使用 SSL,否則鍵入的任何內容都是明文形式的。換句話說,客戶機和伺服器之間的任何人都可以看見它。不過,這是另一個主題。

結束語

我們對安全性、加密技術,甚至公開金鑰加密技術介紹了很多,目的是協助您成功開發下一個 PHP 項目。使用加密和其他加密方法的要點不是建立 100% 可靠的無縫系統。關閉的電腦才是不可攻擊的系統,但是也不能完全保證,因為某人可能會走上前走,開啟它,然後攻擊它。加密的要點是使擷取敏感性資料變得非常困難,以致駭客不再嘗試攻擊,或嘗試攻擊失敗後離去。

所有安全性考慮必須兼顧方便和保護。使用強大的演算法密鑰將所有資料都進行單向加密意味著您的資料非常安全,但是使用時很不方便。這帶來的相應缺陷也很嚴重,如同使用非加密的內容一樣,為您帶來的任何方便也為其他人擷取資料帶來了可怕的方便。通過加密重要的機密資料(如密碼、信用卡號和秘密訊息)和添加好的安全措施(如深層防禦、過濾使用者提供的資料和傳統的一般常識)可以達到最佳平衡。



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.