永強教你加解密:對稱篇(一)

elarity發表於2019-06-12

大家好,我是永強,就是老李之前經常給你們說的區塊鏈大神、大學肄業卻依然大公司iOS主程一波兒流、只生活在老李口中尚未真實露面的騙錢高手、老王的左膀右臂 ——— 趙永強。我和尼古拉斯趙四之間並沒有什麼強關聯,我只是單方面認識他而已。

之前老李企圖讓我發表一些關於如何進行高階騙工資騙錢的教程,被我義正言辭地拒絕了:

                   畢竟是畢生絕學,不能就這麼輕而易舉地教給你們

不過後面有時間我可以給大家出一些關於“如何在公司混日子還能升職加薪”的入門級教程,傳男不傳女,獨家絕技!敬請期待!

圖片描述

言歸正傳,那個一直以來我對加解密技術都是耿耿於懷的,因為很多年前有一次面試中被這東西給坑掉了,雖然我後來就自己對加解密中一些自己不懂的地方請教了對方而且他也沒有給我講清楚…

事情都過去好幾年了,本人自我感覺已經一定程度掌握了一些關於加密的高階技術,因為決定出來裝一波兒逼,時間比較緊張,我打算趕在2020年農曆新年之前把逼裝完,你們要注意配合。

我知道老李之前在社群發表了一些關於加密啊、解密啊之類的東西,甚至還扯上了什麼DH什麼ECDH,又是質數又是橢圓曲線,不過這並不與本系列產生衝突,這並不重要,不要在意這些細節,他那個too young too simple,sometimes naive…

這將是一個大概由四篇左右的文章組成的系列文章,所以在正式開始之前,我不得不強調一點 ——— 如下這幾門學科的基礎理論知識:

  • 《離散數學》
  • 《微分與積分》
  • 《空間幾何》
  • 《概率論》

你並不需要具備。。。

不過你總得知道除了html和css之外的任意一門程式語言。儘管本人精通上到CLanguage下到Perl之類的各種語言,但是本文將採用世界上最好的語言進行一些程式演示,後面老李可能會使用CLanguage和Golang進行其他語言的演示補充。

簡單說來呢,加解密技術就是分為兩大類:

  • 對稱加解密
  • 非對稱加解密

其中,常見的對稱加解密演算法有DES、3DES、AES;而非對稱加解密技術比較典型的則是RSA,就是什麼公鑰私鑰證照什麼亂七八糟的。

我們先從對稱加解密開始,粗暴地說呢,對稱加解密就是“加密和解密的時候用同一個密碼”,聽起來就非常對稱,有沒有?

用圖表達一下就是:

圖片描述

最一開始的時候,我朝人民一般都是傾向於使用“天王蓋地虎”,“寶塔鎮河妖”這種加解密技術;然而,美帝用了一種叫做DES的技術進行對稱加解密,這玩意一度成為業界通用的對稱加解密技術,銀行、五角大樓都愛用這玩意,可惜好景不長、世風日下、世態炎涼,這玩意的破解成本越來越低越來越低~~ 於是,為了續命,就又有一些白鬍子老頭給DES打補丁,縫縫補補搞出來一個玩意叫做3DES,繼續用,又不是不能用…這個顧名思義就行了,別打我,真的:3DES就是用DES處理(注意是處理,我沒說是加密)了三次的意思。就目前看來,3DES實際上用的可能也並不是十分廣泛了,所以如果大家在選擇對稱加解密技術的時候,儘量避開DES和3DES就可以了。

呵呵,喜新厭舊的沙雕人類…雖然DES已經沒人用了,但畢竟也是輝煌過,我覺得還是得動手錶演一波兒。我們知道,在php7裡,原來的mcrypt系列加解密已經被放棄掉了,官方建議我們使用openssl系列來進行加解密,所以確保你的PHP環境裡安裝了openssl標準擴充套件。

<?php
// 這個函式列印出來openssl支援的所有加密方法以及模式的組合
$arr_ava_methods = openssl_get_cipher_methods();
print_r( $arr_ava_methods );

檔案儲存成test.php後,執行一把:php test.php | grep des,結果你們感受一下:

圖片描述

其中帶有ede的,比如des-ede*這樣的就表示是3DES。還有這麼多奇奇怪怪的字尾是什麼含義?回頭再說…又不是不能用。

