畢業(yè)工作以來,接觸的好幾個項目都涉及到數(shù)據(jù)加密和傳輸加密的處理,這些項目的共同點是需要與異構系統(tǒng)對接叁丧,并且要與對方做敏感度高的數(shù)據(jù)交互。在讀研期間恰好稍微接觸過一些信息安全的知識普及岳瞭,沒想到一來公司就需要用上這部分的知識拥娄。在這里寫一寫經(jīng)驗總結,也分享一下相關的知識瞳筏。
我們通常會在傳輸和數(shù)據(jù)兩個層面做安全處理稚瘾。
傳輸,通常我們最熟悉的就是SSH/SFTP協(xié)議和基于SSL的Https協(xié)議姚炕。
數(shù)據(jù)摊欠,數(shù)據(jù)是指數(shù)據(jù)在結束傳輸后落地在[文件系統(tǒng)/數(shù)據(jù)庫]時的展現(xiàn)形式。數(shù)據(jù)的安全一般需要使用一些加密算法對數(shù)據(jù)做[簽名驗證]和[加密解密]兩個措施來保證柱宦。OpenPGP是一套用于數(shù)據(jù)簽名些椒,加密和解密的開源規(guī)范,用的會比較多掸刊。在之前的項目實施中免糕,大部分境外的對接用的就是SFTP+OpenPGP。
接下來首先會用一小章節(jié)介紹一下密碼學的基本概念忧侧,后面的實施部分會頻繁地提起到這些詞匯石窑,如果對這部分熟悉的同學直接跳過就可以啦,之后會具體介紹SFTP以及PGP的相關概念原理以及操作蚓炬,最后介紹項目的實施松逊。
密碼學基本概念
在聊SFTP和OpenPGP之前,我們先用通俗的語言解釋一下密碼學里面一些常用的專業(yè)名詞都是什么意思肯夏。
加密:把人看得懂的明文轉換成人看不懂的密文棺棵,比如把“i love u”轉換成“iP0mlsGW5Kqr1Axy0/PVL/r5lHSBookm”楼咳。
解密:把密文翻譯回明文。
簽名:把明文數(shù)據(jù)加密成密文烛恤,這段密文就被稱為原數(shù)據(jù)的簽名。傳輸?shù)臅r候把明文密文一并傳輸出去余耽,簽名用于發(fā)現(xiàn)數(shù)據(jù)被篡改缚柏。
驗簽:用接收到的明文內容再次生成簽名,對比傳輸過來的簽名看是否一致碟贾。
密鑰:加解密過程中所需要的鑰匙(一串字節(jié)碼)币喧。密鑰是整個加密解密過程的關鍵。密碼學中的算法和密文都不需要保護袱耽,攻擊者即使知道密文和加密過程使用的是什么算法杀餐,只要攻擊者沒有密鑰,那么明文就可以認為是安全的朱巨。
-
算法:用于加密解密的密碼學算法史翘,一般來說分為三種 1. 對稱加密 2. 非對稱加密 3. 哈希(散列算法) 算法重點元素對比
哈希主要用于簽名以及驗簽,該算法不可逆冀续,也就是只能加密不能解密琼讽。接下來主要說一下個人對對稱加密算法和非對稱加密算法的理解。
從圖中可以看到洪唐,對稱加密算法要比非對稱加密算法快钻蹬,那為什么還要有非對稱加密算法?這里的主要原因是密鑰的保護問題凭需。 對稱加密算法加密和解密用的是同一個密鑰问欠,非對稱加密算法加密用的是私鑰,解密用的是公鑰粒蜈。也就是顺献,使用對稱加密算法時,密鑰一定要為發(fā)送方和接收方雙方可知薪伏,這里就一定涉及傳輸密鑰的問題滚澜,并且當密鑰被截獲時,攻擊者可以隨意加解密嫁怀。那傳輸過程中怎么保護好密鑰设捐?無解。因此非對稱加密算法就誕生了塘淑。
使用非對稱加密算法萝招,首先要生成一對密鑰,其中一個只能自己知道存捺,因此命名為“私鑰”槐沼。另一個告訴接收方曙蒸,叫“公鑰”。加密時岗钩,用公鑰加密纽窟,私鑰解密。這樣攻擊者只能知道公鑰不能知道私鑰兼吓,無法完成數(shù)據(jù)的破解臂港。因為私鑰不需要做任何的傳輸動作,因此可靠性高视搏。
但是由于非對稱加密算法速度慢审孽,因此一般只用來加密少量數(shù)據(jù),實際操作一般會結合兩種加密算法來使用
1. 由對稱加密算法加密文本數(shù)據(jù)浑娜;
2. 使用非對稱加密算法和公鑰加密對稱加密的密鑰佑力,把加密后的密鑰和密文一并發(fā)送給接收方;
3. 接收方使用私鑰解密對稱加密的密鑰筋遭;
4. 最后用對稱加密算法和3解密后的密鑰解密文本數(shù)據(jù)打颤。
SFTP安全文件傳輸協(xié)議
SFTP協(xié)議使用SSH連接通道的基礎上完成文件的傳輸。SSH協(xié)議基于雙方約定連接宛畦,使用一系列的加密手段保證了連接通道的私密安全瘸洛。 SFTP 連接有兩種方式,登陸密碼認證和密鑰認證次和。項目開始前反肋,首先需要找對方確認使用的是哪種連接方式。
密碼認證
sftp -P [port] [username]@host
-
密鑰認證(以對方為服務端為例): 首先需要生成一對連接密鑰
生成密鑰過程.pngsftp -P [port] -i [private key] [username@host]
(-P 參數(shù)指目標服務器端口畅形,一般是22养距; -i 是私鑰的絕對路徑,也就是上述的id_rsa)
登陸完成后就可以直接用put [local filePath]
和get [remote filePath]
來上傳/下載文件了日熬。
使用Java連接可以com.jcraft.jsch
包來做連接棍厌,公鑰認證需要填加屬性
Jsch jsch = new Jsch();
jsch.addIdentity(privatekey,passPhase);
其余的可參考https://www.cnblogs.com/zjwwljty/p/8548468.html
SFTP公鑰登陸流程
另外這里提一下sftp公鑰登陸流程,實際上也包含了一個非對稱加密解密的過程竖席。
當客戶端需要使用公鑰登錄時耘纱,向服務器發(fā)送一個公鑰的id;
服務器接收到id后驗證公鑰在服務端是否存在毕荐,如果不存在登陸失敗束析,如果存在進行下一步;
服務器根據(jù)id獲取公鑰的內容憎亚,驗證公鑰是否可用员寇,如果不可用登陸失敗弄慰,如果可用進行下一步;
服務端隨機生成一段字符串蝶锋,并用公鑰進行加密陆爽,把加密后的結果返回給客戶端;(這里便是一個非對稱加密)
客戶端收到加密的字符串扳缕,使用私鑰進行解密墓陈,把解密得到的字符串連同session id一起使用md5做哈希,把哈希后的結果返回給服務端第献;
服務端使用同樣的md5計算并把計算結果與客戶端返回的值做對比,驗證是否登陸通過兔港。
OpenPGP數(shù)據(jù)加密協(xié)議
上面第一章說了很多密碼學的基本概念庸毫,并且在最后指出了加密的常規(guī)操作是對稱加密結合非對稱加密共同完成的。這一章的OpenPGP講的就是一個常用的加密標準衫樊,如何統(tǒng)一化一個復合的加密流程使得發(fā)收雙方能夠減少加密流程的制定工作從而進行快速地做數(shù)據(jù)對接飒赃。
我們選定需要的對稱及非對稱加密算法,一次簽名+加密的OpenPGP流程大致如圖所示(使用OpenPGP簽名(SHA-256)及加密(RSA-4096,AES-256))科侈。
將輸入的數(shù)據(jù)壓縮载佳,這一步可以模糊簡單的數(shù)據(jù)規(guī)律同時壓縮數(shù)據(jù)量
使用我方私鑰(結合私鑰密碼)簽名數(shù)據(jù)并生成簽名塊
生成對稱加密密鑰
使用對稱加密加密壓縮數(shù)據(jù)得到密文
使用對方公鑰加密對稱密鑰
-
將簽名塊,密文塊以及加密后的對稱密鑰組成最終PGP塊
OpenPGP加密流程.png
項目實施
當時我接到需要跟合作伙伴做簽名加解密的對接任務時臀栈,無論是技術上還是流程上還是踩了不少坑蔫慧,這些踩下的坑并不是說會對項目造成類似于停滯不前的嚴重影響,但是維護的時候就嘿嘿了权薯。
基本上姑躲,當和對方確認了安全手段是SFTP和OPENPGP時(其他的暫時沒遇到或者不值一提或者不允許提),我梳理了以下的實施流程(自己是客戶端并且語言使用JAVA)
與對方確定SFTP登陸方式(密碼or公鑰)盟蚣,假設是公鑰黍析,需要讓客戶端方生成一對密鑰,并共享公鑰(生成方式在文章的SFTP介紹中有提屎开,這里就不再贅述了)
與對方線下確認服務器的指紋是否正確(打電話阐枣,郵件或者見面問都行)。在[home_dir]/.ssh/目錄下有一個knownhosts文件奄抽,與對方服務器建立ssh/sftp連接時蔼两,該文件需要記錄有對方服務器的指紋信息,若ip和指紋信息不匹配如孝,該連接將會被拒絕宪哩,這個機制是ssh用來防止中間人攻擊做出的保護措施。
借助com.jcraft.jsch編寫一個SFTP客戶端并部署做測試對接(溫馨提示:記得需要在客戶端上做些冪等第晰,超時重連等處理)
做完連接測試接下來做加密系列操作锁孟。一般來說彬祖,我們在使用OpenPGP標準時不會從頭實現(xiàn)一遍這一套規(guī)則。我們會使用GnuPG來做密鑰管理品抽,使用bouncycastle來實現(xiàn)openpgp加密規(guī)范储笑。
首先mac終端上使用命令
brew install gnupg
安裝GPG工具(GnuPG簡稱GPG)-
因為雙方都需要做加密,需要跟對方交換密鑰圆恤,假設雙方分別叫A和B,
A這邊用B的公鑰加密突倍,用A的私鑰解密;
同樣盆昙,B這邊用A的公鑰加密羽历,B的私鑰解密
首先生成自己的一對密鑰(不要嫌麻煩,這些是必要的)
gpg --full-generate-key
生成密鑰.png
解釋一下上面一些概念淡喜,估計大伙看了會有點疑問
E5834DCB37EED9CD59F2D6673B7411F1C006EA29是密鑰的id,這個id可以用來編輯密鑰秕磷,可以給別人導入你的密鑰;
密鑰有限期炼团,顧名思義澎嚣,到期后過期密鑰需要替換或者通過
gpg --edit-key [Key ID]
命令延期(記得管理好自己的密鑰期限)-
密鑰類型的1,2是帶有子密鑰結構的瘟芝,一般默認會選第一種易桃,主密鑰和子密鑰都使用RSA算法,其中主密鑰做簽名認證锌俱,子密鑰做加密晤郑。但有些企業(yè)會要求無子密鑰,那就只能選3嚼鹉,4了贩汉。我們可以看看剛剛生產(chǎn)的1類型(RSA和RSA)密鑰。
gpg --edit-key [Key ID]
SC代表簽名和認證锚赤,E代表加密匹舞,ssb代表secret sub key,sec代表secret key线脚。
好了赐稽,密鑰生成完了以后,可以使用兩種方式來把公鑰給對方
6.1. 使用命令gpg --import [key id]
來讓對方導入我們生成的公鑰
6.2. 使用命令gpg --armor --output [public key name] --export [KEY ID]
把公鑰文件導出來(--armor參數(shù)是使文件以ASCII碼形式展現(xiàn)浑侥,如果忽略這個參數(shù)生成的是2進制文件)姊舵,然后發(fā)給對方
這兩種方式都要注意的是人工驗證KEY ID是否是真的是對方,最好見面問寓落,不能見面也可以打電話括丁。(自己思考為啥要這個動作)。
最后用同樣的方法把對方生成的密鑰導入就結束密鑰交換流程了伶选。
-
最后,得到密鑰了,再通過bouncy castle編寫一個加密赖歌,解密,簽名抽诉,認證的算法,然后跟對方測試驗證就完成了吐绵。
這里的bouncy castle使用方法不詳細講迹淌,代碼也不打算公開先,網(wǎng)上可以搜到demo己单;因為這個包文檔很不全唉窃,需要很大程度低靠自己理解(可參考上面OPENPGP的原理流程來輔助理解),之后有機會會出一個專門的篇幅來解讀bouncy castle的openpgp實現(xiàn)原理纹笼。