随笔 - 55, 评论 - 298, 引用 - 17

导航

关于

我是新人,: )

每月存档

最新留言

  • re:Last day at Microsoft
    <p><a href="http://www.moretiffany.com/">tiffany jewelry</a> Choose, buy...
    by sibat0705(注册) on 2010/3/12 20:48:58
  • bVSVKxjrysxCAx
    zKTeMu &lt;a href=&quot;http://jmvdsaxpwywz.com/&quot;&gt;jmvdsaxpwywz&lt;/a&am...
    by algkkzvif(匿名) on 2010/2/21 22:53:15
  • DLXXSrOqat
    F3OQLk &lt;a href=&quot;http://pfpvdtnczscw.com/&quot;&gt;pfpvdtnczscw&lt;/a&am...
    by sfxnoylvca(匿名) on 2010/2/21 21:28:18
  • iNOutySOJKTsFyl
    kSPmy1 &lt;a href=&quot;http://kdajmdtvcxfu.com/&quot;&gt;kdajmdtvcxfu&lt;/a&am...
    by lydyggun(匿名) on 2010/2/21 20:21:46
  • mDUfBYTmJjTiGrv
    IXumnI &lt;a href=&quot;http://lamuwgvmprtw.com/&quot;&gt;lamuwgvmprtw&lt;/a&am...
    by gacyafcvtas(匿名) on 2010/2/14 4:47:26
  • oiUMbbvrAlLbcr
    ot9Ga3 &lt;a href=&quot;http://nwawfslgnomg.com/&quot;&gt;nwawfslgnomg&lt;/a&am...
    by cvalpp(匿名) on 2010/2/14 4:46:45
  • re:Last day at Microsoft
    写的真好,看了觉得很受到启发,谢谢,
    by Zheying Zheng(匿名) on 2010/2/4 10:35:20
  • re:REST API的身份验证(Authentication)
    <p>顶</p>
    by kekesoft(注册) on 2010/1/27 20:27:43
  • re:Last day at Microsoft
    祝你好运啊
    by Eric v(匿名) on 2010/1/24 1:53:34
  • re:Last day at Microsoft
    鄙人正在打算内部调动,跨过欢德福卡海峡去西雅图呢, 以后互通有无,常联系.
    by Charlie 木匠(匿名) on 2010/1/11 4:23:23
  • re:Last day at Microsoft
    Good luck, buddy.
    by Huimiao Liu(匿名) on 2010/1/10 20:18:24
  • re:Last day at Microsoft
    &lt;p&gt;Oops,you are right. 改正了。&lt;/p&gt;
    by demonfox(匿名) on 2010/1/10 18:22:13
  • re:Last day at Microsoft
    2006年8月14日起至2009年1月8日止 是2010年吧
    by q(匿名) on 2010/1/10 14:59:53
  • re:Last day at Microsoft
    &quot;永远选择你最感兴趣的项目而不是升职空间等所谓的职业发展前景&quot; -- 说的很好!Good luck!
    by CoderZh(匿名) on 2010/1/8 20:49:26
  • re:Chrome OS和Android的背后
    Google当然不是在传统的操作系统上去跟微软计算,手机操作系统,Windows CE是公认的烂,Google在这里竞争没有什么不可以。Chrome OS更多的是Google云计算战略的一部分,人家根...
    by 啊(匿名) on 2009/12/22 13:14:12

广告

.NET中管理数字证书(Digital Certificate)的一些类

Digital Certificate是计算机安全里很常见的内容。在网络上,最常见的情况大概就是SSL安全连接中的使用了。关于Digital Certificate,RSA算法,DSA算法,Message Digest,Mutual SSL等内容我就不介绍了,需要用到的朋友应该都很熟悉。如果不是很熟悉但有兴趣了解一些,这里有一个很浅显的教程:

http://www.youdzone.com/signature.html

这里简单介绍一点我自己遇到过的一些小例子。

我们的项目里需要用到一些Certificate(抱歉,我想还是不翻译成“证书”了,下同),有各种不同的用处,比如有用来做mutual SSL的,有用来做数字签名(digital signature)的。Windows提供了一个管理你系统里所有Certificate的工具,你可以这样调用:

1. Start -> Run -> "mmc"

2. 然后在出来的工具界面中-> File -> Add/Remove Snap-in -> Add -> Certificates -> 选Computer Account

这样就可以看到所有安装在LocalMachine这个Certificate Store里的Certificates了。如果在最后一步选My user account,则是看到CurrentUser这个Certificate Store。

开始的时候我们的Certificate全是通过这个工具来手工管理的,但后来Certificate越来越多,且每个Certificate的权限设置都有不同的时候,我们发现手工管理很容易出错,而且在最后布置(deploy)Web Application的时候很不方便(需要手动地往服务器上一个个加Certificate),所以我就写了一个工具来自动化整个过程。