圖片描述

篩選一下,我們看des(非des3)有幾種帶著尾巴的具體方法:

  • des-cbc
  • des-cfb*(注意後面的萬用字元星號)
  • des-ecb
  • des-ofb

我們先用傳統des方法繼續進行裝逼表演:

<?php
// 我們就選用des-ecb方法進行一次des加密
$ava_methods = openssl_get_cipher_methods();
$my_method   = 'des-ecb';
if ( !in_array( $my_method, $ava_methods ) ) {
  exit( '錯誤的加密方法'.PHP_EOL );
}
$key  = "123456";
$data = "helloMOTO";
echo "明文:".$data.PHP_EOL;
$enc_data  = openssl_encrypt( $data, $my_method, $key );
echo "密文:".$enc_data.PHP_EOL;
$dec_data  = openssl_decrypt( $enc_data, $my_method, $key );
echo "明文:".$dec_data.PHP_EOL;

儲存為test.php執行一把:

圖片描述

完美!就像老王的meshbox一樣,完美!

簡單解析一下:

換個方法繼續一下:我們使用openssl_get_cipher_methods()函式獲取到可以使用的所有des加密方法,然後簡單判斷一下我們選用的方法是否在其中;緊接著我們用123456作為密碼,helloMOTO作為明文內容,openssl_encrypt()就是加密函式,openssl_decrypt()就是解密函式,具體的函式原型出門左拐查手冊,總之一切都是這麼的完美!

<?php
// 我們就選用des-ecb方法進行一次des加密
$ava_methods = openssl_get_cipher_methods();
$my_method   = 'des-cbc';
if ( !in_array( $my_method, $ava_methods ) ) {
  exit( '錯誤的加密方法'.PHP_EOL );
}
$key  = "123456";
$data = "helloMOTO";
echo "明文:".$data.PHP_EOL;
$enc_data  = openssl_encrypt( $data, $my_method, $key );
echo "密文:".$enc_data.PHP_EOL;
$dec_data  = openssl_decrypt( $enc_data, $my_method, $key );
echo "明文:".$dec_data.PHP_EOL;

執行一波兒,結果如下圖:

圖片描述

並不完美,報錯了,一個warning級的錯誤,雖然並不影響加密和解密,但是畢竟是報錯了,錯誤原文我複製貼上過來,你們感受下:

PHP Warning: openssl_encrypt(): Using an empty Initialization Vector (iv) is potentially insecure and not recommended in /home/ubuntu/lab/test.php on line 10

大概意思就是:用了一個並不推薦而且不安全的空iv在test.php的第十行。我正在翻譯的這句的時候,已經精通英語的老李在旁邊跟我說“你這翻譯也太硬了,要學會人性化,看好了,一看你這就是沒上過全日制大學本科的惡果”:

PHP警告:openssl_encrypt():iv向量最好別是空的,不推薦這麼用,而且這樣並不安全~

什麼是iv向量?先拋開這個問題,我先寫一段程式碼,讓他能跑起來:

<?php
$ava_methods = openssl_get_cipher_methods();
$my_method   = 'des-cbc';
if ( !in_array( $my_method, $ava_methods ) ) {
  exit( '錯誤的加密方法'.PHP_EOL );
}
// 處理iv向量的兩行程式碼
$iv_length = openssl_cipher_iv_length( $my_method );
$iv        = openssl_random_pseudo_bytes( $iv_length );
$key  = "123456";
$data = "helloMOTO";
echo "明文:".$data.PHP_EOL;
$enc_data  = openssl_encrypt( $data, $my_method, $key, 0, $iv );
echo "密文:".$enc_data.PHP_EOL;
$dec_data  = openssl_decrypt( $enc_data, $my_method, $key, 0, $iv );
echo "明文:".$dec_data.PHP_EOL;

注意到8、9、10和15、17兩行,均為iv向量做了改動,然後這次程式碼儲存了執行一波兒:

圖片描述

完美!就像老王的meshbox一樣,完美!

那麼,在des加解密中,我們遺留了兩個問題:

  • des-cbcdes-cfb等這些字尾是什麼意思?
  • iv向量是什麼鬼東西?

長按或許有驚喜

圖片描述

相關文章