证书,电子证书,又叫数字证书,是一种用于计算机身份识别的机制。证书一般包括拥有者的身份信息,一把公钥和证书的签名信息,例如有效时限。(以下证书指的是数字证书)

证书具有唯一性和可靠性,通过它采用公钥机制,即一个密钥对来进行加解密。用户持有私钥用于解密和进行数据签名,而公开公钥用于加密和验证签名。

证书可以由权威机构颁发,专门的证书发行机构即证书授权中心。对于专业的证书申请及维护需要高昂的费用(例如企业证书开户费2000,年费800等等)。也有免费的机构,也可以自己制作,但权威性和认可性要低。

例如:学员在XX学校毕业后,可获得此学校颁发的(毕业)证书A;而大学毕业后,可获得(大学毕业)证书B。可能A只被一些公司承认,而B却可以受全国范围内公司认可。

x.509是全球认可的。

x.509

目前证书的格式普遍采用的是X.509 国际标准,X.509是由国际电信联盟制定的数字证书标准,内容包括:

证书序列号,持有者名称,颁发者名称,证书有效期,公钥,颁发者数字签名等。这个可以这样理解:一份A4纸上有个人的信息,然后到CA进行盖章,来保证此份文件的真实性,也就是保证个人信息的真实性。然后这份文件:个人信息+盖章就是一份证书。当然这是简化的,但意思是这样的。

 

证书有不同的各类,例如:

·个人证书

也就是客户端证书,用于颁发给个人用户的证书,用来向对方表明身份,可以实现邮件,登录等多种安全应用。例如网银的这KU宝。

·企业证书

向企业,政府机关,组织机构颁发的证明身份的证书。

·代码签名

颁发给软件开发商,然后在使用软件时可以用来证明软件来源,完整性等。

·电邮证书

对邮件进行加密和数字签名处理,来保证邮件的安全,机密,发件人身份和不可抵赖性

·服务器证书

颁发给web站等服务器,来证明服务器身份。

 

