1. 程式人生 > >小學生坐馬桶上都看得懂的加密與通訊

小學生坐馬桶上都看得懂的加密與通訊

小學生坐馬桶上都看得懂的加密與通訊

入門導引

筆者在逛知乎的過程中,偶然看見了一篇關於介紹網路安全的文章當中談論到了關於HTTP/HTTPS,和一些密碼儲存的相關的東西,甚是有興趣,文中談到登入過程中一定要使用HTTPS而不能使用HTTP,否者中間人攻擊將很容易取得使用者的密碼,如果帶點鑽牛角尖作者的這個說法恐怕並非正確,密碼的安全性並不能因為使用了HTTPS就高枕無憂,也並非使用了HTTP就不安全.

上面這句話你可能看的一頭霧水,不過這沒有關係,這只是拋磚引玉的幾句牢騷,同時這也是筆者寫這篇文章的原因,一是科普下資料安全的那些事,二是順便帶大家初步的瞭解一下有關於密碼的知識,當然讀者不用擔心,筆者並不打算談論過多的數學方面的東西,你完全可以把本文當故事書來看.不過有些地方恕筆者口拙,仍然不可避免的新增一點點不太複雜的理論基礎,同時筆者並非全才也非研究密碼學數論的專業人士,談吐之餘可能還添加了新的錯誤,仍望讀者見諒指正.

在開始討論關於密碼安全之前,筆者很願意先給大家講述一些小故事,以達到增加文章閱讀趣味的功效,我們先來看看,假如你打算給你的GG或者是MM眉目傳情好在某個愉快的時間唱著歌兒吃著火鍋幹著快活事兒那你該怎麼辦?

當然,眉目傳情這招技術難度實在太高,除了心有靈犀一點通之外畢竟不是誰都能夠有那能耐靠擠眉弄眼就能搞明白對方想表達的是什麼意思,比如你想表達明天下午三點這個概念,恐怕除了眼睛嘴巴外還得用上你的手,你想表達帶100塊錢好在明晚能買兩張電影票這個資訊時,恐怕你連腳指頭用上也不夠了,鑑於眉目傳情不管是技術上還是生理上的不靠譜,如果你活在90年代手機還沒普及,那寫信確實是個好辦法.不過在這個早戀還容易被家長批鬥的年代,如果直接在信上寫

darling, lets go to the movies tonight(親愛的,我們今晚去看電影吧)

恐怕得帶著底下工作黨被抓犧牲的覺悟了,如果你不想你美好的初戀讓因為資訊洩露讓整個學校都知道,你恐怕就得對這些文字進行一番處理,做起來也並不困難,最初級的辦法是對單詞進行混亂或替換,比如你可以和你可愛的GG或者MM約定,加密時將d-\>c,a-\>b,r-\>s,l-\>m,i-\>j,…..也就是每個單詞在字母表中往後移一位最後z-\>a完成一個閉環,在閱讀時再將它們給移動回來,
例如darling經過變換後變成了cbsmjoh這樣傳輸的資訊就沒人能懂了.

這個辦法簡直棒極了,對於傳輸情書這樣的事情,似乎也用不到一群密碼學專家進行解密,因此你大可放心的用這個辦法傳遞你想表達的意思,這值的膨脹膨脹,莫不我是個天才,不過遺憾的是這個辦法恐怕並不能讓你申請專利,凱撒大帝在幾百年前就用這種辦法來傳遞軍事情報了

<ignore_js_op>

 

但不管怎麼樣,這個加密手法簡單粗暴有效,也不用花多少心思去理解,只要像上面這樣製作一個對應表,就能夠完成一段資訊的加密與解密,如果你覺得不放心的話,你大可用更加混亂無序的一張對映表來完成這個加解密,這樣就能粉碎那些想要琢磨你單詞在字母表上到底後移幾位的八卦狗仔隊們的破解了.