.NET 2.0中对Ceritificate以及Certificate Store的使用和管理提供了很多的类,请参看System.Security.Cryptography.X509Certificates这个命名空间。两个最常用的类是:

X509Store (代表Certificate Store)和X509Certificate2 (代表X509标准的Certificates)

每个Certificate Store都有一串sub store,比如Personal是存放一些你个人的Certificate的地方(你如果给你的IIS服务器用selfssl加了一个服务器Certificate,那个Certificate就存放在Personal sub store里),还有比如Trusted Root Certification Authorities是存放所有你信任的Root Certificate的地方。

现在假设我们有一个很简单的任务,就是要在LocalMachine Certificate Store里建立一个MyProjectCerts的sub store,然后把我们项目用到的Certificate全放在那里,这个在.NET很容易做(如果是用传统的Win32 CAPI的话,光看看那些有5,6个参数的API就够你头疼的了):

X509Store store = new X509Store(args[1], StoreLocation.LocationMachine); store.Open(OpenFlags.ReadWrite); X509Certificate2 certificate = new X509Certificate2(PATH_TO_CERTIFICATE); store.Add(certificate); store.Close();

如果你的certificate带有一个Private Key(关于Certificate及其携带的Public Key/Private Key的内容我也略过了)的pfx文件,那么它一定是有密码保护的,不过这也很容易,只要在构造函数里多加一个参数就可以了:

X509Certificate2 certificate = new X509Certificate2(PATH_TO_CERTIFICATE, PASSWORD);

最后一部分是给Certificate分配合理的权限,其中最重要的,就是那些帐号(user account)有权限可以拿到一个Certificate的Private Key。这个很关键,因为Private Key是证明你是这个Certificate拥有者的最终证据,有了Private Key,你就可以生成签名,给消息加密,等等。

可是在这个过程中,原来很简单的问题却有了点波折。

首先我们发现我们的一些功能函数在Visual Studio的unit test环境中工作正常,但当这些函数被Web App的功能模块调用的时候,测试就通不过了。后来我们意识到是权限的问题,在unit test中直接调用那些函数的帐号是system admin,而安装Certificate也是system admin,所以测试程序可以顺利拿到Private Key来完成工作。但当这些函数被Web App调用的时候,执行的帐号变成了ASPNET,而ASPNET没有取得Private Key的权限!

于是我们用的是Windows Server 2003 Resource Kit里的winhttpcertcfg这个工具给ASPNET分配必要的权限,可是这样还有问题。

原本我们是在mmc这个工具里手工加入了Certificate,然后再用winhttpcertcfg分配权限,一切正常。但当我们用我的工具来加入Certificate后,winhttpcertcfg就无法正常设置权限了,硬是说我不是这个certificate的installer。见鬼,我不是刚刚才用我的工具往Certificate Store加了Certifiicate么,然后再马上接着用winhttpcertcfg的,怎么5秒钟的功夫我就变成不是原来的installer了。找了半天也不知什么原因,我甚至把winhttpcertcfg反编译了看它调用了那些CAPI (Cryptography API的简称),还是不懂。

后来才在这里找到了一片文章才恍然:http://blogs.msdn.com/ploeh/archive/2006/12/20/IntegrationTestingWithCertificates.aspx

原来缺省情况下创建一个X509Certificate2对象:X509Certificate2 certificate = new X509Certificate2(PATH_TO_CERTIFICATE); 的时候,Certificate的Private Key是不会被Persist(抱歉,不知该怎么翻译,不过大家对Persistance这个概念总是知道的吧?差不多的意思)到Certificate Store里,一定要调用第三个构造函数:

X509Certificate2 certificate = new X509Certificate2(PATH_TO_CERTIFICATE, PASSWORD, X509KeyStorageFlags.PersistKeySet);

这样做了以后,guess what? 还是不行,呵呵。继续研究一下,才发现,缺省情况下,Private Key是Persist到CurrentUser这个Store里的,而我们的Certificate安装在LocalMachine这个Store里(其实如果你在mmc中同时显示CurrentUser和LocalMachine两个Store,你会发现它们之间有一种奇妙的镜像关系,就是你加到LocalMachine里的Certificate会自动出现在CurrentUser那边,这个现象其实也给我们造成了麻烦,这里我就不展开了)。

最后的正确答案:

X509Certificate2 certificate = new X509Certificate2(PATH_TO_CERTIFICATE, PASSWORD, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet);

posted on 2007-01-23 18:48:00 by demonfox  评论(4) 阅读(8243)

Apple's new iPhone

http://www.apple.com/iphone/

官方网页说iPhone是3个产品合一的结果:手机,宽屏iPod,和Internet Device。

光看看这个界面,就让人有想在上面写点程序的冲动。

