CSP软件不小心把对称尺删了怎样恢复急求贷款

【伪教程】绘图软件sai和csp的使用小技巧_特兰克斯吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0可签7级以上的吧50个
本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:3,276贴子:
【伪教程】绘图软件sai和csp的使用小技巧
你想用软件绘图却总是觉得不太会用软件,或者未能充分认识软件?想了解(非触)我的软件操作技巧,可以往这里瞄一眼。这里主要介绍sai和csp,而且只是简单介绍。或许能帮到你一点点,我都会很开心。如果预想下面会突然出现伤眼的渣图,请自觉戴好护目镜。当然我不是非常了解这些两个软件,也很少用ps,同时也不是美术专业,不足之处请指出。
众所周知sai是一个绘图...
不知道的软件问我 我知...
听说你要打我,还对我的城池图谋不轨。
太长不看。不过还是顶下吧,沙发
【入门级】图层除非你有很好的绘画基础或者特别的需要,不然,不要自始至终都只在同一个图层里作画sai的普通图层(标量图层)、钢笔图层
优动漫paint个人版(clip studio paint pro),简称csp。关于图层的属性不用我介绍你也很容易懂。这是在画一幅大图,电脑跑不动了。提醒:右下角有一个搜狗,这是为了截图而留着它,正式作画时务必将语言选择为“中文(中国)”,即美式键盘状态,否则,会影响到快捷键的使用。
【2.锚点修正】sai的锚点在上面已介绍了你是否对自己画的歪歪扭扭线条感到抓狂?你是否像画素描那样画毛毛线来修正歪扭的线条?或者你在猛擦猛画,而有些人偷懒不想涂改。锚点修正可以帮你移动、扭曲一条矢量线条。看到下面这幅渣图,或许有人会大喊:“Tr不是这种脸型!”没事,修正一下。先生漫画中,Tr的下巴夹角一般不小于90°。没必要完全按照模型的样子画人物的线条,而且模型的手过于大。如果对修正后的效果不满意,就用橡皮擦改吧。(Tr的打手机姿势,求号码(* ̄▽ ̄)y)或许你见到钢笔画出的线条很粗糙,怀疑软件不好,这是设定为漫画用途的原因,设为插画用途则可以画高清线条。
【3.贴网点】我对网点纸不了解,就不详细介绍了。既然有吧友想了解网点,就提一下。老鸟的漫画不贴网点胶(或网点纸)建个选区,再贴网点
看标题还有1L就觉得好复杂~哈哈哈
【4.csp-控制出入锋】没有也能画出有粗细变化的线→你是否在鼠绘的时候被鼠标的笨拙逼到发疯?→还在用橡皮擦将一条线的两头擦尖吗?→鼠标真的只能撸出一条没有粗细变化的肥线了吗?——有些情况下不是。顺带看下这个……肌肉?(反正是草稿,我三心两意弄成这样也没关系吧。画的时候不在状态,好困)这是板绘效果,比例君溜了。●具有控制出入锋功能的“效果线”能自动帮你将一条线的两端处理成尖头。有些地方不需要尖,重修矢量线宽,不过会有锯齿。●的铅笔也能在鼠绘的时候撸出有笔压变化的线。
学会计,到佰平!
【5.】画管状物→对于管道,不同人有不同的绘制方法。你是否直接手描而花费很多精力?→或者画一条线——复制——粘贴——移动位置——修改?○小白专用曲线尺,描好需要的方向后,双击尽头处○不管怎样画都不会偏离方向如果你的软件没这种尺子,还有其它办法。
【5.β】用sai绘制管状物●将选择笔的“最小直径”调至100%●用铅笔仔细描出,再做修改。如果你需要厚涂,不必这样弄线稿。有了上述方法,还怕制作不出好的线稿?(有水印)
太帅了啊!!。收藏了!! 最后的特兰,真的好帅啊
话说第二个绘画软件是=_=  ﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹏₯㎕﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍在这个城市里最高的地方,跟你一起俯瞰万家灯火。感觉你的生命,是我灵魂的归属。    ✄┈┈┈┈┈┈┈┈
楼楼做的说明和介绍看得出是动了脑子而且很认真的做出来的鼓励楼楼多发这样的贴!两个软件都是常用的,楼楼可以继续写的更细更多,期待更新最好能再系统一点,一个软件介绍完,再介绍另一个。不然我看到二楼还是sai,三楼就是,四楼又是sai了,有点接不上而且。。。恩,还是希望再系统一点,总觉得看完之后什么也没有看明白这大概是我错觉吧
【6.此技巧适用于一切可同时编辑多个文件,可建立选区的软件】高还原度的人物线稿→尽管你十分努力地练习画Trunks,上场创作的时候还是会画走形?○用一种类似偷窃的办法助你一臂之力!●截取并复制动画原图中的想要部分。(找不到番外篇悟饭与特兰克斯原视频,也难以登录优酷,只好从一个再加工的不完整的视频中截图)●粘贴到自己的画中作底稿,步骤似上图。适当扩大,降低此图层的不透明度。●因为此截图的Trunks的样子不是我最想要,不必完全模仿。完全的仿品不能当原创来发布!●如果有些地方吃不准,可以拿漫画书在一边参考,注意14岁Trunks的样子和17岁的区别,我拿的漫画书是使用原视频截图加工成的。成品和原图的偏差,眼神做了修改。我一般不会这样来制作原创品。尽量别形成一个坏的依赖习惯,提倡依靠自我。
【7.csp】对文字进行变形●旧版本的没有文字工具,下载了sai的文字工具,但安装失败。sai狂热者可考虑用sai2,sai2新增文字功能。●在Trunks的衣服上打字,我用的字体是黑体。●不能直接在文字图层里对文字进行复杂的变形,要先将文字图层栅格化。●建好选区之后,选择“自由变换”,有必要的再进行网格变形。○确定变换效果之后别忘了点击“〇”。●用ps还能进行更复杂的变形,或者液化,使文字更贴合衣服。
虽然看不懂但是必须顶
【8.csp】运用透视线画背景(SAI2也出透视线了)背景部分就,不完全模仿原著。●画背景线条用的色彩有异于人物的。●打开视频截图,方便设置透视线。●使用“操作”调整已设置好的透视线。
【9.csp】关于放射曲线这栋楼,怎么说呢?别人会用云尺来画,我用的是放射曲线尺。使用放射曲线尺的时候,如果你要的曲线越弯,就多点击几下(就是多些曲线弯折的点),双击就会生成尺的尽头。←为什么上图提示“需要另画的两条”?因为线是旋转状的。●画出的线受“放射曲线尺”本身的长度的影响,画出的线长度过长,就会失控。不明白上述是怎么回事就看看别人的手绘方法视频来自:
【10.能进行复制、粘贴操作,可同时编辑多幅图的软件都适用】图像在不同图层间的转移→你是否在绘画的时候突然发现——画错图层了?→你是否会极度苦恼,想着又要撤销掉,重新画了?用不着这么大的折腾,只要你本来想画在别的图层的那部分和在此图层中的图没太多粘连,就可以将它剪切下来,粘贴在另外的图层上。○选定你画错图层的那部分,剪切。○粘贴,会产生一个新图层。如果不喜欢太多图层,将其和其它图层合并(向下合并)。
【11.csp和sai适用】给画图区域一个的空间→你是否感觉在这么小的画图区域上作业就像管中窥豹?其实画图区域的大小可调。如果你在一段长时间内不需对侧边的工具栏进行操作,就将它们隐藏。方法①:看到圈中的按钮了没有?可伸缩。方法②:按键盘的“Tab▕← →▕&键。重按,工具栏就会弹出来了。
【插播:此帖该怎么阅读】【序号。本技巧用的是的软件】只注明“csp”,即本技巧一般只适用于csp→你可能遇到的问题←本技巧的疑点●重要要点○次重要要点
【插播:新手必知】1.分辨率●一般的专业绘图软件都可以设置图像的分辨率。像Windows画图这种非专业的就不能,它的默认分辨率是72dpi。●人眼的能识别的最高分辨率是300dpi。一般将图像的分辨率设为300dpi就足够。大分辨率主要是适用于印刷。●分辨率越高(数值大),画图时就越消耗内存。分辨率越低,图像质量越高。●如果你的画稿要投给漫画杂志,需按他们对画稿的要求来设置。举例:csp的图像设置
【插播:新手必知】2.文件格式○图的格式有多种,在网上常见的是jpg、、(会动的图)。●如果你的作品需要分多次进行编辑,务必将它保存为可以分图层的格式。●不可保存图层的格式如:jpg、、、●可以保存图层的格式如:、psb、(sai的专用格式)、lip/csp(csp的专用格式)。也有自己的专用格式。●格式的文件可以在多个不同的软件中编辑。○jpg是一种有损性压缩格式,这个格式的图便于在网上发布。举例:ps的文件预设
【插播:新手必知】3.作画过程中,经常点击保存→你是否曾经在作画进行中突然断电,你的作品还没保存,心血都竹篮打水一场空?★特别注意!新建了一个文件,软件并不会将你的工作都自动记录下来,在你第二次打开它的时候就是你上次完成到哪里的状态。●实际情况是——你必须先将一个新建的文件另存为你需要的格式,再在工作后一段时间点击“文件-保存”,或者点击“保存”的快捷按钮。●另存为和保存(或者是其它名称)的区别:“另存为”会产生一个新的文件,“保存”则不会。“保存”是将工作出来的内容写入文件。
((吧里不是有很多者吗?上面这些简单的东西并不难懂吧。即使看起来不明白,自己动手试就会变得简单了,甚至都不必看得那么多。既然此贴反响甚少,我也不怎么更了,又到开学的日子。ㄟ( ▔, ▔ )ㄏ))目前,csp在国内的普及率比不上sai,没用过csp的吧友可到csp的国内或国外的官网看介绍。~~~~~~进入到上色阶段,不同软件的操作方法就大相径庭,不同画风的上色步骤差别更大,下面介绍的将是模仿龙珠官图的上色风格,即动画式胶片上色风格。【插播】csp的官方视频日语,PRO版视频来自:
难以登录。试试马克几笔日语EX版视频来自:
马克马克,传不了视频就删掉汉语,EX版视频来自:
贴吧热议榜
使用签名档&&
保存至快速回贴CSP开发基础--CayptAPI函数库介绍
CSP开发基础--CayptAPI函数库介绍
[摘要:根基减稀函数 根基减稀函数为开辟减稀运用顺序供应了充足灵巧的空间。全部CSP 的通信皆是经过 那些函数。 一个CSP 是完成全部减稀操纵的自力模块。正在每个运用顺序中最少须要提]
基本加密函数
基本加密函数为开发加密应用程序提供了足够灵活的空间。所有CSP的通讯都是通过这些函数。一个CSP是实现所有加密操作的独立模块。在每一个应用程序中至少需要提供一个CSP来完成所需的加密操作。如果使用多于一个以上的CSP,在加密函数调用中就要指定所需的CSP。微软基本加密提供者(Microsoft
Base Cryptographic Provider),是缺省绑定到CryptoAPI 里的。如果没有指定其他CSP时,这个CSP 就是却省的。每一个CSP对CryptoAPI
提供了一套不同的实现。一些提供了更加强大的加密算法,而其他一些CSP包含了对硬件的支持,比如智能卡。另外,一些CSP 偶尔和使用者直接通讯,比如数字签名就使用了用户的签名私钥。
基本加密函数包含了以下几种:
1.1服务提供者函数
应用程序使用服务提供者函数来连接和断开一个CSP。下面就是主要的API:
CryptAcquireContext获得指定CSP的密钥容器的句柄
CryptContextAddRef对HCRYPTPROV句柄增加一个应用计数
CryptEnumProviders枚举当前计算机中的CSP
CryptEnumProviderTypes枚举CSP的类型
CryptGetDefaultProvider对于指定CSP类型的却省CSP
CryptGetProvParam得到一个CSP的属性
CryptInstallDefaultContext安装先前得到的HCRYPTPROV上下文作为当前却省的上下文
CryptReleaseContext释放由CryptAcquireContext得到的句柄
CryptSetProvider和CryptSetProviderEx为指定CSP类型指定一个却省的CSP
CryptSetProvParam指定一个CSP的属性
CryptUninstallDefaultContext删除先前由CryptInstallDefaultContext安装的却省上下文
1.2密钥的产生和交换函数
密钥产生函数创建、配置和销毁加密密钥。他们也用于和其他用户进行交换密钥。下面就是主要的一些函数:
CryptAcquireCertificatePrivateKey对于指定证书上下文得到一个HCRYPTPROV句柄和dwKeySpec
CryptDeriveKey从一个密码中派生一个密钥
CryptDestoryKey销毁密钥
CryptDuplicateKey制作一个密钥和密钥状态的精确复制
CryptExportKey把CSP的密钥做成BLOB 传送到应用程序的内存空间中
CryptGenKey创建一个随机密钥
CryptGenRandom产生一个随机数
CryptGetKeyParam得到密钥的参数
CryptGetUserKey得到一个密钥交换或签名密钥的句柄
CryptImportKey把一个密钥BLOB传送到CSP 中
CryptSetKeyParam指定一个密钥的参数
1.3编码/解码函数
有一些编码/解码函数,他们可以用来对证书、证书撤销列表、证书请求和证书扩展进行编码和解码。
以下就是这几个函数:
CryptDecodeObject对lpszStructType结构进行解码
CryptDecodeObjectEx对lpszStructType结构进行解码,此函数支持内存分配选项
CryptEncodeObject对lpszStructType结构进行编码
CyptEncodeObjectEx对lpszStructType结构进行编码,此函数支持内存分配选项
1.4数据加密/解密函数
这些函数支持数据的加密/解密操作。
CryptEncrypt 和CryptDecrypt 要求在被调用前指定一个密钥。
注:这个密钥可以由CryptGenKey、CryptDeriveKey 或CryptImportKey 产生。创建密钥时要指定加密算法。
CryptSetKeyParam函数可以指定额外的加密参数。
CryptDecrypt使用指定加密密钥来解密一段密文
CryptEncrypt使用指定加密密钥来加密一段明文
CryptProtectData执行对DATA_BLOB结构的加密
CryptUnprotectData执行对DATA_BLOB结构的完整性验证和解密
1.5哈希和数字签名函数
这些函数在应用程序中完成计算哈希、创建和校验数字签名。
CryptCreateHash创建一个空哈希对象
CryptDestoryHash销毁一个哈希对象
CryptDuplicateHash复制一个哈希对象
CryptGetHashParam得到一个哈希对象参数
CryptHashData对一块数据进行哈希,把它加到指定的哈希对象中
CryptHashSessionKey对一个会话密钥进行哈希,把它加到指定的哈希对象中
CryptSetHashParam设置一个哈希对象的参数
CryptSignHash对一个哈希对象进行签名
CryptVerifySignature校验一个数字签名
1.6函数详解
1.6.1获得CSP密钥容器句柄
1.6.1.1 CryptAcquireContext
BOOL WINAPI CryptAcquireContext(
HCRYPTPROV *phProv,
LPCTSTR pszContainer,
LPCTSTR pszProvider,
DWORD dwProvType,
DWORD dwFlags
phProv[out] CSP句柄指针
pszContainer[in]密钥容器名称, 指向密钥容器的字符串指针。如果dwFlags为CRYPT_VERIFYCONTEXT,pszContainer必须为NULL。
pszProvider[in]指向CSP名称的字符串指针。如果为NULL,就使用却省的CSP。
dwProvType[in]CSP类型。下表是就中常见的CSP类型
对称加密算法
PROV_RSA_FULL
PROV_RSA_SIG
PROV_RSA_SCHANNEL
Triple DES
PROV_DSS_DH
CYLINK_MEK
PROV_DH_SCHANNEL
Triple DES
PROV_FORTEZZA
PROV_MS_EXCHANGE
dwFlags[in]标志:
CRYPT_VERIFYCONTEXT
指出应用程序不需要使用公钥/私钥对,如程序只执行哈希和对称加密。只有程序需要创建签名和解密消息时才需要访问私钥。
CRYPT_NEWKEYSET
使用指定的密钥容器名称创建一个新的密钥容器。如果pszContainer为NULL,密钥容器就使用却省的名称创建。
CRYPT_MACHINE_KEYSET
由此标志创建的密钥容器只能由创建者本人或有系统管理员身份的人使用。
CRYPT_DELETEKEYSET
删除由pszContainer指定的密钥容器。如果pszContainer 为NULL,缺省名称的容器就会被删除。此容器里的所有密钥对也会被删除。
CRYPT_SLIENT
应用程序要求CSP不显示任何用户界面。
这个函数是用来取得指定CSP密钥容器句柄,以后的任何加密操作就是针对此CSP 句柄而言。函数首先查找由dwProvType和pszProvider
指定的CSP,如果找到了CSP,函数就查找由此CSP指定的密钥容器。由适当的dwFlags 标志,这个函数就可以创建和销毁密钥容器,如果不要求访问私钥的话,也可以提供对CSP临时密钥容器的访问。
1.6.1.2 CryptReleaseContext
BOOL WINAPI CryptReleaseContext(
HCRYPTPROV hProv,
DWORD dwFlags
hProv[in]由CryptAcquireContext获得的CSP
dwFlags[in]保留。必须为0。
此函数释放CSP的句柄。对于每一次调用,CSP 的引用计数都减1。当引用计数为0时,CSP上下文就会被系统释放变成无效句柄,以后针对此CSP
句柄的函数不再可用。
此函数并不销毁密钥容器或密钥对。
//--------------------------------------------------------------------
HCRYPTPROV hCryptP
if (CryptAcquireContext(
hCryptProv, NULL,
MS_DEF_PROV,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT))
CryptReleaseContext(hCryptProv, NULL);
1.6.2枚举CSP
4.1.6.2.1 CryptEnumProviders
BOOL WINAPI CryptEnumProviders(
DWORD dwIndex,
DWORD *pdwReserved,
DWORD dwFlags,
DWORD *pdwProvType,
LPTSTR pszProvName,
DWORD *pcbProvName
dwIndex[in]枚举下一个CSP的索引。
pdwReserved[in]保留。必须为NULL。
dwFlags[in]保留。必须为NULL。
pdwProvType[out]CSP的类型。
pszProvName[out]指向接收CSP名称的缓冲区字符串指针。此指针可为NULL,用来得到字符串的大小。
pcbProvName[in/out]指出pszProvName字符串的大小。
此函数得到第一个或下一个可用的CSP。如果使用循环,就可以得到计算机上所有可用的CSP。&
1.6.3获得CSP参数
4.1.6.3.1 CryptGetProvParam
BOOL WINAPI CryptGetProvParam(
HCRYPTPROV hProv,
DWORD dwParam,
BYTE *pbData,
DWORD *pdwDataLen,
DWORD dwFlags
hProv[in]CSP句柄。
dwParam[in]指定查询的参数。
PP_CONTAINER
指向密钥名称的字符串
PP_ENUMALGS
不断的读出CSP支持的所有算法
PP_ENUMALGS_EX
比PP_ENUMALGS获得更多的算法信息
PP_ENUMCONTAINERS
不断的读出CSP支持的密钥容器
PP_IMPTYPE
指出CSP怎样实现的
指向CSP名称的字符串
PP_VERSION
CSP的版本号
PP_KEYSIZE_INC
AT_SIGNATURE的位数
PP_KEYX_KEYSIZE_INC
AT_KEYEXCHANGE的位数
PP_KEYSET_SEC_DESCR&
密钥的安全描述符
PP_UNIQUE_CONTAINER
当前密钥容器的唯一名称
PP_PROVTYPE
PP_USE_HARDWARE_RNG
指出硬件是否支持随机数发生器
PP_KEYSPEC
返回CSP密钥的信息
pbData[out]指向接收数据的缓冲区指针。
pdwDataLen[in/out]指出pbData数据长度。
dwFlags[in]如果指定PP_ENUMCONTAINERS,就指定CRYPT_MACHINE_KEYSET。
此函数获得CSP的各种参数。
//-----------------------------------------------------------------
HCRYPTPROV hCryptP
BYTE pbData[1000];
//-------------------------------------------------------------------
//缺省CSP名称
cbData = 1000;
if(CryptGetProvParam(
hCryptProv,
printf(&CryptGetProvParam succeeded.n&);
printf(&Provider name: %sn&, pbData);
printf(&Error reading CSP name. n&);
//--------------------------------------------------------------------
cbData = 1000;
if(CryptGetProvParam(
hCryptProv,
PP_CONTAINER,
printf(&CryptGetProvParam succeeded. n&);
printf(&Key Container name: %sn&, pbData);
printf(&Error reading key container name. n&);
4.1.6.4创建哈希
4.1.6.4.1 CryptCreateHash
BOOL WINAPI CryptCreateHash(
HCRYPTPROV hProv,
ALG_ID Algid,
HCRYPTKEY hKey,
DWORD dwFlags,
HCRYPTHASH *phHash
hProv[in]CSP句柄
Algid[in]哈希算法的标示符。
hKey[in]如果哈希算法是密钥哈希,如HMAC或MAC
算法,就用此密钥句柄传递密钥。对于非密钥算法,此参数为NULL。
dwFlags[in]保留。必须为0。
phHash[out]哈希对象的句柄。
此函数初始化哈希数据流。它创建并返回了一个CSP哈希对象的句柄。此句柄由CryptHashData和CryptHashSessionKey来调用。
4.1.6.4.2 CryptHashData
BOOL WINAPI CryptHashData(
HCRYPTHASH hHash,
BYTE *pbData,
DWORD dwDataLen,
DWORD dwFlags
hHash[in]哈希对象句柄
pbData[in]指向要加入到哈希对象的数据指针
dwDataLen[in]数据长度
dwFlags[in]标志
CRYPT_USERDATA所有微软CSP都忽略此参数。所有其他CSP 都不能忽略此参数,如果置此参数,CSP提示用户直接数据数据。
此函数把一段数据加入到指定的哈希对象中去。
4.1.6.4.3 CryptGetHashParam
BOOL WINAPI CryptGetHashParam(
HCRYPTHASH hHash,
DWORD dwParam,
BYTE *pbData,
DWORD *pdwDataLen,
DWORD dwFlags
hHash[in]哈希对象的句柄
dwParam[in]查询类型。可以是下列:
HP_HASHSIZE
哈希值长度
HP_HASHVAL
哈希值,由hHash指定的哈希值或者消息哈希
此函数得到指定哈希对象的数据。
4.1.6.4.4 CryptDestroyHash
BOOL WINAPI CryptDestroyHash(
HCRYPTHASH hHash
hHash[in]要销毁的哈希对象句柄
此函数销毁由hHash指定的哈希对象。当一个哈希对象被销毁后,它对程序来说不可用。
HCRYPTHASH hCryptH
if (CryptCreateHash(
hCryptProv,
&hCryptHash
CryptDestroyHash(hCryptHash);
4.1.6.5派生密钥
4.1.6.5.1 CryptDeriveKey
BOOL WINAPI CryptDeriveKey(
HCRYPTPROV hProv,
ALG_ID Algid,
HCRYPTHASH hBaseData,
DWORD dwFlags,
HCRYPTKEY *phKey
hProv[in]CSP句柄
Algid[in]要产生密钥的对称加密算法
hBaseData[in]哈希对象的句柄
dwFlags[in]指定密钥的类型
CRYPT_CREATE_SALT
由哈希值产生一个会话密钥,有一些需要补位。如果用此标志,密钥将会赋予一个盐值
CRYPT_EXPORTABLE
如果置此标志,密钥就可以用CryptExportKey函数导出。
CRYPT_NO_SALT
如果置此标志,表示40位的密钥不需要分配盐值。
CRYPT_UPDATE_KEY
有些CSP从多个哈希值中派生会话密钥。如果这种情况,CryptDeriveKey需要多次调用。
phKey[in/out]密钥的句柄
此函数从一基本数据值中派生会话密钥。函数保证当CSP和算法相同时,从相同基本数据值中产生的密钥是唯一的。
4.1.6.5.2 CryptDestroyKey
BOOL WINAPI CryptDestroyKey(
HCRYPTKEY hKey
hKey[in]需要销毁的密钥句柄
此函数释放密钥句柄。
HCRYPTKEY hCryptK
if (CryptDeriveKey(hCryptProv, m_algid, m_hHash, 0, &hCryptKey))
CryptDestroyKey(hCryptKey);
4.1.6.6加密/解密
4.1.6.6.1 CryptEncrypt
BOOL WINAPI CryptEncrypt(
HCRYPTKEY hKey,
HCRYPTHASH hHash,
BOOL Final,
DWORD dwFlags,
BYTE *pbData,
DWORD *pdwDataLen,
DWORD dwBufLen
hKey[in]加密密钥的句柄
hHash[in]哈希对象的句柄。如果数据需要同时被哈希并且加密,hHash就指出了哈希对象。
Final[in]指出是否是最后一次加密操作。如果Final为TRUE,就为最后一次,否则为FALSE。
dwFlags[in]保留
pbData[in/out]指向被加密的数据地址。
pdwDataLen[in/out]指向一个DWORD值的地址。在调用此函数前,这个值就是需要加密的数据长度。在调用此函数后,这个值就是已经加密的数据长度。如果此值为NULL,函数就返回需要数据的长度。
dwBufferLen[in]指出pbData的数据长度。
此函数用于加密数据。加密数据所需要的算法由hKey的密钥指定。
4.1.6.6.2 CryptDecrypt
BOOL WINAPI CryptDecrypt(
HCRYPTKEY hKey,
HCRYPTHASH hHash,
BOOL Final,
DWORD dwFlags,
BYTE *pbData,
DWORD *pdwDataLen
hKey[in]解密密钥的句柄
hHash[in]哈希对象的句柄。如果需要解密数据并且同时作哈希,hHash传递此参数。
Final[in]指出是否是最后一次解密操作。
dwFlags[in]保留
pbData[in/out]需要解密数据的地址
pdwDataLen[in/out]指向DWORD值的指针,此值指出解密数据的长度。在调用此函数前,此值为需要解密数据的长度,调用此函数后,此值为已经解密的数据长度。
此函数对由CryptEncrypt加密过的数据进行解密。
//---------------------------------------------------
HCRYPTPROV hCryptP
HCRYPTHASH hCryptH
HCRYPTKEY hCryptK
CryptAcquireContext(
hCryptProv, NULL,
MS_DEF_PROV,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT);
CryptCreateHash(
hCryptProv,
&hCryptHash
static char szHash[]=”PISAHASHDATA”; //原始字符串
DWORD dwLen=strlen(szHash);
CryptHashData(hCryptHash, (BYTE*)szHash, dwLen, 0);
CryptDeriveKey(hCryptProv, CALG_RC2, hCryptHash, 0, &hCryptKey);
static char szEntry[]=“PISA2002”;
DWORD dwLenIn = strlen(szEntry);
DWORD dwLenOut=dwLenIn;
CryptEncrypt(hCryptKey, 0, TRUE, 0, (BYTE*)szEntry, &dwLenOut, dwLenIn);
CryptDecrypt(hCryptKey, 0, TRUE, 0,(BYTE*)szEntry,&dwLenOut);
CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv, NULL);
4.1.6.7签名/验证
4.1.6.7.1 CryptSignMessage
BOOL WINAPI CryptSignMessage(
PCRYPT_SIGN_MESSAGE_PARA pSignPara,
BOOL fDetachedSignature,
DWORD cToBeSigned,
const BYTE *rgpbToBeSigned[ ],
DWORD rgcbToBeSigned[ ],
BYTE *pbSignedBlob,
DWORD *pcbSignedBlob
pSignPara[in]指向CRYPT_SIGN_MESSAGE_PARA结构的指针。
CRYPT_SIGN_MESSAGE_PARA结构如下:
typedef struct _CRYPT_SIGN_MESSAGE_PARA {
DWORD dwMsgEncodingT
PCCERT_CONTEXT pSigningC
CRYPT_ALGORITHM_IDENTIFIER HashA
void *pvHashAuxI
DWORD cMsgC
PCCERT_CONTEXT *rgpMsgC
DWORD cMsgC
PCCRL_CONTEXT *rgpMsgC
DWORD cAuthA
PCRYPT_ATTRIBUTE rgAuthA
DWORD cUnauthA
PCRYPT_ATTRIBUTE rgUnauthA
DWORD dwInnerContentT
#ifdef CRYPT_SIGN_MESSAGE_PARA_HAS_CMS_FIELDS
CRYPT_ALGORITHM_IDNETIFIER HashEncryptionA
void pvHashEncryptionAuxI
} CRYPT_SIGN_MESSAGE_PARA, *PCRYPT_SIGN_MESSAGE_PARA;
cbSize此结构的大小。
dwMsgEncodingType使用的编码类型。一般为X509_ASN_ENCODING | PKCS_7_ASN_ENCODING
pSigningCert指向要签名的CERT_CONTEXT指针。
HashAlgorithm&CRYPT_ALGORITHM_IDENTIFIER指出了对要进行签名的数据进行哈希的哈希算法
pvHashAuxInfo必须为NULL
cMsgCert&&&rgpMsgCert数组中CERT_CONTEXT结构的元素数量。如果此值为0,则签名消息中不包含任何证书。
rgpMsgCert指向CERT_CONTEXT的数组指针。如果包含pSigningCert,它的指针必须放到rgpMsgCert数组中。
cMsgCrl&rgpMsgCrl数组指向CRL_CONTEXT结构的元素数量。如果为0,签名消息中不包含任何CRL_CONTEXT结构。
rgpMsgCrl&指向CRL_CONTEXT结构的数组指针。
cAuthAttr必须为0
rgAuthAttr指向CRYPT_ATTRIBUTE数组的指针。每一次都包含了认证信息。
cUnauthAttrrg UnauthAttr数组大小。
rgUnauthAttr指向CRYPT_ATTRIBUTE结构的数组指针。
dwFlags通常为0。
dwInnerContentType通常为0。
HashEncryptionAlgorithm&&CRYPT_ALGORITHM_IDENTIFIER结构。通常为0
pvHashEncryptionAuxInfo必须为0。
fDetachedSignature[in]如果为TRUE,就是已解邦定的签名,否则为FALSE。如果此参数为TRUE,
pbSignedBlob中只有签名哈希。否则rgpbToBeSigned和签名哈希都要被编码。
cToBeSigned[in]指出rgpbToBeSigned数据元素的个数。除非fDetachedSigned
为TRUE,此参数就是1。
rgpbToBeSigned[in]指向要签名数据的数组指针。
pbSignedBlob[out]指向一个接收签名哈希的数据地址。如果此参数为NULL,就是需要来接收数据的内存大小。
pcbSignedBlob[in/out]指向DWORD的地址,此数据指出pbSignedBlob
此函数对指定数据进行哈希,然后对哈希值进行签名,然后对原始消息和签名哈希进行编码。
//--------------------------------------------------------------------
#define MY_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#define SIGNER_NAME L&Insert_signer_name_here&
#define CERT_STORE_NAME L&MY&
void HandleError(char *s);
void main(void)
//系统证书库句柄
HCERTSTORE hStoreH
//--------------------------------------------------------------------
//待签名的消息
BYTE* pbMessage =
(BYTE*)&CryptoAPI is a good way to handle security&;
//--------------------------------------------------------------------
DWORD cbMessage = strlen((char*) pbMessage)+1;
//--------------------------------------------------------------------
//证书的上下文
PCCERT_CONTEXT pSignerC
CRYPT_SIGN_MESSAGE_PARA SigP
DWORD cbSignedMessageB
BYTE *pbSignedMessageB
DWORD cbDecodedMessageB
BYTE *pbDecodedMessageB
CRYPT_VERIFY_MESSAGE_PARA VerifyP
//--------------------------------------------------------------------
const BYTE* MessageArray[] = {pbMessage};
DWORD MessageSizeArray[1];
MessageSizeArray[0] = cbM
//--------------------------------------------------------------------
printf(&Begin processing. n&);
printf(& The message to be signed isn-& %s.n&,pbMessage);
//--------------------------------------------------------------------
// Open a certificate store.
if ( !( hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
CERT_SYSTEM_STORE_CURRENT_USER,
CERT_STORE_NAME)))
HandleError(&The MY store could not be opened.&);
//--------------------------------------------------------------------
//得到证书的上下文,此证书必须能访问签名者的私钥
if(pSignerCert = CertFindCertificateInStore(
hStoreHandle,
CERT_FIND_SUBJECT_STR,
SIGNER_NAME,
printf(&The signer's certificate was found.n&);
HandleError( &Signer certificate not found.&);
//--------------------------------------------------------------------
//初始化签名结构
SigParams.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
SigParams.dwMsgEncodingType = MY_TYPE;
SigParams.pSigningCert = pSignerC
SigParams.HashAlgorithm.pszObjId = szOID_RSA_MD5;
SigParams.HashAlgorithm.Parameters.cbData = NULL;
SigParams.cMsgCert = 1;
SigParams.rgpMsgCert = &pSignerC
SigParams.cAuthAttr = 0;
SigParams.dwInnerContentType = 0;
SigParams.cMsgCrl = 0;
SigParams.cUnauthAttr = 0;
SigParams.dwFlags = 0;
SigParams.pvHashAuxInfo = NULL;
SigParams.rgAuthAttr = NULL;
//--------------------------------------------------------------------
//首先得到BLOB的大小
if(CryptSignMessage(
&SigParams, // Signature parameters
FALSE, // Not detached
1, // Number of messages
MessageArray, // Messages to be signed
MessageSizeArray, // Size of messages
NULL, // Buffer for signed message
&cbSignedMessageBlob)) // Size of buffer
printf(&The size of the BLOB is %d.n&,cbSignedMessageBlob);
HandleError(&Getting signed BLOB size failed&);
//--------------------------------------------------------------------
//分配BLOB的内存.
if(!(pbSignedMessageBlob =
(BYTE*)malloc(cbSignedMessageBlob)))
HandleError(&Memory allocation error while signing.&);
//--------------------------------------------------------------------
if(CryptSignMessage(
&SigParams, //
1, //消息数量
MessageArray, //待签名的消息
MessageSizeArray, //消息大小
pbSignedMessageBlob, //缓冲区
&cbSignedMessageBlob)) //缓冲区大小
printf(&The message was signed successfully. n&);
HandleError(&Error getting signed BLOB&);
//--------------------------------------------------------------------
//验证签名信息
//--------------------------------------------------------------------
//初始化VerifyParams结构.
VerifyParams.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA);
VerifyParams.dwMsgAndCertEncodingType = MY_TYPE;
VerifyParams.hCryptProv = 0;
VerifyParams.pfnGetSignerCertificate = NULL;
VerifyParams.pvGetArg = NULL;
//--------------------------------------------------------------------
if(CryptVerifyMessageSignature(
&VerifyParams, //.
pbSignedMessageBlob, //.
cbSignedMessageBlob, //
&cbDecodedMessageBlob, //.
NULL)) // Pointer to signer certificate.
printf(&%d bytes need for the buffer.n&,cbDecodedMessageBlob);
printf(&Verification message failed. n&);
//--------------------------------------------------------------------
//为缓冲区分配内存.
if(!(pbDecodedMessageBlob =
(BYTE*)malloc(cbDecodedMessageBlob)))
HandleError(&Memory allocation error allocating decode BLOB.&);
//--------------------------------------------------------------------
//得到缓冲区的大小
if(CryptVerifyMessageSignature(
&VerifyParams, // Verify parameters.
0, // Signer index.
pbSignedMessageBlob, // Pointer to signed BLOB.
cbSignedMessageBlob, // Size of signed BLOB.
pbDecodedMessageBlob, // Buffer for decoded message.
&cbDecodedMessageBlob, // Size of buffer.
NULL)) // Pointer to signer certificate.
printf(&The verified message is n-& %s n&,pbDecodedMessageBlob);
printf(&Verification message failed. n&);
//--------------------------------------------------------------------
if(pbSignedMessageBlob)
free(pbSignedMessageBlob);
if(pbDecodedMessageBlob)
free(pbDecodedMessageBlob);
if(pSignerCert)
CertFreeCertificateContext(pSignerCert);
if(CertCloseStore(
hStoreHandle,
CERT_CLOSE_STORE_CHECK_FLAG))
printf(&The store closed and all certificates are freed. n&);
printf(&Store closed after signing -- n&
&not all certificates, CRLs or CTLs were freed&);
4.2证书和证书库函数
这组函数管理、使用和取得证书、证书撤销列表和证书信任列表。这些函数可以分成一下几组:
4.2.1证书库函数
一个用户站点可以收集许多证书。这些证书是为这个站点的用户所使用的,证书描述了这个用户的具体身份。对于每个人,可能有一个以上的证书。证书库和其相关的函数提供了
对库获得、枚举、验证和使用证书库里的信息。
以下就是这些函数:
CertAddStoreToCollection在证书库中增加一个证书
CertCloseStore关闭一个证书库句柄
CertControlStore如果证书缓冲区和证书本身内容不相符时,允许给应用程序发一个通知
CertDuplicateStore通过增加引用计数来复制证书库句柄
CertEnumPhysicalStore对于指定系统库枚举物理库
CertEnumSystemStore枚举所有可用的系统库
CertEnumSystemStoreLocation枚举可用系统库的所有位置
CertGetStoreProperty得到一个库的属性
CertOpenStore使用指定库类型来打开证书库
CertOpenSystemStore打开一个系统证书库
CertRegisterPhysicalStore在一个注册系统库里增加一个物理库
CertRegisterSystemStore注册一个系统库
CertRemoveStoreFromCollection从一个库集合里删除证书库
CertSaveStore保存证书库
CertSetStoreProperty设置证书属性
CertUnregisterPhysicalStore从系统库中删除一个物理库
CertUnregisterSystemStore反注册一个指定系统库
4.2.2维护函数
CryptoAPI提供了证书和证书库函数如下:
CertAddSerializeElementToStore在库中增加一系列证书或CRL
CertCreateContext从编码字节中创建指定上下文
CertEnumSubjectInSortedCTL在CTL库中枚举信任主题
CertFindSubjectInCTL在CTL中寻找指定主题
CertFindSubjectInSortedCTL在分类CTL中寻找指定主题
4.2.3证书函数
下列函数是针对于证书的。大多数函数都是处理CRL和CTL 的。
CertAddCertificateContextToStore在证书库里增加一个证书上下文
CertAddCertificateLinkToStore在证书库里增加一个对不同库里的证书上下文的链接
CertAddEncodedCertificateToStore把编码证书转换成证书上下文并且把它加到证书库里
CertCreateCertificateContext从编码证书中创建一个证书上下文。但这个上下文并不放到证书库里
CertCreateSelfSignCertificate创建一个自签名证书
CertDeleteCertificateFromStore从证书库里删除一个证书
CertDuplicateCertificate通过增加引用计数来复制证书上下文
CertEnumCertificateInStore在证书库里枚举证书上下文
CertFindCertificateInStore在证书库里寻找证书上下文
CertFreeCertificateContext释放一个证书上下文
CertGetIssuerCertificateFromStore在证书库里得到指定主题证书的发行者
CertGetSubjectCertificateFromStore获得主题证书的上下文
CertGetValidUsages返回所有证书的用法
CertSerializeCertificateStoreElement串行化编码证书的证书上下文
CertVerifySubjectCertificateContext使用发行者来验证主题证书
CryptUIDlgViewContext显示证书、CRL或CTL
CryptUIDlgSelectCertificateFromStore从指定库中显示对话框,可以从中选择证书
4.2.4证书撤销列表函数
CertAddCRLContextToStore在证书库里增加一个CRL上下文
CertAddCRLLinkToStore在不同的库里增加一个CRL上下文链接
CertAddEncodedCRLToStore把编码CRL转化成CRL 上下文然后把它加入到证书库中
CertCreateCRLContext从编码CRL中创建CRL 句柄,但不把它加到库中
CertDeleteCRLFromStore从证书库里删除一个CRL
CertDuplicateCRLContext通过增加引用计数来复制CRL上下文
CertEnumCRLsInStore枚举库里的CRL句柄
CertFindCertificateInCRL从指定证书里寻找CRL列表
CertFindCRLInStore在库里寻找CRL上下文
CertFreeCRLContext释放CRL上下文
CertGetCRLFromStore从库里得到CRL上下文句柄
CertSerializeCRLStoreElement串行化CRL上下文的编码CRL 和它的属性
4.2.5证书信任列表函数
CertAddCTLContextToStore把一个CTL上下文加入到证书库里
CertAddCTLLinkToStore给不同库里的CRL上下文添加链接
CertAddEncodedCTLToStore把编码CTL转化成CTL 上下文并且把它加到证书库里
CertCreateCTLContext从编码CTL中创建CTL 上下文
CertDeleteCTLFromStore从证书库里删除CTL
CertDuplicateCTLContext通过增加引用计数来复制CTL上下文
CertEnumCTLsInStore在证书库里枚举CTL上下文
CertFindCTLInStore在证书库里查找CTL上下文
CertFreeCTLContext释放CTL上下文
CertSerializeCTLStoreElement串行化CTL上下文的编码CTL 和属性
4.2.6扩展属性函数
CertEnumCertificateContextProperties枚举指定证书上下文的属性
CertEnumCRLContextProperties枚举指定CRL上下文的属性
CertEnumCTLContextProperties枚举指定CTL上下文的属性
CertGetCertificateContextProperty得到证书属性
CertGetCRLContextProperty得到CRL属性
CertGetCTLContextProperty得到CTL属性
CertSetCertificateContextProperty设置证书属性
CertSetCRLContextProperty设置CRL属性
CertSetCTLContextProperty设置CTL属性
4.2.7函数详解
4.2.7.1打开/关闭系统证书库
4.2.7.1.1 CertOpenSystemStore
HCERTSTORE WINAPI CertOpenSystemStore(
HCRYPTPROV hProv,
LPCTSTR szSubsystemProtocol,
hProv[in] CSP句柄。如果为NULL,就为却省CSP。如果不为NULL,它必须是由CryptAcquireContext得到的CSP句柄。
szSubsystemProtocol[in]系统证书库的名称。可以为”CA”、”MY”、”ROOT”、”SPC”。
此函数用来打开通用的系统证书库。
4.2.7.1.2 CertCloseStore
BOOL WINAPI CertCloseStore(
HCERTSTORE hCertStore,
DWORD dwFlags
hCertStore[in]证书库句柄。
dwFlags[in]典型地,此参数为0。却省就是关闭证书库,对于为上下文分配的内存并不释放。如果想要检查并且释放所有为证书、CRL和CTL
上下文的分配的内存,就要置下列标志。
CERT_CLOSE_STORE_CHECK_FLAG检查没有释放的证书、CRL和CTL 上下文。
CERT_CLOSE_STORE_FORCE_FLAG强制释放所有和证书库相关的上下文。
此函数释放证书库句柄。
//-----------------------------------------------------------------
HCERTSTORE hSystemS
if(hSystemStore = CertOpenSystemStore(0,&MY&))
printf(&The MY system store is open. Continue.n&);
CertCloseStore(hSystemStore, CERT_CLOSE_STORE_CHECK_FLAG);
printf(&The MY system store did not open.n&);
4.3证书验证函数
证书验证是通过CTL和证书列表进行的。
4.3.1使用CTL的函数
CertVerifyCTLUsage验证CTL用法
CryptMsgEncodeAndSignCTL编码和验证CTL
CryptMsgGetAndVerifySigner从一个消息中获得和验证CTL
CryptMsgSignCTL对包含CTL的消息进行签名
4.3.2证书链验证函数
CertCreateCertificateChainEngine为应用程序创建一个新的非却省的链引擎
CertCreateCTLEntryFromCertificateContextProperties创建一个CTL入口
CertDuplicateCertificateChain通过增加引用计数来复制证书链
CertFindChainInStore在证书库里查找证书链
CertFreeCertificateChain释放证书链
CertFreeCertificateChainEngine释放证书链引擎
CertGetCertificateChain从最后一个证书建立一个上下文链表
CertSetCertificateContextPropertiesFromCTLEntry通过CTL入口属性来设置证书上下文的属性
CertIsValidCRLForCertificate通过检查CRL来确定CRL 是否包括指定被撤销的证书
CertVerifyCertificateChainPolicy通过检查证书链来确定它的完整性
4.4消息函数
CryptoAPI消息函数包括两组:低级消息函数和简化消息函数。
低级消息函数直接和PKCS#7消息工作。这些函数对传输的PKCS#7 数据进行编码,对接收到的PKCS#7数据进行解码,并且对接收到的消息进行解密和验证。
简化消息函数是比较高级的函数,是对几个低级消息函数和证书函数的封装,用来执行指定任务。这些函数在完成一个任务时,减少了函数调用的数量,因此简化了CryptoAPI的使用。
4.4.1低级消息函数
CryptMsgCalculateEncodedLength计算加密消息的长度
CryptMsgClose关闭加密消息的句柄
CryptMsgControl执行指定的控制函数
CryptMsgCountersign标记消息中已存在的签名
CryptMsgCountersignEncoded标记已存在的签名
CryptMsgDuplicate通过增加引用计数来复制加密消息句柄
CryptMsgGetParam对加密消息进行编码或者解码后得到的参数
CryptMsgOpenToDecode打开加密消息进行解码
CryptMsgOpenToEncode打开加密消息进行编码
CryptMsgUpdate更新加密消息的内容
CryptMsgVerifyCountersignatureEncoded验证SignerInfo结构中标记时间
CryptMsgVerifyCountersignatureEncodedEx验证SignerInfo结构中标记时间,签名者可以是CERT_PUBLIC_KEY_INFO结构
4.4.2简化消息函数
CryptDecodeMessage对加密消息进行解码
CryptDecryptAndVerifyMessageSignature对指定消息进行解密并且验证签名者
CryptDecryptMessage解密指定消息
CryptEncryptMessage加密指定消息
CryptGetMessageCertificates返回包含消息的证书和CRL的证书库
CryptGetMessageSignatureCount返回签名消息的签名者数量
CryptHashMessage创建消息的哈希
CryptSignAndEncryptMessage对消息进行签名并且加密
CryptSignMessage对消息进行签名
CryptVerifyDetachedMessageHash验证包含已解邦定哈希的哈希消息
CryptVerifyDetachedMessageSignature验证包含已解邦定签名的签名消息
CryptVerifyMessageHash验证一个哈希消息
CryptVerifyMessageSignature验证一个签名消息
4.5辅助函数
4.5.1数据管理函数
CertCompareCertificate比较两个证书是否相同
CertCompareCertificateName通过比较两个证书名称来决定他们是否相同
CertCompareIntegerBlob比较两个整数BLOB
CertComparePublicKeyInfo通过比较两个证书公钥来决定他们是否相同
CertFindAttribute通过OID来查找属性
CertFindExtension通过OID来查找扩展
CertFindRDNAttr通过OID来查找RDN 属性
CertGetIntendedKeyUsage从证书中取得相关密钥用法
CertGetPublicKeyLength从公钥BLOB中取得公钥/私钥长度
CertIsRDNAttrsInCertificateName通过指定RDN数组属性比较证书名称属性来决定证书是否已包含了所有属性
CertVerifyCRLRevocation验证主题证书是否在CRL中
CertVerifyCRLTimeValidity验证CRL的有效时间
CertVerifyRevocation验证主题证书是否在CRL中
CertVerifyTimeValidity验证CRL的有效时间
CertVerifyValidityNesting验证主题时间的有效性是否在发行者有效时间内
CryptExportPublicKeyInfo导出公钥信息
CryptExportPublicKeyInfoEx导出公钥信息(用户可以指定算法)
CryptFindCertificateKeyProvInfo枚举CSP和它的密钥容器来查找对应于公钥的相应私钥
CryptFindLocalizedName查找指定名字的局部化名称
CryptHashCertificate哈希证书内容
CryptHashPublicKeyInfo计算公钥信息的哈希
CryptHashToBeSigned计算签名内容的信息哈希值
CryptImportPublicKeyInfo把公钥信息导入CSP并且返回它的句柄
CryptImportPublicKeyInfoEx把公钥信息导入CSP并且返回它的句柄
CryptMemAlloc分配内存
CryptMemFree释放内存
CryptMemRealloc重新分配内存
CryptQueryObject得到BLOB或文件的内容信息
CryptSignAndEncodeCertificate对信息进行签名并且编码
CryptSignCertificate对证书进行签名
CryptVerifyCertificateSignature使用公钥信息对主题证书或CRL的签名进行验证
CryptVerifyCertificateSignatureEx使用公钥信息对主题证书或CRL的签名进行验证
4.5.2数据转换函数
CertAlgIdToOID把CSP算法标示符转换成OID
CertGetNameString得到证书的主题或颁发者名称并且把它转换成字符串
CertNameToStr把证书名称BLOB转换成字符串
CertOIDToAlgId把OID转换成CSP 算法表示符
CertRDNValueToStr把名称值转换成字符串
CertStrToName把字符串转换成编码证书名称
CryptBinaryToString把二进制序列转换成字符串
CryptFormatObject格式化编码数据,返回Unicode字符串
CryptStringToBinary把格式化的字符串转换成二进制序列
4.5.3增强密钥用法函数
CertAddEnhancedKeyUsageIdentifier在证书EKU属性中增加一个用法标示符
CertGetEnhancedKeyUsage获得证书的EKU扩展或属性信息
CertRemoveEnhancedKeyUsageIdentifier从证书EKU扩展属性中删除用法标示符OID
CertSetEnhancedKeyUsage设置证书的EKU属性
4.5.4密钥标示函数
CryptCreateKeyIdentifierFromCSP创建CSP公钥的密钥标示符
CryptEnumKeyIdentifierProperties枚举标示符和其属性
CryptGetKeyIdentifierProperty从指定密钥标示符中获得指定属性
CryptSetKeyIdentifierProperty设置指定密钥标示符的属性
4.5.5证书库回调函数
CertDllOpenStoreProv定义库提供者打开函数
CertStoreProvCloseCallback决定当证书库引用计数为0时将发生的动作
CertStoreProvDeleteCertCallback决定当从证书库中删除一个证书之前的动作
CertStoreProvDeleteCRLCallback决定当从证书库中删除一个CRL之前的动作
CertStoreProvReadCertCallback保留
CertStoreProvReadCRLCallback保留
CertStoreProvSetCertPropertyCallback决定在CertSetCertificateContextProperty和
CertGetCertificateContext调用之前的动作
CertStoreProvSetCRLPropertyCallback决定在CertSetCRLContextProperty和
CertGetCRLContextProperty调用之前的动作
CertStoreProvWriteCertCallback决定在证书库中加入一个证书前的动作
CertStoreProvWriteCRLCallback决定在证书库中加入一个CRL前的动作
CertStoreProvReadCTL读CSP的CTL 上下文
CertStoreProvWriteCTL决定CTL是否可被加入到证书库中
CertStoreProvDeleteCTL决定CTL是否可被删除
CertStoreProvSetCTLProperty决定是否可以设置CTL的属性
CertStoreProvControl当缓冲库和存储库不同时,通知应用程序
CertStoreProvFindCert在证书库中查找下一个证书
CertStoreProvFreeFindCert释放前一个找到的证书上下文
CertStoreProvGetCertProperty得到指定的证书属性
CertStoreProvFindCRL查找第一个或下一个匹配的CRL
CertStoreProvFreeFindCRL释放前一个找到的CRL上下文
CertStoreProvGetCRLProperty得到指定CRL属性
CertStoreProvFindCTL查找第一个或下一个匹配的CTL
CertStoreProvFreeFindCTL释放前一个找到的CTL上下文
CertStoreProvGetCTLProperty得到指定CTL属性
4.5.6 OID支持函数
CryptEnumOIDFuction枚举由编码类型、函数名和OID指定注册的OID函数
CryptEnumOIDInfo枚举注册的OID信息
CryptEnumOIDInfo使用指定的密钥和组查找OID信息
CryptFreeOIDFuctionAddress释放OID函数地址句柄
CryptGetDefaultOIDDllList对于指定的函数结合和类型获得却省注册的DLL入口
CryptGetDefaultOIDFuctionAddress获得已安装的第一次或下一个却省函数或者加载包含却省函数的DLL
CryptGetOIDFuctionAddress搜索匹配指定编码类型和OID函数列表,如果没有找到,就查找注册表。
CryptGetOIDFuctionValue获得指定编码类型、函数名称和OID的值
CryptInitOIDFuctionSet初始化OID函数集合的句柄
CryptInstallOIDFuctionAddress安装可调用的OID函数地址集合
CryptRegisterDefaultOIDFuction注册包含却省函数的DLL
CryptRegisterOIDFuction注册包含指定函数的DLL
CryptRegisterOIDInfo注册由CRYPT_OID_INFO指定的OID 信息
CryptSetOIDFuctionValue设置编码类型、函数名称等的值
CryptUnregisterDefaultOIDFunction卸载包含却省函数的DLL
CryptUnregisterOIDFuction卸载包含函数的DLL
CryptUnregisterOIDInfo卸载指定OID的信息
4.5.7远程对象恢复函数
CryptGetObjectUrl从证书、CTL或CRL 中取得远程对象的URL
CryptRetrieveObjectByUrl由URL指定位置恢复PKI 对象
4.5.8 PFX函数
PFXExportCertStore从证书库中导出证书或证书和私钥
PFXExportCertStoreEx从证书库中导出证书或证书和私钥
PFXImportCertStore从PFX BLOB导入到指定证书库
PFXIsPFXBlob把外层BLOB像pfx 包那样解码
PFXVerifyPassword把外层BLOB像pfx 包那样解码,并且用指定口令解密
一些加密解密标准函数示例——DES,RSA
&一. DES加密、解密
//默认密钥向量
private byte[] Keys = { 0xEF, 0xAB, 0x56, 0x78, 0x90, 0x34, 0xCD, 0x12 };
/// &summary&
/// DES加密字符串
/// &/summary&
/// &param name=&encryptString&&待加密的字符串&/param&
/// &param name=&encryptKey&&加密密钥,要求为8位&/param&
/// &returns&加密成功返回加密后的字符串,失败返回源串&/returns&
public string EncryptDES(string encryptString, string encryptKey)
byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
byte[] rgbIV = K
byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
MemoryStream mStream = new MemoryStream();
CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
cStream.Write(inputByteArray, 0, inputByteArray.Length);
cStream.FlushFinalBlock();
return Convert.ToBase64String(mStream.ToArray());
return encryptS
/// &summary&
/// DES解密字符串
/// &/summary&
/// &param name=&decryptString&&待解密的字符串&/param&
/// &param name=&decryptKey&&解密密钥,要求为8位,和加密密钥相同&/param&
/// &returns&解密成功返回解密后的字符串,失败返源串&/returns&
public string DecryptDES(string decryptString, string decryptKey)
byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey.Substring(0, 8));
byte[] rgbIV = K
byte[] inputByteArray = Convert.FromBase64String(decryptString);
DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
MemoryStream mStream = new MemoryStream();
CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
cStream.Write(inputByteArray, 0, inputByteArray.Length);
cStream.FlushFinalBlock();
return Encoding.UTF8.GetString(mStream.ToArray());
return decryptS
二. &DES/3DES加密算法源代码
/* Project xxxx
* Package com.xxxx.utils
package com.xxxxx.
import java.io.FileInputS
import java.io.ObjectInputS
import java.security.NoSuchAlgorithmE
import java.security.S
import javax.crypto.C
import javax.crypto.KeyG
import javax.crypto.NoSuchPaddingE
import javax.crypto.SecretK
public class DES {
private String Algorithm = &DESede&; //&DESede& for Triple DES
private KeyG
private SecretK
private byte[] cipherB
public DES() {
public DES(String filename) {
init(filename);
public SecretKey genKey() {
keygen = KeyGenerator.getInstance(Algorithm);
deskey = keygen.generateKey();
//利用JavaBean的持久化将key保存为文件XXX.key
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
* @param filename
public void init(String filename) {
restore key
Security.addProvider(new com.sun.crypto.provider.SunJCE());
FileInputStream fis = new FileInputStream(filename);
fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
deskey = (SecretKey) ois.readObject();
ois.close();
fis.close();
c = Cipher.getInstance(Algorithm);
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
} catch (NoSuchPaddingException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
public void init() {
Security.addProvider(new com.sun.crypto.provider.SunJCE());
keygen = KeyGenerator.getInstance(Algorithm);
deskey = keygen.generateKey();
c = Cipher.getInstance(Algorithm);
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
} catch (NoSuchPaddingException ex) {
ex.printStackTrace();
public byte[] encryptor(String str) {
c.init(Cipher.ENCRYPT_MODE, deskey);
cipherByte = c.doFinal(str.getBytes());
} catch (java.security.InvalidKeyException ex) {
ex.printStackTrace();
} catch (javax.crypto.BadPaddingException ex) {
ex.printStackTrace();
} catch (javax.crypto.IllegalBlockSizeException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
return cipherB
public String decryptor(byte[] buff) {
c.init(Cipher.DECRYPT_MODE, deskey);
cipherByte = c.doFinal(buff);
} catch (java.security.InvalidKeyException ex) {
ex.printStackTrace();
} catch (javax.crypto.BadPaddingException ex) {
ex.printStackTrace();
} catch (javax.crypto.IllegalBlockSizeException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
return (new String(cipherByte));
* Project xxxx
* Package com.xxxx.utils
* Created on
* Author Derys
package com.xxxx.
public class XXXDES {
private static XXXDES instance = new XXXDES();
public XXXDES() {
* @param str
public String encrypt(String str) {
StringBuffer buffer = new StringBuffer();
DES des = new DES(&XXX.key&);
byte[] en = des.encryptor(str);
for (int i = 0; i & en. i++) {
buffer.append((char) en[i]);
return buffer.toString();
* @param str
public String decrypt(String str) {
DES des = new DES(&XXX.key&);
byte[] en = new byte[str.length()];
for (int i = 0; i & str.length(); i++) {
en[i] = (byte) str.charAt(i);
String de = des.decryptor(en);
* @param str
public String replaceChar(String str) {
StringBuffer buffer = new StringBuffer();
int index = str.indexOf(&'&);
if (index == -1) {
while (index & -1) {
buffer.append(str.substring(0, index));
buffer.append(&''&);
str = str.substring(index + 1);
index = str.indexOf(&'&);
buffer.append(str);
return buffer.toString();
public static XXXDES getInstance(){
if(instance == null){
instance = new XXXDES();
encryptedTextXXXDES.getInstance().encrypt(&your&plain&text&);
plainText=XXXDES.getInstance().decrypt(&your&encrypted&text&);
三.RSA加密、解密
RSA加密算法是一种非对称加密算法。在公钥加密标准和电子商业中RSA被广泛使用。RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA算法的可靠性基于分解极大的整数是很困难的。假如有人找到一种很快的分解因子的算法的话,那么用RSA加密的信息的可靠性就肯定会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。
1. rsa基本结构
const rsa_method *
bignum *n;
bignum *e;
//公开的加密指数,经常为65537(ox10001)
bignum *d;
bignum *p;
bignum *q;
bignum *dmp1;
//d mod (p-1)
bignum *dmq1;
//d mod (q-1)
//(inverse of q) mod p
2.初始化函数
rsa * rsa_new(void);初始化一个rsa结构
void rsa_free(rsa *rsa);释放一个rsa结构
3.rsa私钥产生函数
rsa *rsa_generate_key(int num, unsigned long e,void (*callback)(int,int,void *), void *cb_arg);产生一个模为num位的密钥对,e为公开的加密指数,一般为65537(ox10001),假如后两个参数不为null,将有些调用。在产生密钥对之前,一般需要指定随机数种子
4.判断位数函数
&int rsa_size(const rsa *rsa);返回rsa模的位数,他用来判断需要给加密值分配空间的大小&
&int rsa_check_key(rsa *rsa);他测试p,q是否为素数,n=p*q,d*e = 1 mod (p-1*q-1), dmp1, dmq1, iqmp是否均设置正确了。
5.rsa的rsa_method函数
&了解rsa的运算那就必须了解rsa_method,下面我们先看看rsa_method结构
typedef struct rsa_meth_st
const char *
int (*rsa_pub_enc)(int flen,const unsigned char *from,
unsigned char *to,rsa *rsa,int padding);
int (*rsa_pub_dec)(int flen,const unsigned char *from,
unsigned char *to,rsa *rsa,int padding);
int (*rsa_priv_enc)(int flen,const unsigned char *from,
unsigned char *to, rsa *rsa,int padding);
int (*rsa_priv_dec)(int flen,const unsigned char *from,
unsigned char *to,rsa *rsa,int padding);
int (*rsa_mod_exp)(bignum *r0,const bignum *i,rsa *rsa);
int (*bn_mod_exp)(bignum *r, const bignum *a, const bignum *p,
const bignum *m, bn_ctx *ctx,bn_mont_ctx *m_ctx);
int (*init)(rsa *rsa);
/* called at new */
int (*finish)(rsa *rsa);
/* called at free */
/* rsa_method_flag_* things */
char *app_
/* may be needed! */
int (*rsa_sign)(int type,const unsigned char *m, unsigned int m_length,unsigned char *sigret, unsigned int *siglen, const rsa *rsa);
int (*rsa_verify)(int dtype,const unsigned char *m, unsigned int m_length,unsigned char *sigbuf, unsigned int siglen, const rsa *rsa);
const rsa_method *rsa_pkcs1_ssleay(void);
const rsa_method *rsa_null_method(void);
主要有上面两个函数。第二个函数是定义了rsa_null才会调用,其实要调用这个函数以后几乎什么都不能干,只是输出错误信息。第一个是常用的method,下面我们看看它的定义
const rsa_method *rsa_pkcs1_ssleay(void)&&&&&&&&
return(&rsa_pkcs1_eay_meth);&&&&&&&&
static rsa_method rsa_pkcs1_eay_meth={&&&&&&&&&eric young's pkcs#1 rsa&,&&&&&&&& rsa_eay_public_encrypt,&&&&&&&& rsa_eay_public_decrypt,
/* signature verification */&&&&&&&& rsa_eay_private_encrypt, /* signing */&&&&&&&& rsa_eay_private_decrypt,&&&&&&&& rsa_eay_mod_exp,&&&&&&&& bn_mod_exp_mont,& &&&&&&&rsa_eay_init,&&&&&&&& rsa_eay_finish,&&&&&&&& 0, /* flags */&&&&&&&& null,&&&&&&&& 0, /*
rsa_sign */&&&&&&&& 0& /* rsa_verify */&&&&&&&& };
由此可以看出,一般rsa-&meth-& rsa_pub_enc对应于rsa_eay_public_encrypt,刚开始看openssl的时候最难得就是这个指向函数的指针,根本不知道rsa-&meth-& rsa_pub_enc对应于哪里。在openssl里面这种指针很多,到以后也能够看到。下面是设置meth的一些函数应该都很容易理解
void rsa_set_default_method(const rsa_method *meth);&
const rsa_method *rsa_get_default_method(void);&
int rsa_set_method(rsa *rsa, const rsa_method *meth);&
const rsa_method *rsa_get_method(const rsa *rsa);&
int rsa_flags(const rsa *rsa);&
rsa *rsa_new_method(engine *engine);
6.加解密函数
int rsa_public_encrypt(int flen, unsigned char *from,&&&&unsigned char *to, rsa *rsa, int padding);&
int rsa_private_decrypt(int flen, unsigned char *from,&&&&unsigned char *to, rsa *rsa, int padding);&
int rsa_private_encrypt(int flen, unsigned char *from,&&&&unsigned char *to, rsa *rsa,int padding);&
int rsa_public_decrypt(int flen, unsigned char *from, unsigned char *to, rsa *rsa,int padding);&
假如rsa_set_method(rsa, rsa_pkcs1_ssleay())的话,那rsa_public_encrypt对应于rsa_eay_public_encrypt,这样我们就可以调试公钥加密的过程了。flen为要加密信息的长度,from为需要加密的信息,to为加密后的信息,一般to至少要申请bn_num_bytes(rsa-&n)大的空间。padding是采取的加解密方案。pkcs#1中主要提供了两种加密方案,rsaex-oaep和psaes-pkcs1-v1_5(反正就是两种加密过程了,有点复杂,它主要是先对先对需要加密的数据进行了编码,比如rsaes-oaep采用eme-oaep编码,再进行加密或解密)。编码的函数:
case rsa_pkcs1_padding:&&&&i=rsa_padding_add_pkcs1_type_2(buf,num,from,flen);
#ifndef openssl_no_sha case rsa_pkcs1_oaep_padding:&&&&&&&i=rsa_padding_add_pkcs1_oaep(buf,num,from,flen,null,0);
#endif case rsa_sslv23_padding:&&&&i=rsa_padding_add_sslv23(buf,num,from,flen);&
case rsa_no_padding:&&&&i=rsa_padding_add_none(buf,num,from,flen);等上面编好码后,就调用bn_mod_exp_mont来进行模幂了。最后得出值,这也就是具体的加密和解密过程。在这里还可以发现,加密时输入的rsa有两种方式,一是p,q,...为null,只有rsa-&d,和rsa-&n不为空,这样就直接用rsa-&d和rsa-&n进行模幂计算,假如p,q.....都不为空的话,他会调用中国剩余定理来进行加密。
7.签名函数
int rsa_sign(int type, unsigned char *m, unsigned int m_len,&&&&unsigned char *sigret, unsigned int *siglen, rsa *rsa);
int rsa_verify(int type, unsigned char *m, unsigned int m_len,&&&&unsigned char *sigbuf, unsigned int siglen, rsa *rsa);其实签名其实和用私钥加密差不多是一回事,所以签名函数最终调用的就是私钥加密的函数,在openssl中这个签名函数很少单独拿出来用的,都是为了给evp_signfinal来调用的。所以假如是利用rsa进行签名的话,rsa_private_encrypt,bn_mod_exp_mont是最基本的,所有的都需要调用他,区别无非就在于在需要签名的信息上做了一下处理(一般将需要签名的信息求取摘要值得到m)
8.写入文件函数
&int rsa_print(bio *bp, rsa *x, int offset);&
&int rsa_print_fp(file *fp, rsa *x, int offset);offset是为了调整输出格式的,随意一个数都可以(例如2,12,16。。)
int rsa_blinding_on(rsa *rsa, bn_ctx *ctx);
void rsa_blinding_off(rsa *rsa);为了防止时间攻击,openssl还在签名的时候产生一个随机因子,附加在私钥上。&&
int rsa_sign_asn1_octet_string(int dummy, unsigned char *m,unsigned int m_len, unsigned char *sigret, unsigned int *siglen,rsa *rsa);&&
int rsa_verify_asn1_octet_string(int dummy, unsigned char *m,unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,rsa
代码示例如下:
using System.Security.C
using System.IO;
using System.T
namespace Microsoft.Samples.Security.PublicKey
// Main entry point
static void Main(string[] args)
// Instantiate 3 People for example. See the Person class below
Person alice = new Person(&Alice&);
Person bob = new Person(&Bob&);
Person steve = new Person(&Steve&);
// Messages that will exchanged. See CipherMessage class below
CipherMessage aliceM
CipherMessage bobM
CipherMessage steveM
// Example of encrypting/decrypting your own message
Console.WriteLine(&Encrypting/Decrypting Your Own Message&);
Console.WriteLine(&-----------------------------------------&);
// Alice encrypts a message using her own public key
aliceMessage = alice.EncryptMessage(&Alice wrote this message&);
// then using her private key can decrypt the message
alice.DecryptMessage(aliceMessage);
// Example of Exchanging Keys and Messages
Console.WriteLine();
Console.WriteLine(&Exchanging Keys and Messages&);
Console.WriteLine(&-----------------------------------------&);
// Alice Sends a copy of her public key to Bob and Steve
bob.GetPublicKey(alice);
steve.GetPublicKey(alice);
// Bob and Steve both encrypt messages to send to Alice
bobMessage = bob.EncryptMessage(&Hi Alice! - Bob.&);
steveMessage = steve.EncryptMessage(&How are you? - Steve&);
// Alice can decrypt and read both messages
alice.DecryptMessage(bobMessage);
alice.DecryptMessage(steveMessage);
Console.WriteLine();
Console.WriteLine(&Private Key required to read the messages&);
Console.WriteLine(&-----------------------------------------&);
// Steve cannot read the message that Bob encrypted
steve.DecryptMessage(bobMessage);
// Not even Bob can use the Message he encrypted for Alice.
// The RSA private key is required to decrypt the RS2 key used
// in the decryption.
bob.DecryptMessage(bobMessage);
} // method Main
} // class App
class CipherMessage
public byte[] cipherB // RC2 encrypted message text
public byte[] rc2K // RSA encrypted rc2 key
public byte[] rc2IV; // RC2 initialization vector
class Person
private RSACryptoServiceP
private RC2CryptoServiceProvider rc2;
// Maximum key size for the RC2 algorithm
const int keySize = 128;
// Person constructor
public Person(string p_Name)
rsa = new RSACryptoServiceProvider();
rc2 = new RC2CryptoServiceProvider();
rc2.KeySize = keyS
name = p_N
// Used to send the rsa public key parameters
public RSAParameters SendPublicKey()
RSAParameters result = new RSAParameters();
result = rsa.ExportParameters(false);
catch (CryptographicException e)
Console.WriteLine(e.Message);
// Used to import the rsa public key parameters
public void GetPublicKey(Person receiver)
rsa.ImportParameters(receiver.SendPublicKey());
catch (CryptographicException e)
Console.WriteLine(e.Message);
public CipherMessage EncryptMessage(string text)
// Convert string to a byte array
CipherMessage message = new CipherMessage();
byte[] plainBytes = Encoding.Unicode.GetBytes(text.ToCharArray());
// A new key and iv are generated for every message
rc2.GenerateKey();
rc2.GenerateIV();
// The rc2 initialization doesnt need to be encrypted, but will
// be used in conjunction with the key to decrypt the message.
message.rc2IV = rc2.IV;
// Encrypt the RC2 key using RSA encryption
message.rc2Key = rsa.Encrypt(rc2.Key, false);
catch (CryptographicException e)
// The High Encryption Pack is required to run this sample
// because we are using a 128-bit key. See the readme for
// additional information.
Console.WriteLine(&Encryption Failed. Ensure that the& +
& High Encryption Pack is installed.&);
Console.WriteLine(&Error Message: & + e.Message);
Environment.Exit(0);
// Encrypt the Text Message using RC2 (Symmetric algorithm)
ICryptoTransform sse = rc2.CreateEncryptor();
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, sse, CryptoStreamMode.Write);
cs.Write(plainBytes, 0, plainBytes.Length);
cs.FlushFinalBlock();
message.cipherBytes = ms.ToArray();
catch (Exception e)
Console.WriteLine(e.Message);
ms.Close();
cs.Close();
} // method EncryptMessage
public void DecryptMessage(CipherMessage message)
// Get the RC2 Key and Initialization Vector
rc2.IV = message.rc2IV;
// Try decrypting the rc2 key
rc2.Key = rsa.Decrypt(message.rc2Key, false);
catch (CryptographicException e)
Console.WriteLine(&Decryption Failed: & + e.Message);
ICryptoTransform ssd = rc2.CreateDecryptor();
// Put the encrypted message in a memorystream
MemoryStream ms = new MemoryStream(message.cipherBytes);
// the CryptoStream will read cipher text from the MemoryStream
CryptoStream cs = new CryptoStream(ms, ssd, CryptoStreamMode.Read);
byte[] initialText = new Byte[message.cipherBytes.Length];
// Decrypt the message and store in byte array
cs.Read(initialText, 0, initialText.Length);
catch (Exception e)
Console.WriteLine(e.Message);
ms.Close();
cs.Close();
// Display the message received
Console.WriteLine(name + & received the following message:&);
Console.WriteLine(& & + Encoding.Unicode.GetString(initialText));
} // method DecryptMessage
} // class Person
} // namespace PublicKey
感谢关注 Ithao123C/c++频道,是专门为互联网人打造的学习交流平台,全面满足互联网人工作与学习需求,更多互联网资讯尽在 IThao123!
Laravel是一套简洁、优雅的PHP Web开发框架(PHP Web Framework)。它可以让你从面条一样杂乱的代码中解脱出来;它可以帮你构建一个完美的网络APP,而且每行代码都可以简洁、富于表达力。
Hadoop是一个由Apache基金会所开发的分布式系统基础架构。
用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。
Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上;而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。HDFS放宽了(relax)POSIX的要求,可以以流的形式访问(streaming access)文件系统中的数据。
Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,则MapReduce为海量的数据提供了计算。
随着国内互联网的发展,产品经理岗位需求大幅增加,在国内,从事产品工作的大部分岗位为产品经理,其实现实中,很多从事产品工作的岗位是不能称为产品经理,主要原因是对产品经理的职责不明确,那产品经理的职责有哪些,本专题将详细介绍产品经理的主要职责
PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。PHP 独特的语法混合了C、Java、Perl以及PHP自创的语法。它可以比CGI或者Perl更快速地执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执行编译后代码,编译可以达到加密和优化代码运行,使代码运行更快。
IThao123周刊}

我要回帖

更多关于 急求借贷 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信