什么是代碼加密?基於雲效 Codeup的代碼倉庫加密是如何實現的?在互聯網快速發展的時代,代碼是企業最核心的資產,代碼安全也是首當其沖;為了保護企業代碼安全,各公司使出的手段也是五花八門,但未必安全,而雲端加密代碼服務是阿里雲 雲效團隊的自研產品,是目前國內率先支持代碼加密的托管服務,能夠有效的阻斷代碼對運維人員的可見性,從而消除用戶上雲的顧慮。
本篇文章為大家揭秘業界創新的代碼倉庫加密技術背后的知識。

01 / 什么是代碼加密?
雲端加密代碼服務是雲效團隊的自研產品,是目前
國內率先支持代碼加密的托管服務,也是目前世界范圍內率先基於原生Git實現加密方案的代碼托管服務。
通過在雲端對托管在雲效 Codeup 的代碼庫進行落盤加密,可以有效避免數據擁有者之外的人接觸到用戶的明文數據,避免數據在雲端發生泄露。同時,代碼加密過程對用戶完全透明,用戶可以使用任意官方Git端(包括但不限於Git、JGit、libgit2等)來訪問Codeup上的代碼倉庫。
02 / Linux社區重大安全性事件回顧
2011年8月底,用於維護和分發 Linux 操作系統的多台服務器感染了惡意軟件,這些惡意軟件非常厲害,可以獲取 root 的訪問權限,修改其上的系統軟件以及登錄密碼。但社區的維護者稱,維護 linux 的源代碼,是未受到漏洞影響的。
這是為什么呢?因為他們使用了 Git 進行代碼維護,對於 linux 內核代碼將近40000個文件來說,每個文件都做了 hash 來確保唯一性,因此很難在不引起注意情況下,更改舊的版本。

雖然Git可以解決開源社區關心的源碼篡改問題,卻解決不了企業擔心的數據泄露問題。而對於企業級代碼托管來說,今天所面臨的問題不但有數據安全、還有可靠性及成本問題。
當企業規模較小時,對可靠性要求也不高,一個自建的代碼托管服務似乎就能滿足需求。但隨着規模不斷擴大,代碼量不斷增加,可能需要更好的服務器配置,才能滿足多人協作的需求,甚至還需要投入專人維護來保證可靠性,這時就不得不思考成本的問題。
而雲代碼托管服務,有着比自建代碼托管服務更高的可靠性及更低的成本,但相比自建代碼托管服務而言,由於其並不開放底層存儲的直接訪問,間接造成了用戶不可控的安全心理。
而代碼加密技術,正是通過將底層存儲的不可控變為近完全可控,解決用戶代碼上雲的顧慮。
03 / 自建真的比上雲更安全么?
在回答這個問題之前,讓我們一起來了解一些背景知識——Git的存儲結構。

當我們使用Git進行代碼提交時,最先接觸到的便是提交記錄及分支。分支或者標簽,可以統稱為引用。它們存儲在以路徑名作為引用名,以及對應版本hash作為內容的單個文件中。由於分支名通常與業務無關,所以可以認為,其中不包含敏感數據的。
除了提交記錄commit之外,我們的代碼文件被存儲到blob對象,文件名及目錄等信息,存儲到tree對象,帶有額外的信息的標簽被存儲到tag對象。
對象是Git中存儲數據的基本單元。通常情況下,對象存儲在以內容hash值命名的單個文件中,我們稱之為松散對象。而通過執行gc(也就是垃圾回收)之后,這些對象就會被打包到一起,生成一個打包文件packfile。代碼內容及文件名,都存儲在blob及tree對象當中,所以可以認為,對象中是包含用戶的代碼內容數據,也就是包含敏感數據的。
Git中的對象存儲,為了降低磁盤占用,會通過zlib進行一次數據的壓縮。換句話說,只需通過解壓縮就可以獲取到數據內容,所以可以認為是明文存儲。也就是說,任意可以接觸到存儲的人,都可以查看存儲上的代碼數據。
明文存儲引發的信任問題
回答前面提出的問題,正是由於Git代碼非安全存儲的特點,自建的代碼托管服務,既要防范來自外部的一些攻擊風險,還要防范內鬼,因為通常企業代碼數據泄露是從內部發生。

