也說Hadoop敏感信息加密方案的嘗試(上) 原

#前言 每個公司都會遇到數據安全性的問題,數據在當下甚至未來,其安全性只會越來越重要。而在大數據的環境下,數據多以集羣存儲,量大而複雜是大數據的一個重要特徵,在這種情況下,數據的安全性方案該如何設計才能保證數據安全,同時保證集羣負載小,對外透明度高呢?

目前的集羣狀況是上了Kerberos,我想這是集羣安全性的一個必要前提,即使你說集羣位於公司內網,但是沒上Kerberos談安全和權限就沒什麼卵用。其次集羣上了Sentry,這是對權限管理的進一步加強,對Hive表可控制權限到列,對HDFS文件也可做具體權限控制。

一個公司大量的數據可能都是行爲數據,所以並沒有太多需要保密的處理,需要加密的往往是敏感數據,比如身份證信息,某些ID等。HDFS在文件層面提供了透明加密機制,配置好後可創建加密區,通過API又可把數據從加密區恢復出來,在DataNode端直接查看Block塊,數據是加密的,保證了安全性。但是它針對所有數據加密,雖說對上層透明,安全好用,但是對集羣壓力大,很多不需要加密的數據做加密處理,是一種資源浪費。

這裏想要提到的方案就是針對Hive表字段加密,一個表具備幾十個字段,需要做保護的可能只有其中一兩個,通過提供一個UDF,在數據入Hive表時,在需要加密的字段上調用,UDF對上層透明,可實現數據保護。在數據需要解密的時候,同樣提供UDF用於解密,調用即可得到明文。

#方案 上面的一個想法,造就了很多種不同方案,一個個嘗試,一個個排除,最後發現回到原點,只有一種方案合適。嘗試過的若干方案分兩大類,按處理類型分爲數據散列處理AES對稱加密

##數據散列處理 散列處理是指Hash一類的處理,算法有md5, sha1, sha-256以及更高位數的散列算法。它有個顯著特徵是雪崩效應,原文稍有改變,算出來的值就會完全不同。Hash是一種摘要算法,同一種hash算法,針對不同的輸入,輸出的位數是固定的,所以hash存在碰撞的可能。在用於數據加密的時候,如果存在hash碰撞,就會導致數據丟失,一個明文會覆蓋另一個明文。所以通過hash處理的話,就必須通過無碰撞碰撞概率在可接受範圍內的驗證,同時敏感字段可能因爲業務需要而在特定場景下需要還原,而hash不可逆,所以這種方案必須得做好明密文映射表

hash碰撞的概率可參考下圖: hash碰撞的概率

對於字段的結構,如果我們很清楚並且在可窮舉範圍內的話,我們可以選擇一個鹽,然後窮舉所有可能,從而可以找到確定無碰撞的鹽。對於無法窮舉的,只能驗證一下碰撞概率是否在可接受範圍內。

###把散列算法布成服務,對外提供明密文訪問的API 優勢在於:

  1. 服務做Hash計算,有碰撞則換鹽,可避免碰撞產生
  2. 密文請求的同時把映射表做完,不用單起服務做映射表,不會漏掉明文
  3. 散列只用做一次,減少計算開銷

劣勢在於:

  1. 每一行都要請求,服務併發太大,需要設計得好,緩存服務做的非常好
  2. 服務單點,一旦宕機所有數據都沒法跑
  3. 最重要的一點,安全和權限管理不好做,一旦API泄露,就可以由明文撞出密文

###在UDF裏做散列,控制鹽的權限,然後單獨起服務做映射表 一個字段對應一個鹽,控制好鹽的權限,比如把鹽存入Hive表裏,借用Sentry的權限控制實現表列的權限控制。在UDF裏獲取鹽,然後實現加密,但是解密需要從映射表來,所以得專門起服務做映射表。

優勢在於:

  1. 可以避免高併發,沒有單點故障
  2. 鹽值可實現權限管理,安全性可以得到保障

劣勢在於:

  1. 散列碰撞可能存在,數據可能丟失,需驗證概率大小是否在可接受範圍內
  2. 映射表需單獨維護,必須在所有數據入庫之前先跑,還要做去重等處理
  3. 映射表的維護要隨業務而變,有新的數據源接入就要更改服務,極其麻煩

以上是散列處理的兩種具體方案,由於散列的不可逆,導致如果需要還原明文,它的代價就非常大,映射表的維護是極其麻煩的事情,而且備份和安全性都不好處理。但如果企業不要求還原,那這裏的第二種方案不失爲一個好的方案。

##AES對稱加密 AES纔是真正的加密算法,上述的散列只能是一種摘要算法,而非加密算法。

AES加密:一種對稱加密的算法,加密和解密使用同一種祕鑰。加密的過程是向量的移位運算過程,它會對輸入進行16字節的劃分,然後進行移位運算,解密則是其反向過程。

AES加密有很多不同的模式,不同模式的運算方式不一樣,有的模式還需要初始化向量。其中CFBOFB模式不會處理填充情況(即輸入不滿16字節的,是否填充爲16字節)。所以AES的輸出長度與輸入長度是相關的,與祕鑰長度無關。

規律:輸入是16*n字節,沒有填充的情況下,輸出和輸入長度相同,有填充的情況下,輸出爲16*(n+1)。如果輸入不是 16字節的整數倍,是16*n16*(n+1)的區間內,沒有填充的情況下,輸出和輸入長度相同,有填充情況下,輸出長度是16*(n+1)

在JDK裏默認有AES 128位的加解密API,如果需要更高位數的,就需要下載額外的jar包,但一般128位日常加密就夠使了。

在AES加密裏,我們可以把加密解密放在UDF裏,只需做好祕鑰Key的管理即可。

前期有個誤解,以爲Sentry能控制UDF的使用權限,最後驗證發現,Sentry其實只能控制UDF的創建權限,而不能控制使用權限。一個普通用戶想要有UDF的創建權限,則必須給他關聯上hive.aux.jars.path裏配置的目錄下的jar包的ALL權限。

所以權限的控制只能放在Key的權限上,所有能取到Key的人,就具備了這個key所對應字段的加解密權限。前期以爲能對UDF和Key都做權限控制,這樣分兩級權限,把祕鑰在後端做的更透明,可以加強權限的管理,有些人無需解密操作,就可以把解密的UDF不對他開放。結果發現只是我們自己樂了一下~

在AES加解密的祕鑰控制上,又有幾種不同的細分方案。針對祕鑰的存儲,分爲Hive表存儲KMS祕鑰管理服務存儲

###Hive表存儲祕鑰 這種方式比較簡單(事實證明簡單粗暴的往往是最好用的~),很好理解。通過創建多個列,不同列對應不同字段的祕鑰,利用Sentry把權限控制到列,即把權限控制到了字段key的級別。

###KMS祕鑰管理服務 它是Hadoop本身提供的一個祕鑰管理組件,用於HDFS文件加密的,我們可以利用它作爲我們祕鑰管理的服務,它支持Kerberos認證和SSL,同時對權限可控制到具體key,權限管理上非常方便。

關於KMS祕鑰管理服務,這裏有單獨的一篇文章做介紹,KMS祕鑰管理服務

未完待續,下篇博客見 也說Hadoop敏感信息加密方案嘗試(下)

歡迎小主們轉載,但請註明出處:https://my.oschina.net/u/2539801/blog/808054

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章