上回写了关于SecureString的特征和为什么我们要使用它,这篇继续研究研究这个SecureString。

**主要内容:**

- SecureString与String之间的转换
- SecureString的基本操作
- 如何销毁一个String? ##SecureString与String之间的转换
###SecureString --> String的转换 我们可以使用[Marshal类](http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal(v=vs.110).aspx)提供的一些方法进行这个转换。 Marshal类并不支持直接将`SecureString`转成托管的`System.String`对像,它提供的方法只能将`SecureString`转成一些非托管的字符串类型。我们需要再做一次转换才能得到`System.String`对象。所以基本的转换思路是这样的: *SecureString --> BSTR/Unicode/ANSI --> System.String* 下面是代码,特别需要注意的地方是,我们一定要把非托管的字符串正确的释放掉。所以`Marshal.ZeroFreeBSTR`放在`Finally`块里确保一定会被执行。 ```
IntPtr bstr = IntPtr.Zero;
try
{
bstr = Marshal.SecureStringToBSTR(sstr);
var str = Marshal.PtrToStringBSTR(bstr);
//处理字符串
}
finally
{
Marshal.ZeroFreeBSTR(bstr);
}
``` **BSTR/Unicode/ANSI有啥区别?** 我们看一下`Marshal`的方法列表就知道`Marshal`可以将`SecureString`转换成五种不同的字符串类型:`BSTR`,`CoTaskMemAnsi`,`CoTaskMemUnicode`, `GlobalAllocAnsi`, `GlobalAllocUnicode`。我当初有一个疑问就是这样子不同的类型转换有啥区别,我后来得出的结论是如果你只是想得到托管的`System.String`类型的话你选哪个作为中间变量都无所谓,只要用完释放资源就行了。 ###String --> SecureString的转换 `SecureString`不接受`String`去构造一个对象,我们有两种方式可以将`String`转成`SecureString`。 1. 通过AppendChar方法把`String`对象中的字符一个一个添加到`SecureString`后面。 2. 虽然`SecureString`不接受`String`来构造一个对象,但是它接受一个字符指针来构造一个对象。所以我们可以取的指向`String`对象的非托管`char*`指针来构造。 ```
string str = "zhengyi.me";
unsafe
{
fixed (char* p_str = str)
{
SecureString sstr = new SecureString(p_str, str.Length);
sstr.MakeReadOnly();
}
}
``` ##SecureString的基本操作 详情参考 [SecureString Class in MSDN](http://msdn.microsoft.com/en-us/library/system.security.securestring(v=vs.110).aspx) ##如何销毁一个String对象? 进一步思考一下,我们引入`SecureString`就是为了让敏感信息不在内存中裸奔。但是目前的.NET Framework提供的接口对`SecureString`的支持很有限,我们总会需要在某一小段时间内将其转换为`String`对象进行一些处理。那我们能不能让这些`String`对象*阅后即焚*呢? 在C++中我们如果要销毁一个字符串的话,无非就是把字符串所在的内存memset成0,然后将这块字符串的内存释放掉。但是在.NET中的话我们主要会遇到这么两个问题: - 众所周知,Java和.NET中的String类型是[不可变的](http://msdn.microsoft.com/zh-cn/library/362314fe.aspx)(immutable)。我们如何将其中的内容重置掉? - .NET中,String是一个[引用类型](http://msdn.microsoft.com/zh-cn/library/362314fe.aspx),所以String实例时会存在于堆上的。那么在一次GC以后如果进行了内存的压缩,那么String实例可能在内存上会被移动。所以也就不方面释放内存。 **如何破?** - 虽然说`String`在.NET中是不可变的,但是.NET中有一种unsafe的机制能够让我们像在C++中一样写*不安全代码*(使用指针的代码)。 - fixed关键字可以防止GC去在内存中挪动变量。 基本的代码就像下面这样: ```
unsafe {
//利用fixed关键字将字符串pin在内存上,确保其不会挪动而出现多个拷贝
fixed(char* c = str)
{
// 处理字符串
// 利用unsafe的代码遍历字符串将其内容重置
for(int i = 0; i < str.Length; i++)
{
c[i] = '\0';
}
}
}
``` ##总之
如同我在前篇文章中写的,我们所做的所有的这一切只是说提高了获取密码的难度和所需的时间。因为如果有人都能够拿到你的程序的内存的话,他可以干很多很多事情。 ##引用:
[1] 关于使用SecureString的一些介绍:http://blogs.msdn.com/b/fpintos/archive/2009/06/12/how-to-properly-convert-securestring-to-string.aspx [2] 还不错的关于SecureString的一些讨论: http://bytes.com/topic/c-sharp/answers/583441-destroy-string

继续SecureString的更多相关文章

  1. 编写高质量代码改善C#程序的157个建议——建议118:使用SecureString保存密钥等机密字符串

    建议118:使用SecureString保存密钥等机密字符串 托管代码中的字符串是一类特殊的对象,它们不可用被改变.每次使用System.String类张的方法之一时,或者使用此类型进行运算时(如赋值 ...

  2. (C#)System.Security.SecureString(表示应保密的文本)

    正常的String类型值,在脱离开作用域之后,其值在内存中并不会被立即销毁,这时如果有人恶意扫描你的内存,程序中所保存的机密信息就会暴露;于是就有了System.Security.SecureStri ...

  3. 17 安全字符串 System.Security.SecureString

  4. .NET基础拾遗(3)字符串、集合和流

    Index: (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开发基础 ...

  5. SharePoint 2016 配置向导报错 - The 'ListInternal' attribute is not allowed

    前言 配置SharePoint 2016的配置向导中,第三步创建配置数据库报错,然后百度.谷歌了一下,都没有解决,自己看日志搞定,也许会有人遇到类似问题,分享一下. 1.配置向导的错误截图,如下图: ...

  6. 探索c#之不可变数据类型

    阅读目录: 不可变对象 自定义不可变集合 Net提供的不可变集合 不可变优点 不可变对象缺点 不可变对象 不可变(immutable): 即对象一旦被创建初始化后,它们的值就不能被改变,之后的每次改变 ...

  7. System.Diagnostics.Process.Start的妙用

    我们经常会遇到在Winform或是WPF中点击链接或按钮打开某个指定的网址, 或者是需要打开电脑中某个指定的硬盘分区及文件夹, 甚至是"控制面板"相关的东西, 那么如何做呢? 答案 ...

  8. ADO.NET 中的新增功能

    ADO.NET 中的新增功能: .NET Framework (current version) 以下是 .NET Framework 4.5 中 ADO.NET 的新增功能. SqlClient D ...

  9. System.Diagnostics.Process 启动进程资源或调用外部的命令的使用

    经常看到一些程序在保存为一个txt,或者excel的文件的时候,保存完毕立即打开, 启动程序或打开文件的代码 System.Diagnostics.Process.Start(System.IO.Pa ...

随机推荐

  1. 解压版MySQL5.7.1x的安装与配置

    解压版MySQL5.7.1x的安装与配置 MySQL安装文件分为两种,一种是msi格式的,一种是zip格式的.如果是msi格式的可以直接点击安装,按照它给出的安装提示进行安装(相信大家的英文可以看懂英 ...

  2. Java中抽象类和接口的区别

    转载自:http://dev.yesky.com/436/7581936.shtml 在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制.正是由于这两种 ...

  3. APP审核被拒,原因总结

    今天早上,突然看到上周末提交的APP,审核被拒了.原以为是因为IPV6审核没过,后来查看原因后发现是,app的3张展示图里面,有些内容显示的有:测试XX等字眼.苹果说提交的版本不能是含有 test,t ...

  4. C# 微信v3退款

    1.退款需要退款证书.C#都是用p12的证书,双击证书导入,密码是mch_id(商户号) 2.调用微信退款接口进行退款操作 string resp=string.Empty string cert = ...

  5. 分组背包——sicily 1750

    1750. 运动会 限制条件 时间限制: 1 秒, 内存限制: 32 兆 题目描述 ZEH是一名04级的学生,他除了绩点高,还有运动细胞.有一次学院举办运动会,ZEH发现里面的 项目都是他所向披靡的, ...

  6. mvc.net 的四种传值方式

    Control: view:

  7. IE跨域访问问题

    可能出现的症状: 1.跨域无法登录. 2.同一页面请求同一域名SESSION无法获取.(SESSION_ID一直在变) 一般情况下在方法前加上以下代码: header("P3P: CP=CU ...

  8. GIT FLOW 时序图

    git flow sequence md link: git branching model master->master branch: use default branch Note rig ...

  9. 用js实现瀑布流的一种简单方法

    现在说瀑布流式布局似乎有点晚了,但是每一项技术都是向着“精”和“简”的方向在不断发展,在发展到极致之前,需要一个相当漫长的过程,因此,从这个角度来说,当瀑布流被应用得越来越多的时候,反而更应该讨论它, ...

  10. berkeley db replica机制 - 消息处理

    repmgr_method.c, __repmgr_start_int()repmgr_method.c, __repmgr_start_msg_threads()repmgr_msg.c, __re ...