SecureString 类

定义

表示应保密的文本,例如在不再需要时将其从计算机内存中删除。 此类不能被继承。

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 、通过调用方法删除单个字符 RemoveAtSecureString 通过调用方法从实例中移除所有字符 Clear

使 SecureString 对象成为只读
定义对象表示的字符串后 SecureString ,调用其 MakeReadOnly 方法,使字符串成为只读的。

获取有关对象的信息 SecureString
SecureString类只包含两个提供有关字符串的信息的成员:其 Length 属性,指示字符串中 UTF16 编码的代码单元的数目; 以及 IsReadOnly 指示该实例是否为只读的方法。

释放分配给实例的内存 SecureString
由于 SecureString 实现 IDisposable 接口,因此可以通过调用方法释放其内存 Dispose

SecureString类没有任何成员用于检查、比较或转换的值 SecureString 。 由于缺少这类成员,因此有助于保护实例的值不被意外或恶意公开。 使用类的适当成员( System.Runtime.InteropServices.MarshalSecureStringToBSTR 方法)来操作对象的值 SecureString

.NET Framework 类库通常 SecureString 以下列方式使用实例:

返回页首

SecureString 和互操作

由于操作系统不直接支持 SecureString ,因此必须先将对象的值转换 SecureString 为所需的字符串类型,然后才能将该字符串传递给本机方法。 Marshal类具有五种执行此操作的方法:

其中每种方法在非托管内存中创建一个明文字符串。 开发人员负责在不再需要该内存时将其从零开始,并将其释放。 每个字符串转换和内存分配方法都有一个对应的方法,以使分配的内存为零并释放已分配的内存:

分配和转换方法 零和免费方法
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 Framework 仍必须将安全字符串值转换为纯文本表示形式,才能使用该字符串。

  • 每当使用或等方法修改安全字符串的值时,都 AppendChar RemoveAt 必须将其解密 (也就是说,转换回纯文本) ,修改后再次加密。

  • 如果在互操作调用中使用安全字符串,则必须将其转换为 ANSI 字符串、Unicode 字符串或 (BSTR) 的二进制字符串。 有关详细信息,请参阅 SecureString and 互操作 部分。

SecureString与类相比,实例的值公开的时间间隔只需缩短 String

存储与使用情况
更常见的情况是, SecureString 类为应受到保护或保密的字符串值定义存储机制。 但是,在 .NET Framework 之外,不支持使用机制 SecureString 。 这意味着,必须将安全字符串转换为可用形式 (通常为明文形式) 可以被其目标识别,并且必须在用户空间中进行解密和转换。

总体而言, SecureStringString 它限制敏感字符串数据的公开更安全。 但是,这些字符串可能仍会公开给有权访问原始内存的任何进程或操作,例如,在主计算机上运行的恶意进程、进程转储或用户可查看的交换文件。 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)

适用于

另请参阅