System.Security.SecureString 類別

重要

建議您不要將 類別用於 SecureString .NET (Core) 上的新開發,或當您將現有的程式代碼移轉至 .NET (Core) 時。 如需詳細資訊,請參閱 不應該使用 SecureString。

本文提供此 API 參考文件的補充備註。

SecureString 是提供安全性量值的字串類型。 它會嘗試避免將潛在的敏感性字串儲存在進程記憶體中做為純文字。 不過,如需限制,請參閱 SecureString 有多安全? section.)實例的值 SecureString 會使用基礎平臺在初始化實例時或修改值時所支援的機制,自動保護的實例值。 您的應用程式可以藉由叫 MakeReadOnly 用 方法來轉譯實例不變,並防止進一步修改。

實例的最大 SecureString 長度為 65,536 個字元。

重要

此型別代表 IDisposable 介面。 當您使用 型別的實例完成時,應該直接或間接處置它。 若要直接處置型別,請呼叫其 try/catch 區塊中的 Dispose 方法。 若要間接處置它,請使用語言建構函式,例如 using (在 C# 中) 或 Using (在 Visual Basic 中)。 如需詳細資訊,請參閱 IDisposable 介面文章中的<使用實作 IDisposable 的物件>一節。

COM 看不到 類別 SecureString 及其成員。 如需詳細資訊,請參閱ComVisibleAttribute

字串與 SecureString

類別的 System.String 實例既不可變,而且不再需要時,無法以程式設計方式排程進行垃圾收集;也就是說,實例在建立后是只讀的,而且無法預測實例何時會從計算機記憶體中刪除。 因為 System.String 實例是不可變的,所以看似修改現有實例的作業實際上會建立其復本來操作。 因此,如果 String 物件包含機密資訊,例如密碼、信用卡號碼或個人資料,則因為您的應用程式無法從計算機記憶體中刪除數據,因此可能會顯示信息的風險。

SecureString對象類似於String物件,其具有文字值。 不過,物件的值 SecureString 會釘選在記憶體中,可能會使用保護機制,例如基礎操作系統所提供的加密,可以修改,直到您的應用程式將它標示為只讀為止,而且可由呼叫 方法的應用程式或 .NET 垃圾收集行程從計算機記憶體 Dispose 中刪除。

如需類別限制 SecureString 的討論,請參閱 SecureString 有多安全? 一節。

SecureString 作業

類別 SecureString 包含可讓您執行下列動作的成員:

具現化 SecureString 物件:您可以呼叫其無參數建構函式來具現化 SecureString 物件。

將字元新增至 SecureString 物件 您可以藉由呼叫 或 AppendCharInsertAt 方法,一次將單一字元新增至 SecureString 物件。

重要

SecureString不應該從 String建構 物件,因為敏感數據已經受限於不可變String類別的記憶體持續性後果。 建構 SecureString 物件的最佳方式是從非受控來源的字元,例如 Console.ReadKey 方法。

從物件移除字元 SecureString 您可以呼叫 SetAt 方法來取代個別字元、呼叫 方法移除個別字元RemoveAt,或藉由呼叫 Clear 方法移除實例中的所有字元SecureString

SecureString將物件設為唯讀 一旦您已定義物件所代表的SecureString字串,您就會呼叫其 MakeReadOnly 方法,讓字串成為唯讀的。

取得 對象的相關信息 SecureString 類別 SecureString 只有兩個成員提供字串的相關信息:其 Length 屬性,指出字串中 UTF16 編碼的程式代碼單位數目;以及 IsReadOnly,方法會指出實例是否為唯讀。

釋放配置給 實例的SecureStringIDisposable記憶體,因為 實SecureString作 介面,因此您可以呼叫 Dispose 方法來釋放其記憶體。

類別 SecureString 沒有檢查、比較或轉換 值 SecureString的成員。 缺少這類成員有助於保護實例的值免於意外或惡意暴露。 使用 類別的適當成員 System.Runtime.InteropServices.Marshal ,例如 SecureStringToBSTR 方法,來操作 物件的值 SecureString

.NET 類別庫通常會以下列方式使用 SecureString 實例:

SecureString 和 Interop

因為操作系統並不直接支援 SecureString,因此您必須將 物件的值 SecureString 轉換成必要的字串類型,才能將字串傳遞至原生方法。 類別 Marshal 有五種方法可執行這項操作:

所有這些方法都會在 Unmanaged 記憶體中建立純文字字串。 開發人員有責任在不再需要記憶體后立即清空並釋放該記憶體。 每個字串轉換和記憶體配置方法都有對應的方法,以零除並釋放配置的記憶體:

配置和轉換方法 零和免費方法
Marshal.SecureStringToBSTR Marshal.ZeroFreeBSTR
Marshal.SecureStringToCoTaskMemAnsi Marshal.ZeroFreeCoTaskMemAnsi
Marshal.SecureStringToCoTaskMemUnicode Marshal.ZeroFreeCoTaskMemUnicode
Marshal.SecureStringToGlobalAllocAnsi Marshal.ZeroFreeGlobalAllocAnsi
Marshal.SecureStringToGlobalAllocUnicode Marshal.ZeroFreeGlobalAllocUnicode

SecureString 有多安全?

正確建立時, SecureString 實例會提供比 更多的 String數據保護。 從一次字元來源建立字串時, String 會在記憶體中建立多個中繼,而 SecureString 只會建立單一實例。 物件的垃圾收集 String 不具決定性。 此外,由於未釘選其記憶體,垃圾收集行程會在移動和壓縮記憶體時製作值的其他複本 String 。 相反地,配置給 SecureString 物件的記憶體會釘選,而且呼叫 方法可以釋放 Dispose 該記憶體。

雖然儲存在 實例中的數據比儲存在 SecureString 實例中的數據 String 更安全,但實例的安全性 SecureString 有重大限制。 包括:

平台

在 Windows 作業系統上,實例的內部字元陣列內容 SecureString 會加密。 不過,無論是因為缺少 API 或金鑰管理問題,所有平臺上都無法使用加密。 由於此平臺相依性, SecureString 因此不會加密非 Windows 平臺上的內部記憶體。 這些平臺上會使用其他技術來提供額外的保護。

期間

即使實 SecureString 作能夠利用加密,指派給 實例的 SecureString 純文本可能會在各種時間公開:

  • 因為 Windows 不提供作業系統層級的安全字串實作,所以 .NET 仍必須將安全字串值轉換成其純文本表示法,才能使用它。

  • 每當安全字串的值由 或 RemoveAtAppendChar方法修改時,都必須解密(也就是轉換回純文本),修改後再加密。

  • 如果在 Interop 呼叫中使用安全字串,則必須轉換成 ANSI 字串、Unicode 字串或二進位字串 (BSTR)。 如需詳細資訊,請參閱 SecureString 和 Interop 一節。

實例值公開的時間間隔 SecureString 只會縮短與 String 類別相比。

儲存體 與使用量比較普遍,類別SecureString會定義應保護或保留機密之字元串值的儲存機制。 不過,在 .NET 本身之外,沒有使用機制支援 SecureString。 這表示安全字串必須轉換成可用表單(通常是純文字形式),才能由其目標辨識,而且解密和轉換必須在用戶空間中發生。

整體而言, SecureStringString 起限制敏感性字串數據的暴露,更安全。 不過,這些字串可能仍會公開給任何可存取原始記憶體的進程或作業,例如在主計算機上執行的惡意進程、進程傾印或用戶可檢視的交換檔案。 建議的替代方式是使用不透明的句柄來處理儲存在進程外部的認證,而不是使用 SecureString 來保護密碼。