這種加密被用了很長時間,甚至在軍事上,而且一直工作的不錯,蘇格蘭的瑪麗女王正是使用這種加密方法來完成很多祕密訊息的傳遞,不過事實也證明了,她確實被這個辦法給坑慘了:),當然本文並不打算介紹瑪麗女王是如何用這種加密方法同別人密謀造反然後被拆穿被續的,我們把注意力放在她的密碼是如何敗露的,現在你可能疑惑,這個加密的問題出在哪了,看上去確實木有啥問題啊,但實際上破解的方法卻很簡單,不需要你具備多麼高深的密碼學數論編碼學方面的知識,只要稍微瞭解下統計學的東西就可以了.那麼是如何辦到的呢,你可以翻開一本英文書,然後從頭看到尾,然後你可以數數當中的字母a佔所有字母的幾成,字母b佔幾成….也許你已經發現當中的區別,是的,如果你統計了足夠多的文章,你會發現這些單詞出現的可能性大概就在某個範圍之內,這種替換法也許替換了原來的單詞,卻無法替換它出現的概率,當破譯者通過某些手段收集了足夠多的瑪麗女王的密文信件時,他就能夠通過這種辦法來破譯出明文了,也正是這樣,強度不夠的加密手段讓瑪麗女王最終因為事情敗露而上了斷頭臺.

這個故事可能講的有點長,但它卻表達了筆者想要表述的幾個概念,一種是加密是什麼,顯然的,加密是將一種資訊表達變成另外一種資訊表達的方式,一個很現實的比方是在外地你和你老鄉交談用的可能是你們家鄉的方言,儘管你用普通話表達”我愛香菜”和用方言表達”我愛香菜”是一個意思,但用方言表述不是你家鄉的人恐怕聽不懂,另一種就是對映關係了,就像上面的對應表,實際上你可以叫它對映表,沒錯
,無非就是把一串資料對應某種關係變成另外一串資料.

儘管我們知道了上面的這種對映加密有多麼的不靠譜,當然這種不靠譜的加密還是有個名字就是叫”凱撒加密”,經過了幾個世紀的發展,經過眾多的數學家密碼學物理學甚至是生物學….家的努力,我們最終還是開發出了不少靠譜的加密方式,在這裡,因為我們主要討論的是計算機相關的東西,所以筆者也得用數學的方式(訊號與系統?)的方式來描述一下了.

假設我們將沒有加密過的資訊叫明文(A),加密後的資訊叫密文(C),設B為加密方式,那麼加密的過程就可以寫成類似

A*B=C

當然,解密過程就是

C*D=A

其中D表示B的逆,也就是解密過程了.

你的鑰匙安全麼

通過上面的故事我們很容易理解一個加密的過程,舉個非常通俗易懂的栗子,假如我們有五個數字要告訴對方,分別是1,2,3,4,5加密就是將每個數字乘以2,對面於是就收到了密文2,4,6,8,10最後,對面只需要將每個數字除以2就能取得明文1,2,3,4,5了,在這個過程中,2作為整個加密過程中最關鍵的數字,可以說是整個加密解密的鑰匙,你就得好好儲存了,一旦讓別人知道了你的金鑰,你的加密將形同虛設.

顯然的,上個章節說到的瑪麗女王並非是自己不小心把自己的鑰匙洩漏了,但別人卻通過統計學的方式取得了她的鑰匙,雖然並不是每個人都能意識到字母在大量的文章書籍中的統計學關係,但我們卻不得不面對一個更加直觀的問題,假如你和一個你不認識的人進行加密通訊,你如何保證你的鑰匙能只交給你的接頭人呢.

當然,當面交易不管是在密碼還是網購都屬於一個比較靠譜的方式,但是如果你想通過信件的方式,就是經過一堆不知名的郵差郵局最終才能到你的接頭人手中時,你就得擔心擔心中間有沒有人把你的鑰匙給拷貝了一份了.現在你面臨一個非常嚴重的問題,你無法保證中間人會不會出賣你,然而你確不得不把自己手中的鑰匙交給他們,否者你的接頭人就無法使用它來和你進行加密通訊了.

儘管這種方式和我們實際說的密碼學多多少少有一點不一樣,但是它的確給了我們提示,設明文為A,金鑰為B,密文為C,是否存在一種加密函式使得:

