SecureString 类
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
表示应保密的文本,例如在不再需要时将其从计算机内存中删除。 此类不能被继承。
public ref class SecureString sealed : IDisposable
public sealed class SecureString : IDisposable
type SecureString = class
interface IDisposable
Public NotInheritable Class SecureString
Implements IDisposable
- 继承
-
SecureString
- 实现
示例
下面的示例演示如何使用 SecureString 保护用户的密码,以将其用作凭据以启动新进程。
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Security;
public class Example
{
public static void Main()
{
// Instantiate the secure string.
SecureString securePwd = new SecureString();
ConsoleKeyInfo key;
Console.Write("Enter password: ");
do {
key = Console.ReadKey(true);
// Ignore any key out of range.
if (((int) key.Key) >= 65 && ((int) key.Key <= 90)) {
// Append the character to the password.
securePwd.AppendChar(key.KeyChar);
Console.Write("*");
}
// Exit if Enter key is pressed.
} while (key.Key != ConsoleKey.Enter);
Console.WriteLine();
try {
Process.Start("Notepad.exe", "MyUser", securePwd, "MYDOMAIN");
}
catch (Win32Exception e) {
Console.WriteLine(e.Message);
}
finally {
securePwd.Dispose();
}
}
}
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Security
Public Class Example
Public Shared Sub Main()
' Instantiate the secure string.
Dim securePwd As New SecureString()
Dim key As ConsoleKeyInfo
Console.Write("Enter password: ")
Do
key = Console.ReadKey(True)
' Ignore any key out of range
If CInt(key.Key) >= 65 And CInt(key.Key <= 90) Then
' Append the character to the password.
securePwd.AppendChar(key.KeyChar)
Console.Write("*")
End If
' Exit if Enter key is pressed.
Loop While key.Key <> ConsoleKey.Enter
Console.WriteLine()
Try
Process.Start("Notepad.exe", "MyUser", securePwd, "MYDOMAIN")
Catch e As Win32Exception
Console.WriteLine(e.Message)
Finally
securePwd.Dispose()
End Try
End Sub
End Class
注解
重要
不建议使用 SecureString
类进行新的开发。 有关详细信息,请参阅 GitHub 上不能使用 SecureString 。
SecureString 是提供安全度量值的字符串类型。 它尝试避免以纯文本形式在进程内存中存储可能敏感的字符串。 (的限制,请参阅 " 安全设置的安全级别 " 一节。 ) 实例的值是在 SecureString 初始化实例或修改该值时使用基础平台支持的机制自动保护的。 您的应用程序可以通过调用方法来使实例不可变,并防止进一步的修改 MakeReadOnly 。
实例的最大长度 SecureString 为65536个字符。
重要
此类型实现 IDisposable 接口。 使用完该类型的实例后,应直接或间接释放该实例。 若要直接释放类型,请在 try
/catch
块中调用其 Dispose 方法。 若要间接释放类型,请使用 using
(在 C# 中)或 Using
(在 Visual Basic 中)等语言构造。 有关详细信息,请参阅 IDisposable 接口主题中的“使用实现 IDisposable 的对象”一节。
SecureString类及其成员对 COM 不可见。 有关详细信息,请参阅 ComVisibleAttribute。
本部分内容:
String 与 SecureString
SecureString 操作
SecureString 和互操作
SecureString 的安全程度如何?
String 与 SecureString
类的实例 System.String 是不可变的,并且在不再需要时不能以编程方式计划进行垃圾回收; 也就是说,实例在创建后是只读的,并且不能预测将从计算机内存中删除该实例的时间。 因为 System.String 实例是不可变的,所以看起来修改现有实例的操作实际上会创建它要操作的副本。 因此,如果 String 对象包含敏感信息(如密码、信用卡号或个人数据),则在使用该信息时可能会出现一种风险,因为应用程序无法从计算机内存中删除数据。
SecureString对象类似于 String 对象,因为它具有一个文本值。 但是,对象的值 SecureString 固定在内存中,可能会使用基础操作系统提供的保护机制(如加密),直到应用程序将其标记为只读,并且可以通过调用方法的应用程序 Dispose 或 .NET Framework 垃圾回收器将其从计算机内存中删除。
有关类的限制的讨论 SecureString ,请参阅 " 安全设置 SecureString" 部分。
SecureString 操作
SecureString类包括允许你执行以下操作的成员:
实例化 SecureString 对象
SecureString通过调用对象的无参数构造函数来实例化对象。
向对象添加字符 SecureString
可以 SecureString 通过调用对象的 AppendChar 或方法,一次将一个字符添加到对象 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 Framework 类库通常 SecureString 以下列方式使用实例:
使用 ProcessStartInfo 结构或通过调用 Process.Start 具有类型的参数的方法的重载,为进程提供密码信息 SecureString 。
如果为,则通过调用 NetworkCredential 具有类型的参数 SecureString 或使用属性的类构造函数来提供网络密码信息 NetworkCredential.SecurePassword 。
通过调用 SqlCredential.SqlCredential 构造函数或检索属性的值,为 SQL Server 身份验证提供密码信息 SqlCredential.Password 。
将字符串传递到非托管代码。 有关详细信息,请参阅 SecureString and 互操作 部分。
SecureString 和互操作
由于操作系统不直接支持 SecureString ,因此必须先将对象的值转换 SecureString 为所需的字符串类型,然后才能将该字符串传递给本机方法。 Marshal类具有五种执行此操作的方法:
Marshal.SecureStringToBSTR,它将 SecureString 字符串值转换为二进制字符串 (BSTR) COM 识别。
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 Framework 仍必须将安全字符串值转换为纯文本表示形式,才能使用该字符串。
每当使用或等方法修改安全字符串的值时,都 AppendChar RemoveAt 必须将其解密 (也就是说,转换回纯文本) ,修改后再次加密。
如果在互操作调用中使用安全字符串,则必须将其转换为 ANSI 字符串、Unicode 字符串或 (BSTR) 的二进制字符串。 有关详细信息,请参阅 SecureString and 互操作 部分。
SecureString与类相比,实例的值公开的时间间隔只需缩短 String 。
存储与使用情况
更常见的情况是, SecureString 类为应受到保护或保密的字符串值定义存储机制。 但是,在 .NET Framework 之外,不支持使用机制 SecureString 。 这意味着,必须将安全字符串转换为可用形式 (通常为明文形式) 可以被其目标识别,并且必须在用户空间中进行解密和转换。
总体而言, SecureString 比 String 它限制敏感字符串数据的公开更安全。 但是,这些字符串可能仍会公开给有权访问原始内存的任何进程或操作,例如,在主计算机上运行的恶意进程、进程转储或用户可查看的交换文件。 SecureString建议的替代方法是对存储在进程外部的凭据使用不透明的句柄,而不是使用来保护密码。
构造函数
SecureString() |
初始化 SecureString 类的新实例。 |
SecureString(Char*, Int32) |
用 Char 对象的子数组初始化 SecureString 类的新实例。 此构造函数不符合 CLS。 符合 CLS 的替代方法是 SecureString()。 |
属性
Length |
获取当前安全字符串中的字符数。 |
方法
AppendChar(Char) |
在当前安全字符串的末尾追加一个字符。 |
Clear() |
删除当前安全字符串的值。 |
Copy() |
创建当前安全字符串的副本。 |
Dispose() |
释放由当前 SecureString 对象使用的所有资源。 |
Equals(Object) |
确定指定对象是否等于当前对象。 (继承自 Object) |
GetHashCode() |
作为默认哈希函数。 (继承自 Object) |
GetType() |
获取当前实例的 Type。 (继承自 Object) |
InsertAt(Int32, Char) |
在此安全字符串中的指定索引位置插入一个字符。 |
IsReadOnly() |
指示此安全字符串是否标记为只读。 |
MakeReadOnly() |
将此安全字符串的文本值设置为只读。 |
MemberwiseClone() |
创建当前 Object 的浅表副本。 (继承自 Object) |
RemoveAt(Int32) |
从此安全字符串中的指定索引位置移除字符。 |
SetAt(Int32, Char) |
将指定索引位置上的现有字符替换为其他字符。 |
ToString() |
返回表示当前对象的字符串。 (继承自 Object) |