而對於雲代碼托管服務而言,我們可以借助阿里雲安全,有效避免來自外部的黑客攻擊風險,那么,如何解決用戶對雲代碼托管服務的信任問題,讓代碼對運維人員不可見呢?
引入代碼加密技術,通過使用用戶的密鑰,加密雲端托管的代碼數據,既增加了靜態存儲數據的安全性,又可以阻斷代碼對運維人員的可見性,從而消除用戶上雲的顧慮。
04 / 代碼加密技術揭秘
把它分化三個問題去解決:
1.密鑰管理
使用一個安全合規的方式托管密鑰,密鑰存儲安全,才能保證加密安全。這個可以借助阿里雲的密鑰管理服務KMS。
2.密鑰使用
Git是一個計算密集型的服務,如果直接使用密鑰管理服務的加解密能力,那么這個性能是難以接受的。 那這里還有什么方案呢?我們可以使用信封加密技術。顧名思義,我們可以使用數據密鑰,來對我們明文的代碼數據進行加密,使用數字信封技術,保證密鑰保存、傳輸、使用過程的安全性。由於我們只存儲密文的數據密鑰及密文的代碼數據,必須通過用戶授權,才能完成運行態的代碼數據解密。而處於靜態存儲的代碼數據,則無法被運維人員獲取。
3.基於原生Git的加密實現
在原生Git的基礎上,通過增加代碼加密補丁,以在實現加密的能力同時,最大程度地獲取到原生Git帶來的各種優勢。
原生Git是如圖所示的這樣一個自上而下的分層架構,和我們常見的應用架構非常類似。

最上層是展現層,包含紛繁復雜的命令行入口,直接暴露給應用服務進行調用。 中間是業務處理層,從數據內容角度,可以分為引用操作及對象操作。通過增加一個加解密的模塊,在內存中進行數據加密,將密文數據寫入磁盤,從而保證靜態數據的安全性。 為了獲取最高的性能,僅選擇與用戶代碼資產相關的對象數據進行加密存儲,而對於引用列表及對象索引等數據,仍維持明文存儲。利用硬件加速,代碼加密的額外性能損耗控制在10%左右,在用戶使用過程中幾乎無感。本地Git代碼加密演示
事先准備好一個配置了代碼加密的的倉庫。這個倉庫是空的。
我們向里面添加一個文件。
通過hexdump -C查看這個文件的二進制內容,我們可以發現,它是以首字節78 01起始,這是一個典型的經過zlib壓縮后的文件頭。

接下來,我們開啟加密的開關,通過git commit創建一個加密的提交記錄。再次查看保存的提交記錄二進制內容,發現這時創建的對象數據不再以78 01開始,而是以我們指定的加密標記位開始。
注意,受時間關系,這里我們未進行同一個對象非加密與非加密狀態下的直接對比,而是以文件頭是否變化來判斷加密與否。
在完成松散對象加密之后,我們可以通過git gc ,將松散對象轉換為打包對象,再看一下打包對象會發生什么樣的變化呢?由圖中我們可以發現,加密后的打包文件包頭版本中,不再是原有的00 00 00 02,而是增加了特定標識的82 00 00 02,並且包頭也由原有的12字節擴展為24字節,增加了12字節的NONCE用於增加安全性。

那么,當我們移除密鑰配置之后,是否可以繼續訪問這個倉庫呢?
當我們移除密鑰之后,由於缺少密鑰,當我們嘗試通過git show HEAD 查看當前版本時,會得到一個錯誤信息,提示未提供密鑰。
這個錯誤是基於我們在原生Git基礎上,定制化了代碼加密能力補丁,若是沒有這個補丁,會有什么樣的表現呢?
針對加密的打包文件packfile,會提示當前版本較低,請升級Git版本;若針對松散對象,則提示文件頭不正確,因為不是一個zlib的壓縮頭。

所以別再自建的代碼托管服務,既要防范來自外部的一些攻擊風險,還要防范內鬼,因為通常企業代碼數據泄露是從內部發生。我們可以借助阿里雲安全,有效避免來自外部的黑客攻擊風險,雲效代碼管理Codeup,10萬企業都在用的代碼管理平台,能夠全方位保護企業代碼資產,幫助企業實現安全、穩定、高效的代碼托管和研發管理。
關於我們
更多關於雲效DevOps的干貨及雲效動態,可微信搜索關注【雲效】公眾號~
彩蛋:公眾號后台回復【指南】,可獲得《阿里巴巴DevOps實踐指南》&《10倍研發效能提升案例集》~
看完覺得對您有所幫助別忘記點贊、收藏和關注呦