AB=C
C
D=AB無法推匯出(至少推導的成本很大)D

簡單來說,就是加密的金鑰和解密的金鑰不一樣,這樣我們就不用擔心我們的金鑰被洩漏了,

在現實有點像這麼一個過程

  1. 首先準備一個帶鎖的箱子,用鑰匙把這個箱子開啟(公鑰)

  2. 把這個箱子交給郵遞員,同時箱子裡附上一個字條,上面寫著:請接頭人想一個我們之間的通訊加密方式,然後把金鑰也放在箱子裡鎖上寄回給我.(通過公鑰加密)

  3. 當這個鎖上的箱子再次回到你手中時,用鑰匙開啟箱子,取得金鑰和加密方式(私鑰解密)

  4. 之後就可以用這個加密方式和金鑰進行通訊了

上面這個辦法完美地避免了中間人看到你和接頭人金鑰,畢竟在交回來時,它可是鎖在箱子裡面的,只要你發現收回來時這個箱子有什麼不對勁,你立即可以編輯簡訊”
有內鬼,終止交易,”.

雖然最後放在數學中這個方式有點不同,但在思路上,卻是大同小異,你也許已經發現了在高中的階段,要計算3的五次方是多少遠比你算多少的5次方是218要簡單的多,當代的不對稱金鑰技術(公鑰加密),大多都用上了這種資訊不對等的理念,也就是正推容易逆推難.

談到公鑰加密,就不得不聊聊目前相當有名的RSA和ECC了,相對於ECC,RSA理解起來就容易的多,RSA加密簡單來說利用了大數質因數分解的數學難題

比如現在你可以隨便挑選兩個素數,比如59,83,然後將它們乘起來59*83=4897,這很容易,即使是一個小學生也能在十幾秒內算出來,但是如果我只告訴你4897這個數,然後讓你做因數分解,如果不信你可以試試,不過八成你需要一個一個數去試試了,假如這兩個素數挑選的都非常大,那麼就算是超級計算機上場,恐怕也得算到世界末日了.儘管上面已經說了本文並不打算討論過多的數學方面的問題,但幸運的是,理解RSA加密並不複雜,即使是在這短短的篇幅中,也很容易將RSA的原理給講清楚.

  1. 定義兩個素數p,q設n = p*q

  2. 設k= ϕ(n)=(p-1)(q-1), ϕ(n)是尤拉函式,這個不熟悉可以百度

  3. 挑選一個大於1小於k的數d,同時d與k互質

  4. 取整數e(RSA中常常取65537),滿足(d*e)%k=1,即de=kt+1(t為某一整數)

然後我們挑選(e,n)作為公鑰,將它釋出出去,(d,n)為私鑰將它儲存起來

那麼加密過程是怎麼樣的呢,我們假設將明文編碼為x,x與n互質設(圖片看不清請下載下來自己看)

<ignore_js_op>


y即為密文,那麼如何對密文進行解密呢,也很簡單隻需要

 

<ignore_js_op>

 

就可以了,當然口說無憑,我們來證明一番

<ignore_js_op>

 

因為x和n互質,根據尤拉定理,
<ignore_js_op>

 

因此上式最終變為了x%n=x,RSA得證,要破解RSA那麼關鍵就是找到這個d了,我們看看d是怎麼來的,首先從點3我們知道,要知道d首先要先知道k,而k=(p-1)(q-1)也就是需要知道p和q了,而我們公佈的只有一個e和n,按照不成文的欽定就算e是65537,也就是說我們必須通過n倒推出p和q,那麼,問題就變成了這個大數因數分解的世紀難題了,當然如果你有辦法解出來,給我回帖前我建議你先寫成論文,只要發表後這樣你就可以先領取500萬美元的獎金了(這還是零幾年的價格,現在應該獎金應該足夠你在北京一環內買套豪華別墅).

RSA已經流行了多年,很多時刻彷彿這套理論就會被爆些大新聞讓人感覺其安全性已經搖搖欲墜,但是最終RSA仍然屹立不倒,些許在之後的某一天量子計算機誕生或者哪個大神真正找到了某個快速大數的質因數分解的方法,RSA也算真正完成了他的歷史使命了.

