﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-David.Turing's Security Blog-文章分类-CryptoAPI</title><link>http://www.blogjava.net/openssl/category/12809.html</link><description>Java Security, CAPICOM, CryptoAPI/CSP, BouncyCastle, Openssl, JCE/JCA, SSO, CAS, Tivoli, CA, PKI
&lt;br&gt;
&lt;font color="#00f100"&gt;本站内容只兼容IE浏览器&lt;/font&gt;
&lt;br&gt;
&lt;font color="#00f100"&gt;重要的文章包均含本人的PGP签名，本人愿意对自己的言论负责&lt;/font&gt;
&lt;br&gt;</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 12:58:11 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 12:58:11 GMT</pubDate><ttl>60</ttl><item><title>RSAUtils for Java Public Encryption</title><link>http://www.blogjava.net/security/articles/RSAUtils_java.html</link><dc:creator>david.turing</dc:creator><author>david.turing</author><pubDate>Fri, 17 Nov 2006 14:30:00 GMT</pubDate><guid>http://www.blogjava.net/security/articles/RSAUtils_java.html</guid><wfw:comment>http://www.blogjava.net/security/comments/81863.html</wfw:comment><comments>http://www.blogjava.net/security/articles/RSAUtils_java.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/security/comments/commentRss/81863.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/security/services/trackbacks/81863.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: package				 org.dev2dev.security.crypto.Asymmetric;				import				 java.io.BufferedInputStream;				import				 java.io.BufferedOutputStream;				import				 java.io.BufferedReader;				impo...&nbsp;&nbsp;<a href='http://www.blogjava.net/security/articles/RSAUtils_java.html'>阅读全文</a><img src ="http://www.blogjava.net/security/aggbug/81863.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/security/" target="_blank">david.turing</a> 2006-11-17 22:30 <a href="http://www.blogjava.net/security/articles/RSAUtils_java.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CryptoAPI第一天</title><link>http://www.blogjava.net/security/articles/56869.html</link><dc:creator>david.turing</dc:creator><author>david.turing</author><pubDate>Wed, 05 Jul 2006 15:18:00 GMT</pubDate><guid>http://www.blogjava.net/security/articles/56869.html</guid><wfw:comment>http://www.blogjava.net/security/comments/56869.html</wfw:comment><comments>http://www.blogjava.net/security/articles/56869.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/security/comments/commentRss/56869.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/security/services/trackbacks/56869.html</trackback:ping><description><![CDATA[<p>
				<font color="#000000">[转]<a href="http://www.chinaitpower.com/A200507/2005-07-27/175804.html">http://www.chinaitpower.com/A200507/2005-07-27/175804.html</a><br /><br />一：准备工作<br />一般必须包含如下头</font>
				<a href="http://www.chinaitpower.com/Soft/Tools/File/index.html" target="_blank">
						<font color="#000000">文件</font>
				</a>
				<font color="#000000">以及定义<br />#include <br />#include <br />#include <br />#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)<br /> 当包含wincrypt.h头</font>
				<a href="http://www.chinaitpower.com/Soft/Tools/File/index.html" target="_blank">
						<font color="#000000">文件</font>
				</a>
				<font color="#000000">时，一般都需要定义#define _WIN32_WINNT 0x（具体的值），否则将得到如下错误：error C2065: undeclared identifier，不同的操作</font>
				<a href="http://www.chinaitpower.com/System/index.html" target="_blank">
						<font color="#000000">系统</font>
				</a>
				<font color="#000000">不同定义如下：<br />Windows Server 2003 family _WIN32_WINNT&gt;=0x0502<br />WINVER&gt;=0x0502<br />Windows XP _WIN32_WINNT&gt;=0x0501 <br />WINVER&gt;=0x0501<br />Windows 2000 _WIN32_WINNT&gt;=0x0500<br />WINVER&gt;=0x0500<br />Windows NT 4.0 _WIN32_WINNT&gt;=0x0400<br />WINVER&gt;=0x0400<br />Windows Me _WIN32_WINDOWS=0x0500<br />WINVER&gt;=0x0500<br />Windows 98 _WIN32_WINDOWS&gt;=0x0410<br />WINVER&gt;=0x0410<br />Windows 95 _WIN32_WINDOWS&gt;=0x0400<br />WINVER&gt;=0x0400<br />Internet Explorer 6.0 _WIN32_IE&gt;=0x0600 <br />Internet Explorer 5.6 _WIN32_IE&gt;=0x0560 <br />Internet Explorer 5.01, 5.5 _WIN32_IE&gt;=0x0501 <br />Internet Explorer 5.0, 5.0a, 5.0b _WIN32_IE&gt;=0x0500 <br />Internet Explorer 4.01 _WIN32_IE&gt;=0x0401 <br />Internet Explorer 4.0 _WIN32_IE&gt;=0x0400 <br />Internet Explorer 3.0, 3.01, 3.02 _WIN32_IE&gt;=0x0300</font>
		</p>
		<p>
				<font color="#000000">二：了解基本知识<br />CryptoAPI的配置信息存储在注册表中，包括如下密钥： <br />HKEY＿LOCAL＿MACHINE＼SOFTWARE＼Microsoft \ Cryptography \Defaults<br />HKEY_CURRENT_USER\ Software \ Microsoft\ Cryptography \Providers<br />---- CryptoAPI使用两种密钥：会话密钥与公共/私人密钥对。会话密钥使用相同的加密和解密密钥，这种算法较快，但必须保证密钥的安全传递。公共/私人密钥对使用一个公共密钥和一个私人密钥，私人密钥只有专人才能使用，公共密钥可以广泛传播。如果密钥对中的一个用于加密，另一个一定用于解密。公共/私人密钥对算法很慢，一般只用于加密小批数据，例如用于加密会话密钥。CryptoAPI支持两种基本的编码方法：流式编码和块编码。流式编码在明码文本的每一位上创建编码位，速度较快，但安全性较低。块编码在一个完整的块上（一般为64位）上工作，需要使用填充的方法对要编码的数据进行舍入，以组成多个完整的块。这种算法速度较慢，但更安全。 </font>
		</p>
		<p>
				<font color="#000000">三：下面进入具体的编程  <br />一： Creating a Key Container and Generating Keys<br />  创建一个密钥容器，在进行加密，解密</font>
				<a href="http://www.chinaitpower.com/Soft/Tools/File/index.html" target="_blank">
						<font color="#000000">文件</font>
				</a>
				<font color="#000000">，并且签名的时候，必须需要一个公/私钥对，下面我们就来创建默认的密钥容器，要注意的是创建密钥容器并不会自动产生公/私钥对.<br />  下面是我们</font>
				<a href="http://www.chinaitpower.com/Dev/index.html" target="_blank">
						<font color="#000000">程序</font>
				</a>
				<font color="#000000">的任务：<br />  1，假如密钥容器不存在则创建一个。<br />  2，假如签名密钥不存在则在密钥容器里创建一个。<br />  3，假如交换密钥不存在则在密钥容器里创建一个。<br />  4，获取CSP中的一些参数<br />  下面是具体的步骤：<br />  1，连接缺省的CSP<br />BOOL WINAPI CryptAcquireContext(<br />  HCRYPTPROV* phProv,   //out<br />  LPCTSTR pszContainer, //in<br />  LPCTSTR pszProvider,  //in<br />  DWORD dwProvType,     //in<br />  DWORD dwFlags         //in<br />);<br />第一个参数是返回的CSP句柄，第二个是密钥容器的名字，第三个是A null-terminated string that specifies the name of the CSP to be used.第四个是指定提供的类型。例如：CryptAcquireContext(&amp;hProv, NULL, NULL, PROV_RSA_FULL, 0))；<br />如果当前机器的未曾设置过缺省的密钥容器，因此必须为机器创建缺省的密钥容器。 <br />CryptAcquireContext( &amp;hCryptProv, UserName, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)大家有没有看到，只是最后一个参数不同而已，多了一个CRYPT_NEWKEYSET而已。<br />  2，取得CSP的参数<br />BOOL WINAPI CryptGetProvParam(<br />  HCRYPTPROV hProv,<br />  DWORD dwParam,<br />  BYTE* pbData,<br />  DWORD* pdwDataLen,<br />  DWORD dwFlags<br />);<br />第一个参数是CSP的句柄，第二个参数是需要取得的具体参数对象（类型比较多，具体请看MSDN）。<br />例子：CryptGetProvParam(hCryptProv, PP_CONTAINER, (BYTE *)szUserName, &amp;dwUserNameLen, 0)<br />  3，函数返回所获取密钥类型的句柄（0表失败，非0表成功）<br />BOOL WINAPI CryptGetUserKey(<br />  HCRYPTPROV hProv,<br />  DWORD dwKeySpec,<br />  HCRYPTKEY* phUserKey<br />);<br />  参数比较简单，只谈谈第二次参数，它可以是AT_KEYEXCHANGE（交换密钥） or AT_SIGNATURE（签名密钥），例如：<br />CryptGetUserKey(hCryptProv,AT_KEYEXCHANGE,&amp;hKey)<br />  4，产生一个随机的交换密钥或者公/私钥对<br />BOOL WINAPI CryptGenKey(<br />  HCRYPTPROV hProv,<br />  ALG_ID Algid,<br />  DWORD dwFlags,<br />  HCRYPTKEY* phKey<br />)；<br />ALG_ID 表明产生私钥所使用的算法。有如下参数：<br /></font>
				<a href="http://www.microsoft.com/" target="_blank">
						<font color="#000000">微软</font>
				</a>
				<font color="#000000">提供的基本算法<br />CALG_MD2，CALG_MD5，CALG_SHA，CALG_SHA1，CALG_MAC，CALG_HMAC，CALG_SSL3_SHAMD5，CALG_MD2，CALG_MD2<br />CALG_RSA_SIGN，CALG_RSA_KEYX，CALG_RC2，CALG_RC4，CALG_DES<br /></font>
				<a href="http://www.microsoft.com/" target="_blank">
						<font color="#000000">微软</font>
				</a>
				<font color="#000000">提供的增强型算法：<br />CALG_MD2，CALG_MD5，CALG_SHA，CALG_SHA1<br />CALG_MAC，CALG_HMAC ，CALG_SSL3_SHAMD5，CALG_RSA_SIGN，CALG_RSA_KEYX，CALG_RC2，CALG_RC4，CALG_DES，CALG_3DES_112，CALG_3DES<br />使用DH的CSP有如下两个参数，CALG_DH_EPHEM，CALG_DH_SF<br />使用公开密钥算法：AT_KEYEXCHANGE，AT_SIGNATURE<br />dwFlags,，表示密钥使用的长度，参数可以为0，采用默认的密钥长度。或者是进行如下几个参数的或：<br />CRYPT_ARCHIVABLE：表示在句柄在关闭之前都能够被导出<br />CRYPT_CREATE_SALT：表示密钥按照一个salt value来随机产生。<br />CRYPT_EXPORTABLE：表示密钥可以从CSP中导出到BLOB，因为会话密钥产生是必须可导出的，所以必须设置<br />CRYPT_NO_SALT：表示没有SALT VALUE获取allocated for a forty-bit symmetric key<br />CRYPT_PREGEN：表示在DH或者DSS密钥产生必须有个初始化。<br />例如：CryptGenKey(hCryptProv,AT_KEYEXCHANGE,0,&amp;hKey)<br />  5，释放CSP句柄<br />BOOL WINAPI CryptReleaseContext(<br />  HCRYPTPROV hProv,<br />  DWORD dwFlags //保留字，现在必须为0<br />);<br />  6，为CSP增加一个reference count（用来跟踪COM对象的整数值，当对象创建，值为1。每次对对象的操作都将增加，而对对象的关闭将减少，当值为0是，对象释放，所以与对象相关操作将无效）<br />BOOL WINAPI CryptContextAddRef(<br />  HCRYPTPROV hProv,<br />  DWORD* pdwReserved,  //保留字，必须为NULL<br />  DWORD dwFlags        //保留字，必须为0<br />);</font>
		</p>
		<p>
				<font color="#000000">  二：Deriving a Session Key from a Password<br />  1，连接CSP<br />  2，使用CryptCreateHash产生一个空的HASH对象<br />  3，对密码进行HASH处理<br />  4，释放HASH以及密码对象<br />  5，释放CSP<br />  下面是具体的步骤：<br />  1，CryptCreateHash初始化一个HASH对象<br />BOOL WINAPI CryptCreateHash(<br />  HCRYPTPROV hProv,  //in<br />  ALG_ID Algid,      //in<br />  HCRYPTKEY hKey,    //in<br />  DWORD dwFlags,     //in保留字，必须为0<br />  HCRYPTHASH* phHash //out<br />);<br />第二个参数是指定HASH算法，有CALG_HMAC,CALG_MAC,CALG_MD2,CALG_MD5,CALG_SHA,CALG_SHA1,CALG_SSL3_SHAMD5。第三个参数对于那些keyed hash，例如HMAC，MAC算法。但是nonkeyed算法，必须设置为0。<br />  2，CryptHashData对数据使用HASH<br />BOOL WINAPI CryptHashData(<br />  HCRYPTHASH hHash,  //in,HASH对象句柄<br />  BYTE* pbData,      //in,待HASH的数据<br />  DWORD dwDataLen,   //in,待HASH数据的长度，当dwFlags为CRYPT_USERDATA为0时，必须为0<br />  DWORD dwFlags      //in,一般为0，或者为CRYPT_USERDATA（用在用户进入</font>
				<a href="http://www.chinaitpower.com/System/index.html" target="_blank">
						<font color="#000000">系统</font>
				</a>
				<font color="#000000">时需要输入PIN）<br />);<br />  3，CryptDeriveKey从某一数据产生会话密钥，他有点类似CryptGenKey，但是他产生的会话密钥来自固定数据，而CryptGenKey是随机产生的。并且不能产生公/私钥对<br />BOOL WINAPI CryptDeriveKey(<br />  HCRYPTPROV hProv,      //in,CSP句柄<br />  ALG_ID Algid,          //in,指定的算法，类似CryptGenKey<br />  HCRYPTHASH hBaseData,  //in,HASH对象的句柄<br />  DWORD dwFlags,         //in,指定产生密钥的类型<br />  HCRYPTKEY* phKey       //in,out产生的密钥句柄地址<br />);<br />例如：CryptDeriveKey(hCryptProv, CALG_RC2, hHash, CRYPT_EXPORTABLE, &amp;hKey)<br />  4，CryptDestroyHash(hHash);<br />  5, CryptDestroyKey(hKey);<br />  6, 在这里发现一个不错的函数，就是那种提示输入密码的命令行（屏幕只会出现***）<br />  void GetConsoleInput(char* strInput, int intMaxChars)<br />{<br /> char ch;<br /> char minChar = ' ';<br /> minChar++;<br /> ch = getch();<br /> while (ch != '\r')<br /> {<br />  if (ch == '\b' &amp;&amp; strlen(strInput) &gt; 0)<br />  {<br />   strInput[strlen(strInput)-1]   = '\0';<br />   printf("\b \b");<br />  }<br />  else if (ch &gt;= minChar &amp;&amp; strlen(strInput) &lt; intMaxChars)<br />  {<br />   strInput[strlen(strInput)+1] = '\0';<br />   strInput[strlen(strInput)]   = ch;<br />   putch('*');<br />  }<br />  ch = getch();<br /> }<br /> putch('\n');<br />}</font>
		</p>
		<p>
				<font color="#000000">  三：Duplicating,setting and getting Session key<br />  1,连接CSP<br />  2,使用CryptGenKey产生一个会话密钥<br />  3,CryptDuplicateKey复制会话密钥<br />  4,CryptSetKeyParam改变密钥产生的过程<br />  5,CryptGenRandom产生随机数<br />具体过程。<br />1，CryptDuplicateKe复制会话密钥<br />BOOL WINAPI CryptDuplicateKey(<br />  HCRYPTKEY hKey,      //in 会话密钥句柄<br />  DWORD* pdwReserved,  //in 保留字，必须为NULL<br />  DWORD dwFlags,       //in 保留字，必须为0<br />  HCRYPTKEY* phKey     //out 新的会话密钥<br />);<br />2,CryptSetKeyParam定制会话密钥的参数<br />BOOL WINAPI CryptSetKeyParam(<br />  HCRYPTKEY hKey,<br />  DWORD dwParam,  //in 很多，具体请看MSDN<br />  BYTE* pbData,<br />  DWORD dwFlags  //in  只有在dwParam=KP_ALGID才被使用<br />);<br />例如CryptSetKeyParam(hOriginalKey, KP_MODE, (BYTE*)&amp;dwMode, 0)(dwMode = CRYPT_MODE_ECB)<br />3,CryptGenRandom为空间产生随机字节<br />BOOL WINAPI CryptGenRandom(<br />  HCRYPTPROV hProv,<br />  DWORD dwLen,    //需要产生的随机比特数<br />  BYTE* pbBuffer  //需要返回数据的空间，这个pbBuffer可以等于CryptSetKeyParam的pbData<br />);<br />例如：CryptGenRandom(hCryptProv, 8, pbData)<br />4,CryptGetKeyParam获取密钥的一些参数<br />BOOL WINAPI CryptGetKeyParam(<br />  HCRYPTKEY hKey,<br />  DWORD dwParam,     //in,参数众多<br />  BYTE* pbData,      //out，获取BYTE数据的指针<br />  DWORD* pdwDataLen, //out，获取BYTE数据的长度<br />  DWORD dwFlags      //关键字，必须为0<br />);<br />例如：CryptGetKeyParam(hKey, KP_IV, pbData, &amp;dwCount, 0)</font>
		</p>
		<p>
				<br />
				<font color="#000000">  四：Exporting a Session Key<br />  1,连接CSP<br />  2,CryptGetUserKey获取公/私钥对和交换密钥，公私钥用来签名，而交换密钥用来导出会话密钥<br />  3,CryptGenKey产生会话密钥<br />  4,CryptExportKey创建简单包含有会话密钥的key BLOB<br />  5,释放处理：<br />  具体过程：<br />1,CryptExportKey函数导出密钥<br />BOOL WINAPI CryptExportKey(<br />  HCRYPTKEY hKey,     //需要导出的密钥句柄<br />  HCRYPTKEY hExpKey,  //将待导出密钥用交换密钥进行加密，假如是公开的BLOG当然就设置为0<br />  DWORD dwBlobType,   //指定导出的密钥BLOB类型。六个参数见MSDN<br />  DWORD dwFlags,      //CRYPT_DESTROYKEY，CRYPT_SSL2_FALLBACK，CRYPT_OAEP<br />  BYTE* pbData,       //导出的数据指针，以后就可以将这个数据写如磁盘或者别的任务。<br />  DWORD* pdwDataLen   //导出的数据长度<br />);<br />例如：CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, pbKeyBlob, &amp;dwBlobLen)<br />2，CryptImportKey将密钥从BLOB转换到CSP中<br />BOOL WINAPI CryptImportKey(<br />  HCRYPTPROV hProv,  //CSP句柄<br />  BYTE* pbData,      //待转换的BLOB数据<br />  DWORD dwDataLen,   //待转换的数据长度<br />  HCRYPTKEY hPubKey, //对BLOB解密的公钥，譬如上面是用交换密钥密钥加密的，就用交换密钥解密<br />  DWORD dwFlags,     //目前还只应用在当一对公/私钥从PRIVATEKEYBLOB中加入CSP中这种情况。<br />  HCRYPTKEY* phKey   //out导入的密钥<br />);<br />例如：CryptImportKey(hProv,pbKeyBlob,dwBlobLen,0,0,&amp;hPubKey)</font>
		</p>
		<p>
				<br />
				<font color="#000000">  五：Encoding and Decoding Messages<br />  编码的处理过程<br />  1，将待编码的数据转化为合适的格式，使用<br />  2，调用CryptMsgOpenToEncode，passing the necessary argument;<br />  3, 调用CryptMsgUpdate函数多次，最后一次调用时，将final参数设置为true<br />  4, 调用CryptMsgGetParam来获取一个需要得到的参数。<br />  5, 调用CryptMsgClose来关闭消息<br />  解码的处理过程<br />  1，检查申请的放编码后数据的空间，利用函数CryptMsgCalculateEncodedLength.<br />  2，调用函数CryptMsgOpenToDecode,passing the necessary argument；<br />  3，调用CryptMsgUpdate一次，这将导致合适的动作去处理信息，以来于信息的格式<br />  4，一些额外的处理，例如额外的解密或者是验证，调用CryptMsgControl,<br />  5，调用CryptMsgGetParam来获取需要得到的参数<br />  6，调用CryptMsgClose来关闭消息<br />  具体的函数介绍：<br />  1，CryptMsgCalculateEncodedLength计算所需要的存储编码的最大空间值<br />DWORD WINAPI CryptMsgCalculateEncodedLength(<br />  DWORD dwMsgEncodingType,//指定编码类型。一般为X509_ASN_ENCODING|PKCS_7_ASN_ENCODING<br />  DWORD dwFlags,<br />  DWORD dwMsgType,<br />  const void* pvMsgEncodeInfo, //in 指向待编码的数据，数据类型依赖于dwMsgType<br />  LPSTR pszInnerContentObjID,<br />  DWORD cbData                 //in 比特数的容量<br />);<br />第二个参数：CMSG_BARE_CONTENT_FLAG，CMSG_DETACHED_FLAG，CMSG_CONTENTS_OCTETS_FLAG，CMSG_CMS_ENCAPSULATED_CONTENT_FLAG<br />第三个参数：CMSG_DATA,CMSG_SIGNED,CMSG_ENVELOPED,CMSG_SIGNED_AND_ENVELOPED,CMSG_HASHED,CMSG_ENCRYPTED<br />第五个参数：szOID_RSA_data,szOID_RSA_signedData,szOID_RSA_envelopedData,szOID_RSA_signEnvData,szOID_RSA,digestedData ,<br />szOID_RSA_encryptedData,SPC_INDIRECT_DATA_OBJID,NULL<br />返回值：返回需要的一个加密信息所需要的长度<br />  2，CryptMsgOpenToEncode打开一个消息以便进行编码，返回打开消息的句柄<br />  HCRYPTMSG WINAPI CryptMsgOpenToEncode(<br />  DWORD dwMsgEncodingType,      //指定编码类型。一般为X509_ASN_ENCODING|PKCS_7_ASN_ENCODING<br />  DWORD dwFlags,                <br />  DWORD dwMsgType,              <br />  const void* pvMsgEncodeInfo,<br />  LPSTR pszInnerContentObjID,    //和CryptMsgCalculateEncodedLength一样<br />  PCMSG_STREAM_INFO pStreamInfo //当流没被使用时，该参数为NULL<br />);<br />第二个参数：CMSG_BARE_CONTENT_FLAG,CMSG_DETACHED_FLAG,CMSG_CONTENTS_OCTETS_FLAG,CMSG_CMS_ENCAPSULATED_CONTENT_FLAG,<br />CMSG_CRYPT_RELEASE_CONTEXT_FLAG<br />第三个参数：<br />CMSG_DATA(Not used),CMSG_SIGNED,CMSG_SIGNED_ENCODE_INFO,CMSG_ENVELOPED,CMSG_ENVELOPED_ENCODE_INFO <br />CMSG_SIGNED_AND_ENVELOPED(Not currently implemented),CMSG_HASHED <br />  3，CryptMsgOpenToDecode打开一个消息以便进行解码，返回打开消息的句柄<br />  CRYPTMSG WINAPI CryptMsgOpenToDecode(<br />  DWORD dwMsgEncodingType,     //指定编码类型。一般为X509_ASN_ENCODING|PKCS_7_ASN_ENCODING<br />  DWORD dwFlags,   //CMSG_DETACHED_FLAG，CMSG_CRYPT_RELEASE_CONTEXT_FLAG<br />  DWORD dwMsgType, //CMSG_DATA,CMSG_ENVELOPED,CMSG_HASHED,CMSG_SIGNED,CMSG_SIGNED_AND_ENVELOPED<br />  HCRYPTPROV hCryptProv,    //指定使用HASHING的句柄，一般设置为0<br />  PCERT_INFO pRecipientInfo,//保留字，必须为NULL<br />  PCMSG_STREAM_INFO pStreamInfo//假如流没被使用，必须为NULL<br />);<br />  4，CryptMsgUpdate增加内容到加密信息中<br />BOOL WINAPI CryptMsgUpdate(<br />  HCRYPTMSG hCryptMsg, //待更新的加密信息句柄<br />  const BYTE* pbData,  //待编码/解码的数据<br />  DWORD cbData,        // pbData 的数据长度<br />  BOOL fFinal          <br />);<br />第四个参数：当CMSG_DETACHED_FLAG没有设置，并且信息由CryptMsgOpenToDecode或CryptMsgOpenToEncode打开，那么fFinal被设置为TRUE，并且CryptMsgUpdate只被调用一次。当CMSG_DETACHED_FLAG被设置，并且信息由 CryptMsgOpenToEncode打开，那么仅在最后一次调用CryptMsgUpdate才被设置为TRUE。当CMSG_DETACHED_FLAG被设置，并且信息由CryptMsgOpenToDecode打开，那么仅在信息头单独被处理时CryptMsgUpdate才被设置为TRUE。<br />  5，CryptMsgGetParam在数据编码/解码后获取参数<br />  BOOL WINAPI CryptMsgGetParam(<br />  HCRYPTMSG hCryptMsg,  //in 信息句柄<br />  DWORD dwParamType,   //in 参数众多，参见MSDN<br />  DWORD dwIndex,       //in 可适用的返回参数句柄,假如参数没有被获取，则被忽略或则为0<br />  void* pvData,        //out 获取的数据指针<br />  DWORD* pcbData      //in,out数据长度<br />);<br />   6，CryptMsgClose关闭信息句柄<br />BOOL WINAPI CryptMsgClose(<br />  HCRYPTMSG hCryptMsg<br />);<br />具体的例子：<br />cbEncodedBlob = CryptMsgCalculateEncodedLength(<br />             MY_ENCODING_TYPE,       // Message encoding type<br />             0,                      // Flags<br />             CMSG_DATA,              // Message type<br />             NULL,                   // Pointer to structure<br />             NULL,                   // Inner content object ID<br />             cbContent))             // Size of content<br />hMsg = CryptMsgOpenToEncode(<br />          MY_ENCODING_TYPE,        // Encoding type<br />          0,                       // Flags<br />          CMSG_DATA,               // Message type<br />          NULL,                    // Pointer to structure<br />          NULL,                    // Inner content object ID<br />          NULL))                   // Stream information (not used)<br />CryptMsgUpdate(<br />        hMsg,         // Handle to the message<br />        pbContent,    // Pointer to the content<br />        cbContent,    // Size of the content<br />        TRUE))        // Last call<br />{<br />CryptMsgGetParam(<br />               hMsg,                      // Handle to the message<br />               CMSG_BARE_CONTENT_PARAM,   // Parameter type<br />               0,                         // Index<br />               pbEncodedBlob,             // Pointer to the BLOB<br />               &amp;cbEncodedBlob))           // Size of the BLOB<br />CryptMsgClose(hMsg);<br />hMsg = CryptMsgOpenToDecode(<br />               MY_ENCODING_TYPE,      // Encoding type.<br />               0,                     // Flags.<br />               CMSG_DATA,             // Look for a data message.<br />               NULL,                  // Cryptographic provider.<br />               NULL,                  // Recipient information.<br />               NULL))                 // Stream information.</font>
		</p><img src ="http://www.blogjava.net/security/aggbug/56869.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/security/" target="_blank">david.turing</a> 2006-07-05 23:18 <a href="http://www.blogjava.net/security/articles/56869.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>