2011-08-08 63 views
33

根據MSDN SecureString的內容是加密爲了更加安全,因此如果程序交換到磁盤時,字符串內容不能被嗅探。SecureString如何「加密」並仍然可用?

我想知道這樣的加密可能性如何?該算法將是固定的,因此可以是已知的或可抵扣的(例如七種工業算法中廣泛使用的算法之一),並且程序中必須有一個關鍵字。所以攻擊者可以獲取加密的字符串,獲取密鑰並解密數據。

這樣的加密如何有用?

+0

它並沒有說它是安全的,只是*更安全* –

+0

@Mark Peters:這就是爲什麼我說*額外的安全*。 – sharptooth

+0

你可以用crypto.SE來問這個問題 - 非常有話題 –

回答

15

我從一篇關於DPAPI的文章引用,它是用來派生密鑰的。這應該回答你關於SecureString的大多數問題。

是的,SecureString有缺點,並不完全安全,有辦法訪問數據,例如,注入Hawkeye到進程中提到MSDN作爲一種方式來提取SecureString。我沒有親自驗證這一說法。

DAPI密鑰管理

DAPI是基於對稱加密技術中,這意味着它使用相同的密鑰來加密和解密數據。在介紹如何使用DAPI的例子之前,有必要介紹DAPI如何管理密鑰。大多數情況下,DAPI密鑰管理過程是不可見的,您通常不需要擔心,這是DAPI是一種好方法的主要原因。

在介紹中我寫道,主密鑰是從用戶的登錄密碼生成的。這不是完整的圖片。實際發生的事情是,Windows使用用戶的登錄密碼來生成主密鑰。此主密鑰使用用戶的密碼進行保護,然後與用戶的配置文件一起存儲。這個主密鑰然後被用來派生許多其他密鑰,並且這些密鑰用於保護數據。

Windows爲什麼會這樣做是因爲它允許應用程序向生成個別密鑰的過程中添加額外的信息,稱爲熵。您會看到,在用戶的登錄帳戶下運行的每個應用程序是否使用了相同的密鑰,那麼每個應用程序都可以解除DAPI保護的數據的保護。有時您可能希望應用程序能夠共享受DAPI保護的數據;但是,有時你不會。通過讓應用程序將熵貢獻給密鑰的生成,那麼該密鑰變爲應用程序特定的,並且任何受該應用程序保護的數據如果知道熵,則只能再次不受保護。

儘管生成主密鑰,然後使用該主密鑰生成其他密鑰以進行實際加密,但看起來像是一種冗長的方法,但確實有一個主要優勢。由於用戶密碼保護的主密鑰和用於保護數據的實際密鑰之間存在額外的抽象級別,這意味着當用戶更改其密碼時,只需要重新保護主密鑰;所有受保護的數據都不需要重新保護。由於主密鑰的尺寸比數據小得多,因此節省了顯着的性能。

當用戶的密碼發生變化時,當然會生成一個新的主密鑰。這個新的主密鑰然後用於生成新的個體密鑰。但是,由於所有以前生成的單個密鑰都是從舊的主密鑰導出的,因此Windows需要存儲之前所有的主密鑰。 Windows永遠不會忘記主密鑰,所有受保護的數據都會標記一個GUID,以指示哪個主密鑰用於保護數據。因此,就適應性而言,DAPI能夠應對用戶密碼的變化,同時確保a)受保護的數據不需要被重新保護,以及b)用於保護數據的密鑰仍然可用,以及c) )它會自動爲你做這一切。

除非計算機是域的成員DAPI只能在用於保護它的同一臺計算機上提供未受保護的數據。

除了允許用戶級別的保護,由於主密鑰基於用戶密碼,並且受保護的數據對於一個用戶不會受到其他用戶的保護,所以DAPI還提供機器級保護,因爲主密鑰基於機器具體信息。機器級主密鑰允許應用程序存儲受保護的數據,以便應用程序的所有用戶都可以不受保護。已經描述的過程中唯一的區別是主密鑰是從機器特定的信息生成的,而不是用戶特定的信息。

+1

+1讓我們知道Hawkeye –

+0

我認爲從發佈的文章中拿掉的關鍵是「大多數情況下DAPI密鑰管理過程是不可見的你通常不需要擔心「。就在那裏,我傾向於定製解決方案。足夠好的保護並不總是,很好,足夠好。 –

+0

注意:截至05/18/2017,文章鏈接返回404:http://www.dsmyth.net/wiki/Print.aspx?Page=StudyNotes_DAPI – iokevins

11

我看了一下它的代碼,它使用Windows的advapi32來做它的骯髒的工作。所以密鑰不會存儲在應用程序的內存中。

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
internal static int SystemFunction040([In, Out] SafeBSTRHandle pDataIn, [In] uint cbDataIn, [In] uint dwFlag) 

這是更好地爲RtlEncryptMemory.

它進行解密RtlDecryptMemorySystemFunction041)。

我確定編譯器也會對SecurityCriticalAttribute做些什麼。

編輯這反映了使用4.0。其他版本可能與不同。

2

通過DPAPI的魔力:

該類存儲使用受保護的內存模型數據保護API(DPAPI)其數據。換句話說,數據總是以加密的形式存儲在SecureString中。加密密鑰由本地安全授權子系統(LSASS.EXE)管理,通過DPAPI可以通過進程間通信解密數據。

7

正如其他人已經回答,SecureString的內容使用DPAPI進行加密,因此密鑰不存儲在您的應用程序中,它們是操作系統的一部分。我不是100%肯定的,但我會假設SecureString使用用戶特定的密鑰,以便即使另一個進程訪問該內存塊,它也必須在相同的憑據下運行,以便簡單解密使用DPAPI的內容。即使不是,機器密鑰(理論上)也可以防止字符串在傳輸到另一個系統時被輕易解密。

SecureString更重要的是當你使用它時如何&。它應該用於存儲需要在「擴展」時間段內保留在內存中的字符串數據,但是這些數據在解密形式中並不經常需要。在某些時候,你將不得不將它解密爲普通的舊版本System.StringSystem.Char[]。這是記憶中最脆弱的時候。如果你經常這樣做,那麼你有多個解密字符串的副本在內存中等待收集。作爲一般規則,如果我讀取我需要保留的經常使用(例如,PayPal或Amazon API交互)的加密數據(例如登錄憑證),那麼我將這些憑證存儲/緩存爲SecureString,然後根據需要對其進行解密,只需足夠長的時間以便進行Web服務調用,並確保任何解密副本的生命週期僅爲幾行代碼。

使用關鍵塊或類似的方式向CLR提示,在解密的字符串正在使用時不應該進行上下文切換,以提高在緩存內容之前收集任何解密的副本的機會,或者交換。

相關問題