公鑰加密技術有諸多的優點,但是其缺點也一樣很明顯,大多的公鑰加密演算法其效能開銷基本都比金鑰對稱加密大得多,因此,他們一般都不用於加密大量的資料,在實際使用中,它們大多被用於交換其它更加經濟快速的加密金鑰對,或者被設計與數字簽名,如果你想進一步瞭解RSA,那麼在在網際網路上的資料已經是鋪天蓋地筆者便不再複述了,如果你對其它的公鑰加密有興趣比如ECC,那麼也許筆者之後的\<\<小學生坐在馬桶上都看得懂的橢圓曲線加密原理\>\>你也許有興趣.

HTTP/HTTPS

看到了標題你可能已經在犯咕咚,剛說完密碼怎麼突然就跳到http/https上來了,不過不用擔心,一個非常直觀的理解就是,http就是你用明文來寫情書,https就是你的情書加密了,實際上後者就是前者加密後的產物.那麼什麼是http呢,你可以開啟一個網站比如百度,如果你用的是chrome,那麼按下F12,你可以看到有一堆文字

<ignore_js_op>

 

這段文字就是符合http規範的的文字(當然http協議相關的細節資訊已經省略了),你可以管它叫網站原始碼,或者簡單一點來說,就是這段文字經過解析後變成了你所看到的網頁,當然,這個原始碼在網際網路上傳輸,就像你把情書交給了一個不靠譜的郵遞員一樣不靠譜,這個郵遞員大可能已經被你的情敵收買了,把你的信件拆開來添油加醋地加一點東西然後再神不知鬼不覺地封回去這樣足夠給你造成一些情感危機了,但https能夠很好的避免這一堆問題,因為這段文字被加密了,如果不知道解密手段的話,即使添加了一些東西解密後也會變成一堆意義不明的資料,收信方也很容易察覺出問題.因此,https顯然在防篡改方面比http要安全.

那麼是否是HTTPS就一定比HTTP安全呢,HTTP是否一定不安全呢,就像文中作者所說的,不管怎麼樣一定要使用HTTPS做密碼的登入框,不然密碼就會被洩漏.

其實這句話,就有點像就算是屠龍寶刀如果給一個菜鳥的話,恐怕真到約架時,也會被砍的娘都不認識,就算是一根樹枝假如給的是獨孤求敗這種人物,就算是在多人一起上也是被扁的哇哇叫,打鐵還需自身硬,如果自身都不夠硬,真要幹起架來,哪怕是再好的武器也於事無補.要理解HTTPS為什麼安全,安全在哪裡,我們就得有打破砂鍋問到底,不到禿頭不掉淚的精神以探其究竟.

HTTPS和中間人攻擊

在這裡,我們進稍微一步地探究下細節,有關於HTTPS的傳輸流程是怎麼樣的,可以看到,HTTPS比HTTP就多了一個字母S,這個S代表著SSL(Secure
Socket
Layer)的意思,也就是安全傳輸層,不要看名字那麼高大上,實際上用人話來講就和筆者第一章說的那個送箱子的過程差不多,首先SSL層先使用公鑰加密技術交換金鑰對(比如RSA,ECC….),之後再使用AES
DES或者更經濟點的RC4進行加密通訊,看上去這個交遞箱子的方案似乎沒有什麼問題,但我們回到那個交遞箱子的過程

  1. 首先準備一個帶鎖的箱子,用鑰匙把這個箱子開啟(公鑰)

  2. 把這個箱子交給郵遞員,同時箱子裡附上一個字條,上面寫著:請接頭人想一個我們之間的通訊加密方式,然後把金鑰也放在箱子裡鎖上寄回給我.(通過公鑰加密)

  3. 當這個鎖上的箱子再次回到你手中時,用鑰匙開啟箱子,取得金鑰和加密方式(私鑰解密)

  4. 之後就可以用這個加密方式和金鑰進行通訊了

