惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Cisco Blogs
爱范儿
爱范儿
有赞技术团队
有赞技术团队
博客园 - 【当耐特】
Jina AI
Jina AI
Project Zero
Project Zero
宝玉的分享
宝玉的分享
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
Simon Willison's Weblog
Simon Willison's Weblog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tenable Blog
F
Fortinet All Blogs
大猫的无限游戏
大猫的无限游戏
Last Week in AI
Last Week in AI
月光博客
月光博客
雷峰网
雷峰网
G
Google Developers Blog
V
V2EX
T
Tor Project blog
罗磊的独立博客
Schneier on Security
Schneier on Security
Know Your Adversary
Know Your Adversary
W
WeLiveSecurity
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
P
Privacy International News Feed
S
Securelist
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
P
Proofpoint News Feed
Blog — PlanetScale
Blog — PlanetScale
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
小众软件
小众软件
Scott Helme
Scott Helme
I
Intezer
T
Threat Research - Cisco Blogs
The GitHub Blog
The GitHub Blog
N
Netflix TechBlog - Medium
C
CERT Recently Published Vulnerability Notes
Security Archives - TechRepublic
Security Archives - TechRepublic
酷 壳 – CoolShell
酷 壳 – CoolShell
L
LINUX DO - 最新话题
N
News | PayPal Newsroom
L
Lohrmann on Cybersecurity
T
Troy Hunt's Blog
Google DeepMind News
Google DeepMind News
P
Proofpoint News Feed
人人都是产品经理
人人都是产品经理
Latest news
Latest news
AWS News Blog
AWS News Blog
Apple Machine Learning Research
Apple Machine Learning Research

博客园 - Sherrys

Content-Type 参数 Sql 2000 中行转列的查询方法 DotNet Framework 小技巧 通过 INotifyPropertyChanged 实现观察者模式 API参数说明符前缀详解 C#中调用Windows API的要点 - Sherrys - 博客园 SQL 处理简单的 Xml Special Considerations When Using Query Notifications 利用.NET Framework使用RSS feed SQL远程连接 SQL 事务的隔离 SELECT 语句收藏(2000 & 2005) 自动处理 SQL 2005 表格数据 SQL事务的使用 用JS让文章内容指定的关键字加亮 - Sherrys - 博客园 查询SQL连接数的方法 对象的继承方案 使用 ICallbackEventHandler aspx页面中的DropDownList 的 SelectValue 出现中文导致不回调方法的问题 如何利用SQL Server 2005数据库快照形成报表
使用 .NET 2.0 SecureString 类保护敏感数据
Sherrys · 2007-06-22 · via 博客园 - Sherrys

什么时候应当使用SecureString类

你可能感到怀疑,既然可以使用基本的String类,为什么还有必要使用SecureString类呢?问题在于String类的设计方面。例如,如果你有一个String类的实例包含某个人的社会安全号,你就希望应用程序在处理过程中将其安全保存,以避免泄露。

问题的关键在于安全保存文本,因为String类将其以明文形式保存。查明数据的保存位置需要对.NET字符串有一定了解。.NET字符串是不可变的。也就是说,字符串值的每一个变化都在内存中建立一个新的字符串。因此,内存中的各种敏感数据可能会被不严格的代码或用户访问。

这并不是说明为什么使用StringBuilder对象的最有效方法和解释。由于垃圾收集功能,你可能认为这并不是一个太大的问题,但利用.NET垃圾收集使用字符串恢复内存没有确定性。因此,如果数据确实十分敏感,你应当避免String类,而选择SecureString类这些其它方法。

SecureString类具有以下特性:

  • 它对保存在内存中的字符串值进行加密。它利用数据保护API(DPAPI),因此它只能在基于NT的平台上使用。

  • SecureString类遵循IDisposable模式。

  • 加密文本不能被轻易解密;也就是说,不存在可以迅速阅读字符串内容的ToString类(没人说过加密很容易)。

一个简单的事例:

System.Security.SecureString ss = new System.Security.SecureString();

ss.AppendChar('T');

ss.AppendChar('e');

ss.AppendChar('c');

ss.AppendChar('h');

ss.AppendChar('R');

ss.AppendChar('e');

ss.AppendChar('p');

ss.AppendChar('u');

ss.AppendChar('b');

ss.AppendChar('l');

ss.AppendChar('i');

ss.AppendChar('c');

ss.AppendChar('.');

ss.AppendChar('c');

ss.AppendChar('o');

ss.AppendChar('m');

Console.WriteLine(ss);

增加最后一个字符后,以上代码用MakeReadOnly方法锁定字符串值。这意味着这个值不能被修改。使数据只读后,一旦你企图修改数据,就会出现异常。你会注意到,在执行时,代码只显示类的名称(System.Security.SecureString)。

获得数据

像.NET Framework的大多数对象一样,SecureString类也提供一个ToString方法。但是,ToString方法源于基本的System.Object类,在SecureString类中它不能被忽略。因此,调用SecureString类的ToString方法只显示对象(System.Security.SecureString)的类型,而没有实际的值。

应用SecureString类的难点在于如何恢复保存在其中的数据。因为它使用Windows的加密服务,要利用它,你需要使用System.Runtime命名空间。下面的C#代码是恢复数据的第一个步骤。它将SecureString类的内容复制到一个长指针对象中。

IntPtr pointerName = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(SecureString object);

    植入指针对象后,指针通过System.Runtime.InteropServices.Marshal类转换为一个字符串。这一操作由以下C#代码完成:

Console.WriteLine(System.Runtime.InteropServices.Marshal.PtrToStringBSTR(bstr));

微软文件指出,转换对象到一个指针分配了一个字符串所需的未管理内存,因此任务完成后你应当总是通过调用ZeroFreeBSTR方法释放指针对象,如以下的C#所示:

    System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(bstr);

下面的C#代码将在SecureString对象中保存数据与恢复数据、保存和显示内容的例子结合起来:

System.Security.SecureString ss = new System.Security.SecureString();

ss.AppendChar('T');

ss.AppendChar('e');

ss.AppendChar('c');

ss.AppendChar('h');

ss.AppendChar('R');

ss.AppendChar('e');

ss.AppendChar('p');

ss.AppendChar('u');

ss.AppendChar('b');

ss.AppendChar('l');

ss.AppendChar('i');

ss.AppendChar('c');

ss.AppendChar('.');

ss.AppendChar('c');

ss.AppendChar('o');

ss.AppendChar('m');

Console.WriteLine(ss);

IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(ss);

try

{

Console.WriteLine(System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr));

}

finally

{

System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);

}