继续SecureString
上回写了关于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的更多相关文章
- 编写高质量代码改善C#程序的157个建议——建议118:使用SecureString保存密钥等机密字符串
建议118:使用SecureString保存密钥等机密字符串 托管代码中的字符串是一类特殊的对象,它们不可用被改变.每次使用System.String类张的方法之一时,或者使用此类型进行运算时(如赋值 ...
- (C#)System.Security.SecureString(表示应保密的文本)
正常的String类型值,在脱离开作用域之后,其值在内存中并不会被立即销毁,这时如果有人恶意扫描你的内存,程序中所保存的机密信息就会暴露;于是就有了System.Security.SecureStri ...
- 17 安全字符串 System.Security.SecureString
- .NET基础拾遗(3)字符串、集合和流
Index: (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开发基础 ...
- SharePoint 2016 配置向导报错 - The 'ListInternal' attribute is not allowed
前言 配置SharePoint 2016的配置向导中,第三步创建配置数据库报错,然后百度.谷歌了一下,都没有解决,自己看日志搞定,也许会有人遇到类似问题,分享一下. 1.配置向导的错误截图,如下图: ...
- 探索c#之不可变数据类型
阅读目录: 不可变对象 自定义不可变集合 Net提供的不可变集合 不可变优点 不可变对象缺点 不可变对象 不可变(immutable): 即对象一旦被创建初始化后,它们的值就不能被改变,之后的每次改变 ...
- System.Diagnostics.Process.Start的妙用
我们经常会遇到在Winform或是WPF中点击链接或按钮打开某个指定的网址, 或者是需要打开电脑中某个指定的硬盘分区及文件夹, 甚至是"控制面板"相关的东西, 那么如何做呢? 答案 ...
- ADO.NET 中的新增功能
ADO.NET 中的新增功能: .NET Framework (current version) 以下是 .NET Framework 4.5 中 ADO.NET 的新增功能. SqlClient D ...
- System.Diagnostics.Process 启动进程资源或调用外部的命令的使用
经常看到一些程序在保存为一个txt,或者excel的文件的时候,保存完毕立即打开, 启动程序或打开文件的代码 System.Diagnostics.Process.Start(System.IO.Pa ...
随机推荐
- js获取新浪天气接口
<!doctype html> <html class="no-js fixed-layout"> <head> <meta charse ...
- @helper函数使用方法
这个函数方法,我也是通过别人博客看到的,感觉不错和大家一起学习分享一下. 1.自定义函数方法,只在同一个view视图文件里调用 Controller public ActionResult Index ...
- amr转MP3
using System; using System.Threading; using System.IO; using System.Diagnostics; using System.Securi ...
- js模块和级联
1.模块 模块模式的一般形式是:一个定义了私有变量和函数的函数,利用闭包创建可以访问私有变量和函数的特权函数,最后返回这个特权函数,或者把它们保存到一个可访问的地方.使用模块模式就可以摒弃全局变量的使 ...
- 搭建maven环境
有两种方式可以配置maven的环境配置,本人推荐使用第二种,即使用本地的maven安装文件,个人感觉这样可以方便管理下载jar包的存放位置,错误信息的输出等,可以在dos窗口中可以清晰看到,虽然比较麻 ...
- 使用django-admin.py 时出错
我在安装好django后,运行django-admin.py 时出现两处错误: 一.当你在dos命令下输入django-admin.py 时不会运行,而是以记事本的方式打开了. 解决办法:找到你的dj ...
- html或者jsp页面引用jar包中的js文件
一,页面上引用jar包中的js文件的方法 使用java web框架AppFuse的时候发现,jquery.bootstrap等js框架都封装到jar包里面了.这些js文件通过一个wro4j的工具对其进 ...
- hibernate中保存一个对象后再设置此对象的属性为什么不需要调用update方法了
hibernate中保存一个对象后再设置此对象的属性为什么不需要调用update方法了 例如session.save(user);user.setAge(20); 原因: hibernate对象的三种 ...
- 用wordpress搭建个人博客
一.安装WordPress所需的开发环境. 1.安装apache yum install httpd 2.安装mysql 可参照我的另一篇文章:http://www.cnblogs.com/kings ...
- 获取google翻译的音频文件_合并音频文件的方法
1. 把引文输入google 翻译,然后点击"朗读"