我們做一個這個假設,假設這個郵遞員準備了一個和你一模一樣的箱子,然後偽裝成你的接頭人和你通訊,再用這個偽造的箱子和你真正的接頭人進行通訊,那麼你還能保證你的通訊是安全的麼.恐怕這個時候,即使是公鑰加密技術也無能為力了,我們能做的,只能是儘量提醒接頭人,比如在箱子上蓋個印章條形碼,並方方正正地寫上”此箱子版權所有,仿冒必究,請到xx正品店進行專櫃驗證”,然後祈禱你的接頭人會好好地驗證這個箱子的真偽,但鑑於你和接頭人從未謀面,恐怕他也並不知道你會不會給他寄個”帶有防偽標籤的箱子”,是的,這個過程幾乎和ssl的理念一樣,每個https的站點需要向一個可信的第三方CA(數字證書的頒發機構)申請一個證書來向每一個瀏覽你網站的人證明你是你,但瀏覽你網站的人可能根本無法意識到,你的網站是否進行過防偽了這種中間人攻擊的手段又叫SSL剝離攻擊,其原理圖一看就明白大概是如何辦到的

<ignore_js_op>

 

如何避免中間人攻擊

雖然不願意承認,不過如果你的網路流量出入口真被某些居心叵測的破壞分子控制的話,你能做的就是儘量祈禱這個傢伙的技術水平不夠到家和給你編寫APP的碼農技術到不到家了,搭建一個SSL剝離的攻擊方案也許就是一個黑wifi,一次ARP劫持和幾個指令碼的事情了,實際上避免攻擊的準則除了選擇一個可以信賴的網路服務商,另外的更多工作需要在自己設計的程式碼中去實現而不是盲目地相信某種通用的手段(當然不是說HTTPS不好用,有條件當然還是最好用上),一個最基本的理念是,如果攻擊你的成本遠遠大於攻擊成功取得的價值成本,就能夠很大程度的避免自己被一些別有用心的大佬而不是吃的太飽的大佬擺上一道,這也就是為什麼我們學習密碼學的原因,如果你能將那些更加複雜的公鑰加密技術設計在你的通訊體系中,設計的程式能夠利用這些知識,去驗證收到資料的真偽(比如驗證可信CA頒發的簽名證書)那麼攻擊者就需要花費更大的代價去剝離你的驗證部分,或者根本就不可能在偶然的一次通訊劫持中完成這類攻擊.

但遺憾的是在程式碼通用化程度如此高的今天,儘管很多的軟體運用了完善的加密體系最大程度地保證了通訊的安全,但大部分因為開發成本或者是其它的關係,開發人員並沒有好好的給自己充個電認為使用現有的安全架構就能夠一勞永逸去避免一堆可能帶來的問題,例如這個登入的驗證問題,處理起來遠遠不是弄個證書整個HTTPS就能夠解決的,但不論是出於開發平臺還是出於開發成本或者是開發員的技術水平,絕大多數的網站在保證安全這塊都還有很長的路要走.

除了開發人員,最後是寫給使用者安全建議的:

  1. 請在信任的網路中下載程式或流量網頁

  2. 如果你連入了一個不信任的網路,請不要瀏覽不帶有效簽名的網站,

  3. 不要下載沒有有效簽名的軟體,如果你新的過這個沒有簽名的軟體,也要在信任網路中下載

  4. 瞭解密碼安全的一些知識

  5. 找個靠譜的碼農朋友.

雜湊函式(hash)

最後筆者在末尾想科普一下雜湊函式也就是俗稱hash函式的東西,在開始科普關於hash之前,筆者首先想談談大約五六年前CSDN資料庫洩漏的事件,儘管我們無法猜測csdn到底出於什麼目的將使用者的密碼進行明文儲存,但這個事件無疑在圈內掀起了軒然大波,無數無辜躺槍的碼農程式猿忙著修改自己的賬戶密碼,避免被某些別有用心之徒用撞庫的手段給自己造成損失.

倘若csdn不使用明文記錄使用者的密碼資訊,而將這個密碼用某種不可逆的手段編碼成其它的資料,無疑這次的風波至少不會造成如此巨大的損失.