Palm界面的布局和iPhone还挺像的,但iPhone明显cool多了。我很高兴(或者说很庆幸?)Windows Mobile的界面是不同的风格,要真的和Apple较量UI设计,老实说我信心不怎么足。

It's good to have companies like Google and Apple around.  They make the life fun.

posted on 2007-01-10 05:17:00 by demonfox  评论(10) 阅读(5381)

The Problem with Double-checked Locking (双检锁)

前几天在看一段.NET源代码的时候偶尔遇到了Double-checked Locking (双检锁)的一个使用,于是想到了以前看过的一些资料,写出来分享一下。

主要参考:The "Double-Checked Locking is Broken" Delaration (http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html)

双检锁是在多线程环境下很常见的一种实现singleton模式里lazy initialization的方法。

先看一下最这个模式的起源(注:代码为Java,不过这个问题适用各种语言,比如C++):

// Single threaded version class Foo { private Helper helper = null; public Helper getHelper() { if (helper == null) helper = new Helper(); return helper; } // other functions and members... }

很容易看出,在多线程的情况下,上面的getHelper是不能正确工作的(可能生成多个helper实体)。

于是有下面的改进代码:

// Correct multithreaded version class Foo { private Helper helper = null; public synchronized Helper getHelper() { if (helper == null) helper = new Helper(); return helper; } // other functions and members... }

这样写程序不会出错,因为整个getHelper是一个整体的"critical section",但就是效率很不好,因为我们的目的其实只是在第一个初始化helper的时候需要locking(加锁),而后面取用helper的时候,根本不需要线程同步。

于是聪明的人们想出了下面的做法:

// Broken multithreaded version // "Double-Checked Locking" idiom class Foo { private Helper helper = null; public Helper getHelper() { if (helper == null) synchronized(this) { if (helper == null) helper = new Helper(); } return helper; } // other functions and members... }

思路很简单,就是我们只需要同步(synchronize)初始化helper的那部分代码从而使代码既正确又很有效率。

这就是所谓的“双检锁”机制(顾名思义)。

很可惜,这样的写法在很多平台和优化编译器上是错误的。

原因在于:helper = new Helper()这行代码在不同编译器上的行为是无法预知的。一个优化编译器可以合法地如下实现helper = new Helper():

1. helper = 给新的实体分配内存

2. 调用helper的构造函数来初始化helper的成员变量

现在想象一下有线程A和B在调用getHelper,线程A先进入,在执行到步骤1的时候被踢出了cpu。然后线程B进入,B看到的是helper已经不是null了(内存已经分配),于是它开始放心地使用helper,但这个是错误的,因为在这一时刻,helper的成员变量还都是缺省值,A还没有来得及执行步骤2来完成helper的初始化。

当然编译器也可以这样实现:

1. temp = 分配内存

2. 调用temp的构造函数

3. helper = temp

如果编译器的行为是这样的话我们似乎就没有问题了,但事实却不是那么简单,因为我们无法知道某个编译器具体是怎么做的,因为在Java的memory model里对这个问题没有定义(C++也一样),而事实上有很多编译器都是用第一种方法(比如symantec的just-in-time compiler),因为第一种方法看起来更自然。

在上面的参考文章中还提到了更复杂的修改方法,不过很可惜,都是错误的,我这里就略去不介绍了。

那么有什么解决方案呢?有如下一些:

1. 如果你的singleton是static的,那你可以将这个singleton申明为一个独立类的一个成员变量:

class HelperSingleton { static Helper singleton = new Helper(); }

Java的语意会保证:1. lazy initialization, 2. singleton在被调用前已经完全初始化了。

2. 双检锁对于基础类型(比如int)适用。很显然吧,因为基础类型没有调用构造函数这一步。事实上,我前面提到的.NET里面的那段代码就是在一个int变量上使用双检锁。

3. 使用explicit memory barrier。这个我不说了,关于memory barrier我们可以写一本小册子来介绍,有兴趣的朋友可以自己查一下资料,上面的参考里也有很多相关链接。

4. 使用Thread Local Storage。也不介绍了。

上面的文章还提到了Java在考虑为volatile关键字定义新的语意来解决这个问题以及双检锁对Java里immutable对象影响,不过因为这篇文章已经有些年头而我也不是Java的专家,所以不太清楚现在的情况怎样,总之,在遇到双检锁的时候,需要的朋友应该做些必要的调查来确定自己的代码是线程安全的。

 

Update: 这篇文章也很浅显有用 -- Implementing the Singleton Pattern in C#

             .NET中DCL的处理 -- http://discuss.develop.com/archives/wa.exe?A2=ind0203B&L=DOTNET&P=R375 (感谢saucer提供)

posted on 2007-01-04 18:05:00 by demonfox  评论(9) 阅读(6615)

Powered by: Joycode.MVC引擎 0.5.2.0