Windows Azure 中的加密服務和數據的云安全
概述:許多早期云用戶的云平臺都存在安全問題。我們來重溫一下 Windows Azure中的某些加密服務和提供程序,以及云中應用程序的某些安全隱患。
Windows Azure 平臺的許多早期采用者仍對平臺安全及其加密支持存在大量疑問。在此,我將介紹 Windows Azure 平臺內加密和相關安全的一些基本概念。詳細闡述本主題可能需要很大的篇幅,因此我只打算說明并重溫一下 Windows Azure 中的某些加密服務和提供程序。任何向 Windows Azure 的過渡也會存在一些安全隱患。
對于任何新平臺或服務交付方法,您都會面臨新的挑戰。另外還要提醒您,一些典型問題仍然存在,甚至您過去使用的一些相同的解決方案仍將有效。任何應用程序工程師或設計人員都應仔細思考本主題,因為它與您可能存儲及需要保留的數據類型有關。將此方法與系統化方法相結合,會為您和您的客戶提供優質服務。
因此,為什么我會認為開發人員社區中需要此信息呢?在過去的幾個月中,我發現社區站點中有關 Azure 基本安全性的文章越來越多。Microsoft 建議將加密作為保護 Azure 項目的應用層數據的一部分。但是,構建 Windows Azure 平臺的產品設計人員和開發人員需要正確理解加密和 .NET 安全模型。
我發現這么一件事:特定于加密服務和密鑰存儲的文章的百分比不斷增加。對于 Windows Azure Storage 服務來說,更是如此。這勾起了我的好奇心,我發現這是一個值得深入討論的話題。
在撰寫本文的過程中,我將大量使用加密服務提供程序 (CSP),在該程序中可實施系統編程接口中的加密標準、算法和函數。出于本文的目的,我將使用由 Rijndael 加密類提供的對稱加密算法。
加密基礎知識
Windows Azure SDK 擴展了核心 .NET 庫,允許開發人員集成并使用由 Windows Azure 提供的服務。對 CSP 的訪問并不僅限于在 Windows Azure 項目和服務中進行。這意味著您的許多與加密和解密數據有關的開發將與您習慣使用的程序集保持一致。但是,基本體系結構有一些更改,即加密數據的時間或位置及保存密鑰的位置和方式的問題。本文稍后將討論一些關鍵數據和機密數據持久性。 您還能夠訪問 Windows Azure 中加密哈希功能的完整陣列,例如 MD5 和 SHA。以上內容對增強任何系統的安全性(如檢測重復的數據、哈希表索引、消息簽名和密碼驗證等)至關重要。
一致建議始終不創建您自己的加密算法或使用專有加密算法。.NET CSP 中提供的算法已得到證實并經過測試,已公開很多年供備份。使用 XOR 創建您自己的加密過程并不相同,并且不提供相同級別的數據安全性。
第二個建議是使用 RNGCryptoServiceProvider 類生成隨機數字。這可以確保您的應用程序生成的隨機數字始終具有極高級別的平均信息量,從而在模式上難以猜測。
以下代碼實現了單個靜態成員,該成員將返回隨機的 32 位 int 值且滿足加密學角度上的安全需要。通過使用 Cryptography 命名空間中提供的 RNGCryptoServiceProvider 中的字節生成器可以實現這一點:
public static int GenerateRandomNumber() {
byte[] GeneratedBytes = new byte[4];
RNGCryptoServiceProvider CSP = new RNGCryptoServiceProvider();
CSP.GetBytes(GeneratedBytes);
return BitConverter.ToInt32(GeneratedBytes, 0);
}
圖 1 顯示了在 Windows Azure 平臺內部使用 CSP 的簡單示例。公開了三個公共成員,用于在任何 Windows Azure 應用程序中使用。第一個成員接受二進制密鑰和初始化向量 (IV) 及未加密數據的二進制緩沖區并返回其加密的等效方法。第二個成員通過解密數據執行相反的操作。第三個成員返回為該數據計算出的哈希值。在此請注意,我使用 Rijndael CSP 對提供程序進行托管訪問。我還在二進制緩沖區中存儲數據和密鑰并在完成后進行改寫。稍后將在討論不變性時介紹本主題。 圖 1 簡單加密
public static byte[] SampleEncrypt(byte[] dataBuffer,
byte[] Key, byte[] IV) {
MemoryStream InMemory = new MemoryStream();
Rijndael SymetricAlgorithm = Rijndael.Create();
SymetricAlgorithm.Key = Key;
SymetricAlgorithm.IV = IV;
CryptoStream EncryptionStream = new CryptoStream(InMemory,
SymetricAlgorithm.CreateEncryptor(), CryptoStreamMode.Write);
EncryptionStream.Write(dataBuffer, 0, dataBuffer.Length);
EncryptionStream.Close();
byte[] ReturnBuffer = InMemory.ToArray();
return ReturnBuffer;
}
這是加密數據并以字節數組形式返回加密結果的最簡單示例。這不是可以在未進行所有適當的安全性分析的情況下在安全環境中使用的代碼,只是一個示例。
圖 2 中的示例幾乎與圖 1 中的示例具有相同的結構。在本例中,我基于相同的密鑰和 IV 解密數據,僅將加密的字節緩沖區作為參數使用。這里唯一真正的差別就是當創建加密流時,我指定創建對稱解密器而不是先前創建的加密器。
圖 2 簡單解密
public static byte[] SampleDecrypt(byte[] dataBuffer,
byte[] Key, byte[] IV) {
MemoryStream InMemory = new MemoryStream();
Rijndael SymetricAlgorithm = Rijndael.Create();
SymetricAlgorithm.Key = Key;
SymetricAlgorithm.IV = IV;
CryptoStream EncryptionStream = new CryptoStream(InMemory,
SymetricAlgorithm.CreateDecryptor(), CryptoStreamMode.Write);
EncryptionStream.Write(dataBuffer, 0, dataBuffer.Length);
EncryptionStream.Close();
byte[] ReturnBuffer = InMemory.ToArray();
return ReturnBuffer;
}密鑰存儲和持久性
同應用程序或企業層次的任何加密策略一樣,加密和解密基礎結構遠未成功。實際問題在于密鑰存儲和密鑰持久性。由加密數據提供的數據安全僅取決于使用的密鑰,此問題比人們最初想到的要難得多。我所介紹的系統已經在各處存儲了加密密鑰,從直接存儲在源代碼中到存儲在巧妙命名的文本文件,以及存儲在難以找到的目錄中的平面文件中。
考慮在云環境中存儲和保留密鑰的位置時,密鑰持久性的重要問題浮現出來。某些人表示擔心通過在云中保存密鑰,您會受到來自云本身的安全威脅。也就是說,如果某人對您的數據具有物理訪問權限,默認情況下可能不會加密磁盤中存儲的數據(對于 Windows Azure 也是如此)。考慮到 SQL Azure 尚未支持加密,這成為在規劃和設計解決方案時考慮的安全決策。與任何安全性實現一樣,必須對風險進行度量、權衡和緩解。
但這并不意味著云平臺(通常情況下)和 Windows Azure(特別情況下)在本質上不安全。可能為您提供的其他選項呢?
現在需要注意的是,應用程序始終不應將由 Windows Azure 提供的任何密鑰用作加密數據的密鑰。示例如下:由 Windows Azure 提供用于存儲服務的密鑰。這些密鑰被配置為可以輕松旋轉,以提高安全性或防止某種原因遭到破壞。換句話說,以后可能不存在密鑰,并且可能分布極其廣泛。
在 Windows Azure Storage 服務中存儲您自己的密鑰庫是一個保存某些機密信息的好方法,因為您可以使用在多租戶環境中保證安全的數據并使用您自己的存儲密鑰保證安全。這不同于將存儲密鑰用作您的加密密鑰。實際上,如同任何其他存儲文件一樣,可使用存儲服務密鑰訪問密鑰庫。實現非常簡單。例如,假設您想將自己的密鑰庫作為簡單文本文件來實現,以保留某些機密信息。相對于隊列或表存儲服務而言,最好作為數據存儲在 blob 服務 API 中。存儲服務的 blob 區域是二進制音頻和圖像甚至文本文件等數據的最佳位置。服務的隊列部分著重介紹了保護不會長期保留的小型數據對象的消息傳送的安全。表存儲系統非常適合于需要在特定部分保留和訪問的結構化數據和信息,這與數據庫中的關系數據完全相同。
首先,將密鑰保存在 CSP 密鑰容器中。這是用于存儲公鑰的最佳選項,不具有對該服務器的物理訪問權限,很難對該密鑰進行檢索。對于 Windows Azure(其中,應用程序和數據的位置很抽象),這將使查找和檢索以這種方式存儲的公鑰極其困難。創建密鑰存儲容器非常簡單;下面是使用創建密鑰的 RSA 提供程序的一個示例。如果密鑰容器已存在,會自動將其密鑰加載到該提供程序:
CspParameters CspParam = new CspParameters();
CspParam.KeyContainerName = "SampleContainerName";
RSACryptoServiceProvider RSAProvider = new
RSACryptoServiceProvider(CspParam);
此外,還提供了您可以根據需要考慮的其他選項。例如,您可以使用特定標記為創建該容器的用戶保證密鑰的安全。可使用 CspParameters 標記成員完成此操作:
CspParam.Flags = CspProviderFlags.UseUserProtectedKey;
現在,使用 Windows Azure 存儲密鑰創建一個 blob API 請求。該請求本身要求使用簽名字符串和正確的請求標題。正確的標題格式為:
Authorization="[SharedKey|SharedKeyLite]
在本示例中,我希望最大程度地提高保留的機密數據的安全性,因此我將使用 SharedKey 授權方法。此標題的簽名部分是一個基于哈希的身份驗證代碼,由 SHA256 算法和您的存儲密鑰針對簽名中的數據生成。然后,此哈希被編碼為 base64 字符串。示例簽名可能如下所示:
"PUT\n\ntext/plain; charset=UTF-8\n\nx-ms-Date:Fri, 12 Sep 2009 22:33:41 GMT\nx-ms-meta-m1:v1\nx-ms-meta-m2:v2\n/exampleaccount/storageclientcontainer/keys.txt"
如前所述,然后會生成 base64 編碼哈希并將其用作標題中的簽名。然后,只有以下人員才能訪問該密鑰文件:其應用程序在 Windows Azure 云中的應用程序空間中運行并有權訪問您的存儲密鑰。因此,借助密鑰持久性,您既可以管理 Windows Azure 框架外部的密鑰,還可以管理云本身內部的密鑰。
密鑰和安全威脅
至少值得簡要介紹的一項是密鑰安全性。這與如何保留和存儲密鑰略有不同。密鑰本身實質上是具有極高級別的平均信息量(也就是極高級別的隨機性)的字符串。實際上,這可能會導致查找系統中的密鑰的常見的攻擊進程。例如,如果轉儲硬盤上的內存或數據區域,則具有極高平均信息量的區域是您開始查找密鑰的最佳位置。
除了基于應用程序的需要選擇很好的安全實踐和保護數據的安全之外,您還有其他辦法保護自身的安全嗎?首先,始終假定您解密、加密和保護數據安全所使用的過程為所有攻擊者所熟知。記住這一點后,確保定期交替使用您的密鑰并保證其安全。僅為必須利用這些密鑰的人員提供密鑰,并盡量減少暴露不受控制的密鑰的機會。
最后,花時間將您的安全和不安全數據流繪制成圖表。請看一下您的數據流往的位置和流去途徑、存儲機密的位置以及特別是數據跨越邊界(例如,公共網絡和專用網絡)的位置。這將使您很好地了解公開數據的位置并允許您通過直接遷移風險的計劃來應對這些風險。
曾有人問過我一個相關問題:Windows Azure 是否支持 SSL。簡短的回答是“是”。Windows Azure 對于基于 Web 的服務和不支持 SSl 的應用程序來說可能不是一個功能非常強大的云平臺。
使用 SQL Azure 進行加密
SQL Server 2008 的發布引入了一個新功能:透明數據加密 (TDE)。SQL Server 第一次可以僅憑比 SQL Server 2005 中提供的有限加密稍多一點的工作完全加密其數據。但是,SQL Azure 存儲的初始版本尚不支持數據庫級加密,盡管這是未來版本中考慮的功能。應注意的是,SQL Azure 僅可通過端口 1433 和 TCP 連接使用;目前還無法對其他端口公開。
盡管此功能尚未集成到 Windows Azure 中,但是開發人員或設計人員應牢記 SQL Azure 的幾個安全功能。首先,SQL Azure 支持使用表格格式數據流 (TDS)。這表示,大多數情況下,您可以像以前一樣連接數據庫并與該數據庫進行交互。絕對值得考慮利用 ADO.NET 加密和受信任的服務器證書,特別是當從云外部訪問您的 SQL Azure 數據庫時。
正確組合中的連接屬性 Encrypt=True 和 TrustServerCertificate = False 將確保數據傳輸的安全性并幫助防止中間人攻擊。這也是連接到 SQL Azure 的要求 — 您無法連接到 SQL Azure,除非已啟用連接級別的加密。
您應當熟悉的 SQL Azure 的第二個安全功能是 SQL Azure 防火墻。這將是使用過本地軟件防火墻甚至是 SQL Server 安全外圍應用工具集的人比較熟悉的工具。它使您能夠允許或阻止從各種源一直到特定 IP 地址或范圍的連接。可通過 SQL Azure 門戶管理 SQL Azure 防火墻或使用提供的存儲進程(如 sp_set_firewall_rule 和 sp_delete_firewall_rule)直接在主數據庫中對其進行管理。
與任何 SQL Server 實現一樣,還必須嚴格控制用戶帳戶管理。SQL Azure 中的防火墻確實是一個很好的工具,但它不應該依賴其本身。還應使用具有強密碼和使用特定權限配置的用戶帳戶來完善您的數據安全模型。
這些新工具可以使 SQL Azure 成為對基于云的應用程序非常嚴密的安全托管平臺。如果您第一次試用此服務,請記住,必須對 SQL Azure 防火墻進行初始化配置后,才可以進行連接。必須首先通過 SQL Azure Web 門戶完成此操作,但是如上所述,稍后便可直接在主數據庫中進行。
不變性和內存資源
什么是不變性?不變性在面向對象的編程中僅意味著在初始創建對象后無法修改其狀態。Microsoft .NET Framework 中的一個具體示例是字符串類。在代碼中更改了字符串的值后,只需棄用內存中的原始字符串并創建一個用于存儲新值的新字符串對象。
為什么從安全性的角度講這很重要?只要服務器處于聯機狀態并且不重新啟動,該字符串可以始終保留在內存中。您真的無法確定字符串將在內存中保留多長時間。這在考慮如何在代碼中存儲信息(例如,加密密鑰或加密和解密數據的副本)時非常重要。內存中數據遺跡很可能留下將秘密透露給狡猾的數據盜賊的信息。
由于此不變性,強烈建議將此類數據存儲在緩沖區(如字節數組)中。這樣,當您使用此信息完成操作后,您可以使用 0 或任何其他數據覆蓋該緩沖區來確保該數據不再位于內存中。
由于 Windows Azure 是云環境,曾經有人問我,是否仍需要考慮這些,這是一個很好的問題。仍需要考慮這些,在 Windows Azure 系統中,各個應用程序之間相互獨立。這通常會使透露內存中的數據變得異常簡單。很難將應用程序與云中的內存空間相關聯。但是,我仍建議使用此方法時要格外謹慎并在執行操作后進行清理。您可能不會始終在云中運行此段代碼,且其他漏洞可能會在將來將自身公開。不需要太擔心,保持這個習慣并堅持按此方法執行操作即可。
在圖 3 中,我已修改了生成隨機整數的上一示例。我在此處添加了一些錯誤處理以確保具有在任何情況下都始終運行的 finally 塊。我正在該塊中通過字節數組中的值執行非常簡單的迭代,使用零值覆蓋各個位置。這將覆蓋內存中的數據,因為字節數組具有可變性。我知道該數字不再包含在歸此成員執行的操作所有的內存中。可對用作項目(例如密鑰、初始化向量和加密或解密數據)的數據緩沖區的任何字節數組執行此操作。
圖 3 清除內存中的數據
public static int GenerateRandomNumber() {
byte[] GeneratedBytes = null;
try {
GeneratedBytes = new byte[4];
RNGCryptoServiceProvider CSP =
new RNGCryptoServiceProvider();
CSP.GetBytes(GeneratedBytes);
return BitConverter.ToInt32(GeneratedBytes, 0);
}
finally {
for (int x = 0; x < GeneratedBytes.Length; x++) {
GeneratedBytes[x] = 0;
}
}
}
消息隊列
Windows Azure 隊列為 Microsoft 消息隊列 (MSMQ) 服務提供了一組類似的功能,這些服務對企業 Windows 應用程序通用。Windows Azure 中的此消息隊列服務以先進先出 (FIFO) 的方式存儲基于文本的、大小不超過 8KB 的消息。這允許在不同的服務器(或像本示例這樣,在云中)運行服務和應用程序以采用安全和分發式方法進行交互并相互之間發送可操作消息。
有 5 個允許您將消息推入到隊列、查看消息、推出消息等等的基本功能。最常提出的問題是這些消息到底有多安全?
當前受 MSMQ 支持的許多功能在 Windows Azure 消息傳送 API 中還不受支持。然而,存在相似之處。對于 blob 數據服務,消息傳送服務利用相同的 REST get 和 put 界面。可在代碼中或使用 URI 和 Web 請求調用編寫和讀取消息,可使用 SSL 針對不安全網絡中的請求對該調用進行加密。這表示傳送請求的過程是經過加密的。
另外,對于 Windows Azure 中的其他存儲服務,對消息隊列的任何訪問必須利用同一存儲服務密鑰。只有有權訪問該密鑰的應用程序才能查看這些隊列或向這些隊列中添加消息。這使對這些消息的其他加密操作有點多余,除非這些消息的主體將保留安全網絡或安全應用程序空間。
總結
在目前面向服務的體系結構和解決方案的趨勢之下,很少人會想到在云應用程序中開展業務。多租戶環境(例如 Windows Azure)中的數據和服務的隔離是放眼于使用私有數據的人們最關注的問題之一。
與所有新平臺一樣,安全和加密功能將繼續在 Windows Azure 平臺中不斷改進。Microsoft 花費了巨大精力在以下方面:不僅提供安全、隔離環境,還要公開針對這些度量的公共證書所得成果。這應該會使工程師堅信,Microsoft 希望成為安全性和保持系統和應用程序為鎖定狀態方面的親密合作伙伴。
安全,特別是加密的關鍵之處在于使您的信息和過程很難訪問。我們可以將“很難”定義為超出了任何敵方在數據或進程的生命期內進入該系統的能力。然而,這是一種基于正在使用的應用程序或數據的要求的相對定義。這就是我為何在這篇文章中繼續強調需要不斷對安全和加密要求進行評估。這對確保可有效地使用這些工具以保護云系統的安全并保護數據至關重要。
評論
查看更多