這很重要
建議您不要將 類別用於 SecureString
.NET (Core) 上的新開發,或當您將現有的程式代碼移轉至 .NET (Core) 時。 如需詳細資訊,請參閱 不應該使用 SecureString。
本文提供此 API 參考文件的補充備註。
SecureString 是提供安全性量值的字串類型。 它會嘗試避免將潛在的敏感性字串儲存在進程記憶體中做為純文字。 不過,如需限制,請參閱 SecureString 有多安全? 一節。實例的值 SecureString 會使用基礎平臺在初始化實例時或修改值時所支援的機制,自動保護的實例值。 您的應用程式可以藉由調用 MakeReadOnly 方法,使實例成為不可變,並防止進一步修改。
實例的最大 SecureString 長度為 65,536 個字元。
這很重要
此類型會實作 IDisposable 介面。 當您完成使用類型的實體時,應該直接或間接地處理它。 若要直接處置類型,請在 Disposetry
/ 區塊中呼叫其 catch
方法。 若要間接處置它,請使用語言建構,例如 using
(C#) 或 Using
(在 Visual Basic 中)。 如需詳細資訊,請參閱介面主題中的
COM 看不到 類別 SecureString 及其成員。 如需詳細資訊,請參閱ComVisibleAttribute。
字串與 SecureString
類別的 System.String 實例既不可變,而且不再需要時,無法以程式設計方式排程進行垃圾收集;也就是說,實例在建立后是只讀的,而且無法預測實例何時會從計算機記憶體中刪除。 因為 System.String 實例是不可變的,所以看似修改現有實例的操作實際上會建立一個副本來進行操作。 因此,如果String 物件包含機密資訊,例如密碼、信用卡號碼或個人資料,因為您的應用程式無法從電腦記憶體中刪除資料,將面臨洩露資訊的可能性。
SecureString對象類似於String物件,其具有文字值。 不過,物件的值 SecureString 會固定在記憶體中,可能會使用保護機制,例如由底層作業系統所提供的加密,可以被修改,直到您的應用程式將它標示為只讀為止,而且可由您的應用程式透過呼叫 Dispose 方法或由 .NET 垃圾回收器從計算機記憶體中刪除。
如需類別限制 SecureString 的討論,請參閱 SecureString 有多安全? 一節。
SecureString 作業
類別 SecureString 包含可讓您執行下列動作的成員:
具現化 SecureString 物件:您可以呼叫其無參數建構函式來具現化 SecureString 物件。
將字元新增至 SecureString 物件 您可以藉由呼叫 或 SecureStringAppendChar 方法,一次將單一字元新增至 InsertAt 物件。
這很重要
SecureString不應該從 String建構 物件,因為敏感數據已經受限於不可變String類別的記憶體持續性後果。 建構 SecureString 物件的最佳方式是從字元一個接一個來的非受控來源,例如 Console.ReadKey 方法。
從 SecureString 物件移除字元 您可以呼叫 SetAt 方法來取代個別字元,或是呼叫RemoveAt 方法來移除個別字元,或者透過呼叫 SecureString 方法來移除Clear 實例中的所有字元。
SecureString將物件設為唯讀 一旦您已定義物件所代表的SecureString字串,您就會呼叫其 MakeReadOnly 方法,讓字串成為唯讀的。
取得 對象的相關信息 SecureString 類別 SecureString 只有兩個成員提供字串的相關信息:其 Length 屬性,指出字串中 UTF16 編碼的程式代碼單位數目;以及 IsReadOnly,方法會指出實例是否為唯讀。
釋放配置給 SecureString 實例的記憶體。由於 SecureString 實作了 IDisposable 介面,因此您可以透過呼叫 Dispose 方法來釋放其記憶體。
類別 SecureString 沒有檢查、比較或轉換 值 SecureString的成員。 缺少這類成員有助於保護實例的值免於意外或惡意暴露。 使用 System.Runtime.InteropServices.Marshal 類別的適當成員,例如 SecureStringToBSTR 方法,來操作 SecureString 物件的值。
.NET 類別庫通常會以下列方式使用 SecureString 實例:
若要透過使用 ProcessStartInfo 結構或呼叫包含 Process.Start 型別參數的 SecureString 方法多載,將密碼資訊提供給程序。
若要藉由呼叫 NetworkCredential 具有 型 SecureString 別參數的類別建構函式或使用 NetworkCredential.SecurePassword 屬性來提供網路密碼資訊。
若要提供 SQL Server 驗證的密碼資訊,請藉由呼叫 SqlCredential.SqlCredential 建構函式或擷取 SqlCredential.Password 屬性的值。
將字串傳遞至非受控程式碼。 如需詳細資訊,請參閱 SecureString 和 Interop 一節。
SecureString 和 Interop
因為作系統並不直接支援 SecureString,因此您必須將 物件的值 SecureString 轉換成必要的字串類型,才能將字串傳遞至原生方法。 類別 Marshal 有五種方法可執行這項作:
Marshal.SecureStringToBSTR,可將字串值轉換成 SecureString COM 所辨識的二進位字串 (BSTR)。
Marshal.SecureStringToCoTaskMemAnsi 和 Marshal.SecureStringToGlobalAllocAnsi,將 SecureString 字串值複製到非受控記憶體中的 ANSI 字串。
Marshal.SecureStringToCoTaskMemUnicode 和 Marshal.SecureStringToGlobalAllocUnicode,它們的作用是將 SecureString 字串值複製到非受控記憶體中的 Unicode 字串。
所有這些方法都會在非受控記憶體中建立純文字字串。 開發人員有責任在不再需要記憶體后立即清空並釋放該記憶體。 每個字串轉換和記憶體分配方法都有對應的方法,用來清零並釋放分配的記憶體:
SecureString 有多安全?
當正確建立時,SecureString 實例會提供比 String 更佳的數據保護。 從一次字元來源建立字串時, String 會在記憶體中建立多個中繼,而 SecureString 只會建立單一實例。 String 物件的垃圾回收是非決定性的。 此外,由於未釘選其記憶體,垃圾收集器在移動和壓縮記憶體時,會額外複製String的值。 反之,配置給 SecureString 物件的記憶體會被固定,可以透過呼叫 Dispose 方法來釋放該記憶體。
雖然儲存在 SecureString 實例中的數據比儲存在 String 實例中的數據更安全,但 SecureString 實例的安全性仍然有重大限制。 這些包括:
平台
在 Windows 作業系統中,實例的內部字元陣列內容 SecureString 已被加密。 不過,無論是因為缺少 API 或金鑰管理問題,所有平臺上都無法使用加密。 由於此平臺相依性, SecureString 因此不會加密非 Windows 平臺上的內部記憶體。 這些平臺上會使用其他技術來提供額外的保護。
持續時間
即使 SecureString 實作能夠利用加密,指派給 SecureString 實例的純文本可能會在不同的時刻被公開:
因為 Windows 不提供作系統層級的安全字串實作,所以 .NET 仍必須將安全字串值轉換成其純文本表示法,才能使用它。
每當安全字串的值由 或 AppendChar等RemoveAt方法修改時,都必須解密(也就是轉換回純文本),修改後再加密。
如果在 Interop 呼叫中使用安全字串,則必須轉換成 ANSI 字串、Unicode 字串或二進位字串 (BSTR)。 如需詳細資訊,請參閱 SecureString 和 Interop 一節。
相較於 SecureString 類別,String 實例值公開的時間間隔只是縮短而已。
記憶體與使用比較普遍,類別 SecureString 會針對應受到保護或保留機密的字串值定義儲存機制。 不過,在 .NET 本身之外,沒有使用機制支援 SecureString。 這表示安全字串必須轉換成可用表單(通常是純文字形式),才能由其目標辨識,而且解密和轉換必須在用戶空間中發生。
整體而言, SecureString 比 String 起限制敏感性字串數據的暴露,更安全。 不過,這些字串可能仍會公開給任何可存取原始記憶體的進程或作業,例如在主計算機上執行的惡意進程、進程傾印或用戶可檢視的交換檔案。 建議的替代方式是使用不透明的句柄來處理儲存在程式外部的認證,而不是使用 SecureString 來保護密碼。