现在示例证书申请及安装(我的系统是win2003

(一)安全证书服务

添加windows组件:证书服务

(二)证书颁发机构

管理工具——证书颁发机构,这就是CA

(三)申请证书

服务器申请证书。

1 站点属性——目录安全性——安全通信——服务器证书

生成文本文件。

2 默认网站——CertSrv——default.asp base64编码申请证书,把文本文件中的内容复制到文本框

(四)CA颁发

管理工具——证书颁发机构

挂起的证书,颁发证书

(五)领取证书

默认网站——CertSrv——default.asp

查看挂起的证书的状态,下载证书

(六)安装

可以双击安装,也可以在站点属性中安装

 

证书系列工具

1makecert.exe

工具位置:Microsoft Visual Studio 9.0\SmartDevices\SDK\SDKTools

用于创建x.509证书。这个工具命令行有大量参数

命令行:makecert -? 显示基本参数

makecert [options] outputFilename

outputFIlename.cer的文件名

 

基本选项:

选项

说明

-n x509name

指定主题的证书名称。此名称必须符合 X.500 标准。最简单的方法是在双引号中指定此名称,并加上前缀 CN=;例如,"CN=myName"

-pe

将所生成的私钥标记为可导出。这样可将私钥包括在证书中。

-sk keyname

指定主题的密钥容器位置,该位置包含私钥。如果密钥容器不存在,系统将创建一个。

-sr location

指定主题的证书存储位置。Location 可以是 currentuser(默认值)或 localmachine

-ss store

指定主题的证书存储名称,输出证书即存储在那里。

-# number

指定一个介于 1 2,147,483,647 之间的序列号。默认值是由 Makecert.exe 生成的唯一值。

-$ authority

指定证书的签名权限,必须设置为 commercial(对于商业软件发行者使用的证书)或 individual(对于个人软件发行者使用的证书)。

-?

显示此工具的命令语法和基本选项列表。

-!

显示此工具的命令语法和扩展选项列表。

 

扩展选项:

选项

说明

-a algorithm

指定签名算法。必须是 md5(默认值)或 sha1

-b mm/dd/yyyy

指定有效期的开始时间。默认为证书的创建日期。

-cy certType

指定证书类型。有效值是 end(对于最终实体)和 authority(对于证书颁发机构)。

-d name

显示主题的名称。

-e mm/dd/yyyy

指定有效期的结束时间。默认为 12/31/2039 11:59:59 GMT

-eku oid[,oid]

将用逗号分隔的增强型密钥用法对象标识符 (OID) 列表插入到证书中。

-h number

指定此证书下面的树的最大高度。

-ic file

指定颁发者的证书文件。

-ik keyName

指定颁发者的密钥容器名称。

-iky keytype

指定颁发者的密钥类型,必须是 signatureexchange 或一个表示提供程序类型的整数。默认情况下,可传入 1 表示交换密钥,传入 2 表示签名密钥。

-in name

指定颁发者的证书公用名称。

-ip provider

指定颁发者的 CryptoAPI 提供程序名称。

-ir location

指定颁发者的证书存储位置。Location 可以是 currentuser(默认值)或 localmachine

-is store

指定颁发者的证书存储名称。

-iv pvkFile

指定颁发者的 .pvk 私钥文件。

-iy pvkFile

指定颁发者的 CryptoAPI 提供程序类型。

-l link

到策略信息的链接(例如,一个 URL)。

-m number

以月为单位指定证书有效期的持续时间。

-nscp

包括 Netscape 客户端身份验证扩展。

-r

创建自签署证书。

-sc file

指定主题的证书文件。

-sky keytype

指定主题的密钥类型,必须是 signatureexchange 或一个表示提供程序类型的整数。默认情况下,可传入 1 表示交换密钥,传入 2 表示签名密钥。

-sp provider

指定主题的 CryptoAPI 提供程序名称。

-sv pvkFile

指定主题的 .pvk 私钥文件。如果该文件不存在,系统将创建一个。

-sy type

指定主题的 CryptoAPI 提供程序类型。

 

 

证书的管理

打开mmc控制台,添加证书管理单元

运行——mmc——文件——添加/删除管理单——证书

图不贴了。

证书下的节点例如:个人|企业信任等就是证书的存储位置。在.net中,System.Security.Cryptography.X509Certificates名字空间提供了对x.5.9 v3证书的实现。

这里介绍几个常用的类:

(一)x.509证书帮助类X509Certificate

这个类提供了使用x.509证书的方法,但在大多数情况下,推荐使用X509Certificate2

示例:加载证书,显示证书的字符串形式

public void Test1()
{
    
string strPath = @"k:\zzz.cer";
    X509Certificate cert 
= new X509Certificate(strPath);
    
string str = cert.ToString(true);
    Console.WriteLine(str);
}

 

结果:

[Subject]
E
=zzzz@126.com, CN=zzz, OU=z, O=z, L=z, S=z, C=CN
[Issuer]CN
=catest.com
[Serial Number]617B56D4000000000004
[Not Before]
2010-4-8 14:03:16
[Not After]
2011-4-8 14:13:16
[Thumbprint]0CC045B734255A79050A309C59F2C7CE4A95DAB1

 

这些信息可以通过双击打开证书查看。

(二)x.509证书帮助类X509Certificate2

同上使用ToString方法,显示了更详细的内容信息。

返回公钥:

public void TestPublicKey()
{
    
string strPath = @"k:\zzz.cer";
    X509Certificate2 cert 
= new X509Certificate2(strPath);
    
string str = cert.GetPublicKeyString();
    Console.WriteLine(str);
}

 

结果:

30818902818100B438E5F16EBBF34218817638F63038DFAD933DBF43F

3D9A8BA6687F06765978AC28A4B0C076B30FFFFA30964CC08F158E58

CF9D4ADFE6852FF592146C0D29913BA6E32E95073150BBFC0751AE2C

3440698BD8D9FBC5FDFE39DF93581CAD7070BE20D6F7C7897D30ED97

08A282D1BBA2AA8B02349487276262CD1B7883E3BF6730203010001

 

(三)存储位置X509Store

这个类是保留和管理证书的物理存储区的实现,通过它可以处理证书的存储区

它几个重要的属性:

1 Certificates  返回位于 X.509 证书存储区中的证书集合。

public X509Certificate2Collection Certificates { get; }

 

2Location  获取 X.509 证书存储区的位置。

public StoreLocation Location { get; }

 

此属性返回当前用户存储区或本地计算机存储区的 X.509 证书存储区位置。枚举类型

·CurrentUser 当前用户使用的 X.509 证书存储区。

·LocalMachine 分配给本地计算机的 X.509 证书存储区。

3Name  获取 X.509 证书存储区的名称。

返回 X.509 证书存储区名称。可以指示所存储证书的类型,如根证书或来自受信任发行者的证书。

·AddressBook其他用户的X.509证书存储区。

·AuthRoot第三方证书颁发机构(CA)X.509证书存储区。

·CertificateAuthority中间证书颁发机构(CA)X.509证书存储区。

·Disallowed吊销的证书的X.509证书存储区。

·My个人证书的X.509证书存储区。

·Root受信任的根证书颁发机构(CA)X.509证书存储区。

·TrustedPeople直接受信任的人和资源的X.509证书存储区。

·TrustedPublisher直接受信任的发行者的X.509证书存储区。

4StoreHandle  获取 HCERTSTORE 存储区的 IntPtr 句柄。

使用 StoreHandle 属性可提供与非托管 Microsoft Cryptographic API (CAPI) 的兼容性。

示例:

public void TestStore()
{
    X509Store store 
= new X509Store(StoreLocation.CurrentUser); 

    store.Open(OpenFlags.ReadOnly);
    X509Certificate2Collection certificates 
= store.Certificates;
    store.Close();

    
foreach (X509Certificate2 cer in certificates)
    {
        Console.WriteLine(cer.Subject);
    }
}

 

结果:

CN=ZHAO\Administrator
CN
=SERVER\Administrator
CN
=Administrator
E
=zzzz@126.com, CN=zzz, OU=z, O=z, L=z, S=z, C=CN

 

以上我是本机的的admin帐号下的个人证书,可以在IE——属性——内容——证书——个人,查看

 

使用证书

1)创建证书