那麼說人話, hash函式到底是什麼呢,按照百度百科的說法,
hash就是指通過雜湊演算法,變換成固定長度的輸出,該輸出就是雜湊值,說的太專業了?沒關係,除法求餘數總會吧,看下面的式子

y=x%99

這是一個很簡單的求餘運算,x表示輸入的某個整數值,y表示輸出的值,顯然,不管x取多少,y的結果必定在0-99,如果你知道y的值那麼能不能求出x的值呢,很遺憾,也許你能找出很多個符合這個條件的x值,但你恐怕永遠不能確定原始的x值是哪一個了

整數求餘運算是一個非常簡單的雜湊運算函式或者通俗點叫hash函式,但這是一個不合格的hash函式,因為我們可以非常容易地通過輸出y求得多個x的可能解,並且x和y在一定的範圍內存線上性關係,而理想的hash函式,是正著算容易,倒著算難,同時輸入的輕微變動也將導致輸出極大的不同,

那麼這就很有意思了,假如我們在資料庫儲存密碼時,使用適當的hash函式對其進行編碼,那麼就能夠避免我們的密碼明文被洩漏了,說到這裡,不得不提提當今鼎鼎有名的幾個hash函式,比如MD5,SHA256.

這就安全了麼?

的確,當明文的密碼使用MD5或者是SHA256後想要再逆向為明文是不大可能了,但這還不足以讓你高枕無憂,畢竟早不久才報出個大新聞MD5被破解了!,當然,被破解這種標題黨的行為在學術上來說極為的不準確,準確來說,是MD5被找到了一種能夠快速找到碰撞的辦法,那麼碰撞是什麼呢,我們回到之前的y=x%99,如果我們知道y的值是1,那麼x的值是多少呢,顯然的,x的值可以是100,可以是199,可以是298….,要知道如果我們用求餘法作為密碼的hash函式,那麼我們輸入199,298…哪怕我們的原始密碼是100,也會被當做是正確的密碼,也就是說,199,298是100對於該hash函式的碰撞結果.

這可就要命了,明明黑客輸入的密碼和我們輸入的密碼不一樣,系統還是將它當做了一個正確的密碼讓他登入了,這簡直就是密碼系統的災難,既然MD5不再安全了,那麼就放棄MD5專用SHA256吧.

然而還是太天真了,我們忽略了一個最基本的事實,如果明文的密碼長度不夠,那麼不管加密的手段如何的高明,我們也能通過窮舉的方式進行破解,比如你的密碼是一個三位數數字,那麼我只需要把100-999都嘗試一遍,就可以知道正確的結果了,也許用人腦這個辦法有點難,但是在計算機當中,完成這個窮舉連1秒都不用.

實際上確實也有人這麼幹了,他們購買了大容量的儲存裝置,收集大量大常用明文密碼進行hash計算,同時他們建立了快速的查詢機制,只要你的密碼長度不夠或者使用了一些常用的密碼,那麼hash函式的對你明文密碼的保護機制將很可能不再有效.而這種方法在網上有個比較漂亮的名字叫彩虹表

給密碼加約束

為了避免彩虹表的危機,我們必須對密碼加一系列的約束,比如我們可以規定密碼的長度一定要大小寫組合的8位以上,16位以下,然後再在密碼的結尾加上一段我們自己想出來的隨機的值增加輸入長度,以避免常規計算的的彩虹表對我們的密碼進行暴力破解的效果.

這是一種非常流行的做法,用專業的術語來說就是加鹽(salt),那段隨機的值就是我們所說的鹽值,這個效果的確非常有效,在如今即便是已經被證明不安全的MD5在尋找碰撞仍然不是那麼的快的時候,只要這個salt足夠長,的確能夠在一定程度上緩解這次的危機問題,但不管如何,我們仍然應該摒棄那些不再安全的hash函式而使用目前相對安全的hash函式.同時在設計通訊架構時,永遠不要相信當前的密碼手段是永恆不破的,畢竟這就和明天我會不會中個億元大獎然後走向人生巔峰一樣,誰又說得清呢?

小學生坐馬桶上都看得懂的加密與通訊