方法一:win2003证书服务

方法二:makecert工具

创建x.509证书,证书名:soapEncrypt

makecert --pe -"CN=soapEncrypt" -sky exchange -ss my k:\soapEncrypt.cer

 

2)使用证书为xml元素加密

public void TestUserCer()
{
    XmlDocument xmlDoc 
= new XmlDocument(); 

    xmlDoc.PreserveWhitespace 
= true;
    xmlDoc.Load(
@"k:\soaptest.xml"); 

    X509Store store 
= new X509Store(StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadOnly); 

    X509Certificate2Collection certCollection 
= store.Certificates;
 

    X509Certificate2 cert 
= null;
    
foreach (X509Certificate2 c in certCollection)
    {
        
if (c.Subject == "CN=soapEncrypt")
        {
            cert 
= c;
            
break;
        }
    }
    store.Close();
 

    XmlElement ele 
= xmlDoc.GetElementsByTagName("UserName")[0as XmlElement; 

    EncryptedXml encryptXml 
= new EncryptedXml();
    EncryptedData edElement 
= encryptXml.Encrypt(ele, cert);
    EncryptedXml.ReplaceElement(ele, edElement, 
false);    

    xmlDoc.Save(
@"k:\test.xml");

    Console.WriteLine(xmlDoc.OuterXml);
}

 

说明:

·加载要加密的xml

·从存储区打开

·获取本存储区的要使用的证书(创建的)

·设置要加密的xml元素

·通过EncryptedXml对元素进行加密

·保存xml文件

 

Soaptest.xml文件内容:

<Envelope>
  
<Body>
    
<UserName>Songjiang</UserName>
    
<age>33</age>
  
</Body>
</Envelope>

 

加密后的内容:

<Envelope>
  
<Body>
<EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" 
xmlns
="http://www.w3.org/2001/04/xmlenc#">
      
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
      
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        
<EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
          
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
          
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            
<X509Data>
                 
<X509Certificate>MIIBYzRw=</X509Certificate>
            
</X509Data>
          
</KeyInfo>
          
<CipherData>
            
<CipherValue>DP0Mhog=</CipherValue>
          
</CipherData>
        
</EncryptedKey>
      
</KeyInfo>
      
<CipherData>
        
<CipherValue>OaCotrETMu7uV</CipherValue>
      
</CipherData>
    
</EncryptedData>
    
<age>33</age>
  
</Body>
</Envelope>

 

其中的省略了内容的大部分。

 

以下是对这个加密的xml进行解密:

public void TestDeencryptUserCer()
{
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.Load(@"k:\test.xml"); 

    EncryptedXml exml = new EncryptedXml(xmlDoc);
    exml.DecryptDocument();
    Console.WriteLine(xmlDoc.OuterXml);
}

 

结果:

<Envelope>
   
<Body><UserName>Songjiang</UserName><age>33</age></Body>
</Envelope>

 

这段代码使用的是当前用户帐号的本地证书存储区的x.509证书对xml元素进行解密。使用DecryptDocument方法自动检索x.509证书,然后对<EncrytedData>元素的<EncryptedKey>元素中的密钥进行解密,然后使用该密钥对xml元素进行解密。

 

使用证书对字串进行加解密

加密,通过RSA加密。获取证书公钥来加密,私钥来解密

public void TestRsaWithCerEncrypt()
{
    
//获得证书
    X509Store store = new X509Store(StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadOnly);
    X509Certificate2Collection certCollection 
= store.Certificates; 

    X509Certificate2 cert 
= null;
    
foreach (X509Certificate2 c in certCollection)
    {
        
if (c.Subject == "CN=soapEncrypt")
        {
            cert 
= c;
            
break;
        }
    }
    store.Close();


    
//原文
     string strContent = "abcd123";
    Console.WriteLine(
"原文:{0}",strContent);

    
//证书公钥
    PublicKey _publicKey = cert.PublicKey; 

    
//RSA加密
    RSACryptoServiceProvider _Rsa = _publicKey.Key as RSACryptoServiceProvider;
 

    
//编码及加密
    Encoding _encoding = Encoding.Default;
    
byte[] bb = _encoding.GetBytes(strContent); 

    
byte[] bEncrypt = _Rsa.Encrypt(bb, false);
    
string strEncrypt = _encoding.GetString(bEncrypt);

    Console.WriteLine(
"密文:{0}",strEncrypt); 

    
//解密
    RSACryptoServiceProvider _Rsaa = cert.PrivateKey as RSACryptoServiceProvider;
    
byte[] bDeencrypt = _Rsaa.Decrypt(bEncrypt, false);
    
string strDecrypt = _encoding.GetString(bDeencrypt);
    Console.WriteLine(
"解密后:{0}",strDecrypt);

 

posted on 2010-04-12 12:24  梅桦  阅读(2454)  评论(0编辑  收藏  举报