关于作者

用户名:sagely
笔名:sagely
地区:
行业:其他

日历  

快速登录

+ 用户名:
+ 密 码:

在线留言



信息安全

朋友之间

访问统计:
文章个数:35
评论个数:37
留言条数:6




Powered by BlogDriver 2.1

sagely's blog

 

专注于信息安全 QQ:335957600 E_Mail:sagely_zou@163.com

文章

我的blog搬家了

新地址为http://blog.csdn.net/sagely,欢迎大家继续访问.

- 作者: sagely 2005年05月7日, 星期六 15:50  回复(0) |  引用(0) 加入博采

shell编程
    很长一段时间没有更新blog了,看到访问量的增加,对访问我blog的朋友真是觉得很不好意思。可是我最近都作了什么呢,我实在不知道有什么可以写写的,好象每天都很忙,但是却好象没有干出什么事情来,只是自己让自己在白忙活而已。很想改变这种日子,但是却提不起精神,还好最近借了N本LINUX的书,准备好好学学。
    接触LINUX也有一段时间了,觉得命令好多,很难记住。有个高人指点我现学学shell编程可能会对LINUX的理解好很多。在这里也不想说什么有关语法亚,变量的问题,我直接给出一点具体的程序知道一下格式也就行了。
#!/bin/sh
#本脚本目的在于实现某个软件的启动,关闭,或者重新启动
#启动的软件由参数PGM决定
#列出错误提示
USAGE="Usage:$0 [ start | stop | restart ]"
#给出软件路径
PGM=/usr/sbin/sshd
#给出软件参数
PGM_OPTS=
#判断软件路径是否存在
if [ ! -x "$PGM" ] ; then
echo "Error:Not Executable:$PGM" l>&2
exit 1
fi
#判断操作系统类型
case "'uname -s'" in
Linux | Darwin | *BSD)PS="bin/ps auwxx"
;;
*)PS="/bin/ps -ef"
;;
esac
#判断命令
case "$1" in
#启动命令
start)
RUNNING=`$PS -aux | grep "$PGM" | grep -v grep |head `
if [ -n "$RUNNING" ] ; then
echo "Error:Already running :$PGM" 1>&2
exit 1
fi
"$PGM" $PGM_OPTS
echo "$PGM start"
;;
#关闭命令
stop)
RUNNING=`$PS | grep "$PGM" | grep -v grep |head `
if [ -z "$RUNNING" ] ; then
echo "Error:Not Exist:$PGM" 1>&2
exit 1
fi
/bin/ps -ef | grep "$PGM" | grep -v grep | \
awk '{print $2;}' | xargs kill 2 > /dev/null
echo "$PGM stop"
;;
#重启命令
restart)
RUNNING=`$PS | grep "$PGM" | grep -v grep |head `
if [ -z "$RUNNING" ] ; then
echo "Error:Not Exist:$PGM" 1>&2
exit 1
fi
/bin/ps -ef | grep "$PGM" | grep -v grep | \
awk '{print $2;}' | xargs kill 2 > /dev/null
"$PGM" $PGM_OPTS
echo "$PGM restart"
;;
#错误提示
*)
echo "$USAGE"
exit 1
;;
esac
exit 0

- 作者: sagely 2005年04月17日, 星期日 20:20  回复(2) |  引用(0) 加入博采

终于完成了一个CA的搭建

    前几天整了一个linux服务器,这回就真正可以搭建一个网站了,虽然前面把这些都说得比较详细了,但是中间也出了不少问题。
首先就是openldap出问题,安装openldap是个很麻烦的事情,老是出现数据库不匹配的问题,上网找了找有人说把openldap下的include和lib复制到/usr/include和/usr/lib下面就能解决问题,可是好象更不行,最后还替换了几个文件,这回我想死定了。openldap不装那证书就没地方放。最后我一发狠就把以前装的openldap复制到这个服务器上,居然能用,真是激动。。。所以建议以后大家openldap安装不上就直接复制一个(我也不知道用不用安那个什么数据库),还有就是openldap数据要经常备份,我昨天非法远程断线以后居然openldap就不能启动了,只好把openldap-data全部替换了。
    第二就是中文化问题,在linux下不要太相信setlocale,尽量用inconv。反正这个问题让我搞了一两天。还有就是不知道为什么在CGI中变量使用UTF8编码老是出错,所以变量还是用GB2312比较好,到了下一页面再进行处理。
    当然还有很多配置问题,太细小了,很麻烦,哎,这里就不想回顾了, 反正思路比较清晰,按照步骤来才是最好的。否则就有好累的拉。


- 作者: sagely 2005年04月4日, 星期一 15:58  回复(1) |  引用(0) 加入博采

linux下字符集编码转换轻松实现
在LINUX上进行编码转换时,既可以利用iconv函数族编程实现,也可以利用iconv命令来实现,只不过后者是针对文件的,即将指定文件从一种编码转换为另一种编码。
一、利用iconv函数族进行编码转换
iconv函数族的头文件是iconv.h,使用前需包含之。
#include <iconv.h>
iconv函数族有三个函数,原型如下:

(1) iconv_t iconv_open(const char *tocode, const char *fromcode);
此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。
(2) size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft);
此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间。 (3) int iconv_close(iconv_t cd);
此函数用于关闭转换句柄,释放资源。
例子1: 用C语言实现的转换示例程序

/* f.c : 代码转换示例C程序 */
#include <iconv.h>
#define OUTLEN 255
main()
{
char *in_utf8 = "姝e?ㄥ??瑁?";
char *in_gb2312 = "正在安装";
char out[OUTLEN];

//unicode码转为gb2312码
rc = u2g(in_utf8,strlen(in_utf8),out,OUTLEN);
printf("unicode-->gb2312 out=%sn",out);
//gb2312码转为unicode码
rc = g2u(in_gb2312,strlen(in_gb2312),out,OUTLEN);
printf("gb2312-->unicode out=%sn",out);
}
//代码转换:从一种编码转为另一种编码
int code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen)
{
iconv_t cd;
int rc;
char **pin = &inbuf;
char **pout = &outbuf;

cd = iconv_open(to_charset,from_charset);
if (cd==0) return -1;
memset(outbuf,0,outlen);
if (iconv(cd,pin,&inlen,pout,&outlen)==-1) return -1;
iconv_close(cd);
return 0;
}
//UNICODE码转为GB2312码
int u2g(char *inbuf,int inlen,char *outbuf,int outlen)
{
return code_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen);
}
//GB2312码转为UNICODE码
int g2u(char *inbuf,size_t inlen,char *outbuf,size_t outlen)
{
return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);
}

例子2: 用C++语言实现的转换示例程序

/* f.cpp : 代码转换示例C++程序 */
#include <iconv.h>
#include <iostream>

#define OUTLEN 255

using namespace std;

// 代码转换操作类
class CodeConverter {
private:
iconv_t cd;
public:
// 构造
CodeConverter(const char *from_charset,const char *to_charset) {
cd = iconv_open(to_charset,from_charset);
}

// 析构
~CodeConverter() {
iconv_close(cd);
}

// 转换输出
int convert(char *inbuf,int inlen,char *outbuf,int outlen) {
char **pin = &inbuf;
char **pout = &outbuf;

memset(outbuf,0,outlen);
return iconv(cd,pin,(size_t *)&inlen,pout,(size_t *)&outlen);
}
};

int main(int argc, char **argv)
{
char *in_utf8 = "姝e?ㄥ??瑁?";
char *in_gb2312 = "正在安装";
char out[OUTLEN];

// utf-8-->gb2312
CodeConverter cc = CodeConverter("utf-8","gb2312");
cc.convert(in_utf8,strlen(in_utf8),out,OUTLEN);
cout << "utf-8-->gb2312 in=" << in_utf8 << ",out=" << out << endl;

// gb2312-->utf-8
CodeConverter cc2 = CodeConverter("gb2312","utf-8");
cc2.convert(in_gb2312,strlen(in_gb2312),out,OUTLEN);
cout << "gb2312-->utf-8 in=" << in_gb2312 << ",out=" << out << endl;
}


二、利用iconv命令进行编码转换

iconv命令用于转换指定文件的编码,默认输出到标准输出设备,亦可指定输出文件。

用法: iconv [选项...] [文件...]

有如下选项可用:

输入/输出格式规范:
-f, --from-code=名称 原始文本编码
-t, --to-code=名称 输出编码

信息:
-l, --list 列举所有已知的字符集

输出控制:
-c 从输出中忽略无效的字符
-o, --output=FILE 输出文件
-s, --silent 关闭警告
--verbose 打印进度信息

-?, --help 给出该系统求助列表
--usage 给出简要的用法信息
-V, --version 打印程序版本号

例子:
iconv -f utf-8 -t gb2312 aaa.txt >bbb.txt
这个命令读取aaa.txt文件,从utf-8编码转换为gb2312编码,其输出定向到bbb.txt文件。

小结: LINUX为我们提供了强大的编码转换工具,给我们带来了方便。

应用地址:http://www.donews.net/xzwenlan/archive/2005/02/05/269237.aspx

- 作者: sagely 2005年03月31日, 星期四 22:02  回复(0) |  引用(0) 加入博采

利用openssl进行RSA加密签名小结

   加密(签名)的过程是(M的e次方)mod n,在这里我们把消息M假定为一个数字,但实际上消息一般为字符串,所以必须有一个将字符串转化为数字的规则,并且要让这个数字的大小和n相当(也不能比n大)。这样做的目的是为了使(M的e次方)> n ,假如不是这样那么C=(M的e次方)mod n = (M的e次方),也就是mod n完全没有作用,攻击者就能够轻松的通过取C的第e次方根来恢复M。那么下面来讨论这种转换的标准:
  1,计算出格式化加密分组所需的大小。如果n是一个L位的数字,那么加密分组就有L/8字节长(只舍不入)。
  2,第一个高位字节总是0,而第二个为分组类型。对加密来说,这是2,对签名来说是1,这样就确保形成的数字比n要稍小。
  3,消息存放在加密分组的低位字节中,并在之前安放一个0
  00 01 ff ff ff ff ...     00 消息数据 —— 这是签名时的转换方式
  00 02 伪随机非零字节 00 消息数据 —— 这是加密时的转换方式
  由这里可以看出,对一个消息进行重复签名时,签名结果是一样的。对一个消息进行反复加密时,得出来的加密分组是不一样的。恢复加密分组时,就只需要从第三个字节开始一直向右推进到一个0字节为止,这就找到了数据起始位置。


但是需要注意上面这个过程中还要加入摘要算法的标识符,因为:
  在RSA_sign函数中在RSA_eay_private_encrypt(i,s,sigret,rsa,RSA_PKCS1_PADDING);函数以前有一段程序,问题的答案就在这里,楼上说的摘要是存在m中的,而s=3020300C06082A864886F70D020505000410+m(34比特),这段程序意思很好理解,就是加上摘要算法的标识符。所以3020300C06082A864886F70D020505000410就是代表md5这个algorithm。
  这样我们就可以得出签名的数据的转化格式
  00 01 ff ff ff ff ... 00 算法标识 消息数据
  
那么我们看看openssl中证书签名的过程:
int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
{
//先进行ret->cert_info->signature,以及ret->sig_alg的设置;
  inl=i2d_X509_CINF(ret->cert_info,NULL);//求出证书编码后的长度
  buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl);//申请空间
  outll=outl=EVP_PKEY_size(pkey1);
  buf_outl=(unsigned char *)OPENSSL_malloc((unsigned int)inl);
  if ((buf_in == NULL) ││ (buf_outl== NULL))
    {
    outl=0;
    goto err;
    }
    p=buf_in;//p与buf-in共享一段地址
    i2d_X509_CINF(ret->cert_info,&p);//将证书编码存入buf-in
    EVP_MD_CTX_init(&ctxl);//初始化
    EVP_SignInit(&ctxl,dgst);//将需要使用的摘要算法存入ctxl中
    EVP_SignUpdate(&ctxl,(unsigned char *)buf_in,inl);//存入证书的编码值
    EVP_DigestFinal(&ctxl,&(m[0]),&m_len);//求取编码的长度为m_len摘要值存入m中
    RSA_sign(ctxl->digest->type,m,m_len,buf_out,outl,pkey->pkey.rsa)//求取摘要值的签名值,最后将长度为outl的签名值存入buf-out。
    RSA_sign最主要是调用了RSA_eay_private_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding)函数。这里值得注意的一点是: RSA_eay_private_encrypt 加密时默认调用RSA密钥文件中的p、q因子使用中国剩余定理的算法进行加密,这样可以提高效率,而不是直接调用pkey->pkey.rsa->d进行加密,所以有时候直接改动pkey->pkey.rsa->d而加密结果是不会变化的。
  在此过程中编码函数采用了EME-PKCS1——5-ENCOD编码函数,大数与字符串之间的转换函数使用的是OS2IP、I20SP格式转换函数BN_bin2bn和BN_bn2bin。EME-PKCS1_5-ENCODE 函数
输入:字符串 M 、emlen 表示信息编码以后的长度。(注意:信息M 的长度不得大于 emlen-10 个字节)
输出: EM 表示 M 经过编码以后的内容。函数的具体操作步骤是随机产生 emlen-len(M)-2 字节长度的非零字符串PS ,且len(PS)>=8 然后按照下列方式 EM= 02 ││ PS ││ 00 ││ M 的方式把它们连接起来。

- 作者: sagely 2005年03月30日, 星期三 14:38  回复(1) |  引用(0) 加入博采

linux启动慢的问题
很久没有更新blog了,主要是因为要开题了,得写点理论性的东西。并且一些基础设施也已经搭建了,下面主要是有些理论创新好完成毕业论文,所以能够写出来的经验之谈已经不多了。下面是这几天的一些小问题。

在运行linux的时候突然挂掉了,毫无反应,觉得真是奇怪,电脑硬件已经不差了, 何况还是linux操作系统,居然也死机?然后重起以后发现进Xwindows特别慢。呵呵不过这个问题我知道怎么办,因为上次我遇见过,具体为什么我也没搞明白,据我推测是开机启动的时候往/tmp目录下入了一个.font-unix文件,这个文件与xfs服务有关,也它与/etc/X11/XFree86Config里面的FontPath "UNIX/:7100"有关系。下面是解决办法:
1:删除/tmp目录下所有文件,在这里有人告诉我说用rm -rf *,我觉得可能还是删除不掉.font-unix文件,不知道有没有效果,我的做法就是
     rm -rf /tmp
     mkdir /tmp
     chmod 777 /tmp
    最后一句话很重要,这次我一急就忘记这句话了。马上就造成完全不能进入xwindows,连命令行都登不进去,郁闷透顶。那就只好拿安装盘F4,然后linux rescue,不过需要注意的是,假如要进入真正的目录的话,好象要cd /mnt/sysimage,然后把/tmp权限给改了。但是重启以后发现还是特别慢,那就只能把FontPath "UNIX/:7100" 注释掉,这次重启果然快了,可是过了一天后发现好象没有输入法了,xfs &发现有错误,哎,现在还没解决呢,有谁知道请告诉我,我只好重装个输入法了。

- 作者: sagely 2005年03月29日, 星期二 18:37  回复(3) |  引用(0) 加入博采

为IE增加按钮
基本原理:
从IE5开始便允许我们向工具栏添加自己的按钮,其本质就是修改注册表,添加创建此按钮所需的信息。
实现步骤:
1.创建此按钮的GUID(globally unique identifier)
你可以通过Visual Studio中的Guidgen.exe来产生GUID。
例如我生成的GUID是{1FBA04EE-3024-11D2-8F1F-0000F87ABD16}
以下的例子中我都使用这个GUID来作说明。
2.创建子键HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Extensions\{1FBA04EE-3024-11D2-8F1F-0000F87ABD16}
3.在此子键下创建如下字串值。
(1)CLSID
这是IE的CLSID,其值必须为{1FBA04EE-3024-11D2-8F1F-0000F87ABD16}
(2)Default Visible
指明此按钮默认状态下是否可见,Yes表示可见,No为不可见
(3)ButtonText
按钮文字
(4)Icon
默认状态下的图标全路径,例如c:\vckbase.ico。也可以是EXE文件中包含的图标,例如:C:\PROGRA~1\NETANTS\NetAnts.exe,1000
(5)HotIcon
鼠标移到按钮上时的图标全路径
如下子键为按下按钮后需要执行的相应动作:可以是COM对象、浏览条Explorer Bar、脚本Script、可执行文件。
下面是网络蚂蚁修改注册表的例子: Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Extensions\{57E91B47-F40A-11D1-B792-444553540000}] "CLSID"="{1FBA04EE-3024-11D2-8F1F-0000F87ABD16}" "Default Visible"="Yes" "HotIcon"="C:\\PROGRA~1\\NETANTS\\NetAnts.exe,1001" "Icon"="C:\\PROGRA~1\\NETANTS\\NetAnts.exe,1000" "Exec"="C:\\PROGRA~1\\NETANTS\\NetAnts.exe" "ButtonText"="NetAnts" "MenuText"="&NetAnts" "MenuStatusBar"="Launch NetAnts" 下面来看看具体的编程过程。 //这是由GUIDGEN产生的GUID:{06926B30-424E-4f1c-8EE3-543CD96573DC} CRegKey reg; char KeyName[]="Software\\Microsoft\\Internet Explorer\\Extensions\\{06926B30-424E-4f1c-8EE3-543CD96573DC}"; TCHAR PathName[MAX_PATH]; TCHAR IconPathName[MAX_PATH]; ///正常时的图标全路径 TCHAR HotIconPathName[MAX_PATH]; ///鼠标覆盖时的图标全路径 GetModuleFileName(0,PathName,MAX_PATH); ///得到本可执行文件的路径 strcpy(IconPathName,PathName); strcpy(HotIconPathName,PathName); strcat(HotIconPathName,",131"); ///131是图标的ID,你可以以资源方式打开EXE文件就可以看到所有资源及其ID strcat(IconPathName,",129"); reg.Create(HKEY_LOCAL_MACHINE,KeyName); reg.SetValue("{1FBA04EE-3024-11D2-8F1F-0000F87ABD16}","CLSID"); reg.SetValue("Yes","Default Visible"); reg.SetValue("VC知识库","ButtonText"); reg.SetValue(IconPathName,"Icon"); reg.SetValue(HotIconPathName,"HotIcon"); /////假如是执行脚本,可以是reg.SetValue("c:\\test.html","Script"); ///在test.html 存放你的脚本代码
reg.SetValue("http://www.vckbase.com/","Exec");///打开网页 下面我们再来看看如何添加COM组件 对于COM组件来说,它是没有Exec键名的,但是它多了一个ClsidExtension键名,包含一个类标识,通过这个类标识,IE能够找到实现扩展的COM组件。ClsidExtension实质上等于COM组件的全球唯一定位符COM组件应该在注册时实现上述注册项的添加。而且COM组件还应该实现IoleCommandTarget接口,另外如果你的COM 对象还需要存取当前IE显示的DHTML网页,你还需要实现IobjectWithSite接口。在实现IoleCommandTarget接口的时候,你必须提供IoleCommandTarget::Exec方法,这个方法有一个参数nCmdID标识调用是工具栏按钮单击激活或是菜单响应激活,这种差别允许编程人员为两种不同的事件提供不同的行为。当你实现IobjectWithSite接口时,Internet Explorer会调用IobjectWithSite::SetSite,并传递给它一个IshellBrowser指针,借助于这个指针可以获得与浏览相关的IwebBrowser对象,通过它你就可以对HTML网页进行解析,访问页面中的每一个元素了。 参考文献:http://www.vckbase.com/document/viewdoc/?id=190 http://www.ccw.com.cn/htm/app/salon/01_12_12_3.asp

- 作者: sagely 2005年03月24日, 星期四 10:46  回复(0) |  引用(0) 加入博采

学习使用cryptoapi第三天
1,CertOpenSystemStore打开系统最常用的证书存储区域。假如需要满足复杂的需要,请看CertOpenStore
HCERTSTORE WINAPI CertOpenSystemStore(
HCRYPTPROV hprov, //CSP句柄,NULL为默认句柄,或者由CryptAcquireContext返回
LPTCSTR szSubsystemProtocol //打开的系统存储区的名字。假如名字不为CA,MY,ROOT,SPC则新建一个证书存储区域,可以使用CertEnumSystemStore列出所有的已存在的系统存储区
);
2,CertOpenStore使用一个指定的存储区提供类型来打开一个证书存储区。
HCERTSTORE WINAPI CertOpenStore(
LPCSTR lpszStoreProvider, //指定提供的存储的类型,大量类型,请参见MSDN
DWORD dwMsgAndCertEncodingType, //只有当上一参数为CERT_STORE_PROV_MSG, CERT_STORE_PROV_PKCS7, or CERT_STORE_PROV_FILENAME才使用,否则必须为0
HCRYPTPROV hCryptProv, //密码算法提供方的句柄,推荐使用默认,将参数置为NULL
DWORD dwFlags, //它由高字节和低字节组成,参数众多。
const void* pvPara //void类型,可以指向任意类型数据。
);
例如:if(hSysStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,NULL,CERT_SYSTEM_STORE_CURRENT_USER,L"MY")打开系统的MY存储区
3,CertCloseStore关闭打开的证书存储区句柄
BOOL WINAPI CertCloseStore(
HCERTSTORE hCertStore, //证书存储区句柄
DWORD dwFlags
);
第二个参数一般为0,关闭了存储区,但是里面内容并没有释放
假如为CERT_CLOSE_STORE_CHECK_FLAG,检查没有释放空间的证书,CRL和CTL内容。他将返回一个错误报告。一般只用用于程序的诊断工具。
假如为CERT_CLOSE_STORE_FORCE_FLAG,则强制释放相关空间。他只在存储区打开并且存储区以及其相关内容没有被别的程序调用的时候使用才安全的。
4,CertDuplicateStore复制存储区,其reference count 也将增一,返回一个存储区的句柄
HCERTSTORE WINAPI CertDuplicateStore(
HCERTSTORE hCertStore
);
5,CertFindCertificateInStore从证书存储区中寻找符合指定要求的证书内容
PCCERT_CONTEXT WINAPI CertFindCertificateInStore(
HCERTSTORE hCertStore, //打开的证书存储区的句柄
DWORD dwCertEncodingType, //指定编码的类型,一般为X509_ASN_ENCODING | PKCS_7_ASN_ENCODING
DWORD dwFindFlags, //用来修改查找规则,一般都不用并且把它设置为0
DWORD dwFindType, //指定的查找类型,类型中多,例如CERT_FIND_CERT_ID
const void* pvFindPara, //需要查找的内容
PCCERT_CONTEXT pPrevCertContext //返回最近一次返回的CERT_CONTEXT结构。
);
例如:CertFindCertificateInStore(hSystemStore,MY_ENCODING_TYPE,0,CERT_FIND_SUBJECT_STR,L"Cert_subject_1",NULL);
6,CertCreateCertificateContext从一个编码证书创建一个证书内容
PCCERT_CONTEXT WINAPI CertCreateCertificateContext(
DWORD dwCertEncodingType, //指定编码的类型,一般为X509_ASN_ENCODING | PKCS_7_ASN_ENCODING
const BYTE* pbCertEncoded, //包含编码证书内容的指针
DWORD cbCertEncoded //编码证书数据的长度
);
7,CertAddCertificateContextToStore将一个证书内容增加到证书存储区中。
BOOL WINAPI CertAddCertificateContextToStore(
HCERTSTORE hCertStore, //证书存储区的句柄
PCCERT_CONTEXT pCertContext, //CERT_CONTEXT结构指针
DWORD dwAddDisposition, //指定与已存在相同证书的操作,例如CERT_STORE_ADD_ALWAYS
PCCERT_CONTEXT* ppStoreContext //一个证书的复制的指针,可以为NULL,说明不需要返回证书的复制。
);
8,CertAddCertificateLinkToStore增加一个从一个证书存储区中证书内容到另一个证书存储区的连接
BOOL WINAPI CertAddCertificateLinkToStore(
HCERTSTORE hCertStore, //需要被增加的证书存储区的句柄
PCCERT_CONTEXT pCertContext, //CERT_CONTEXT结构指针
DWORD dwAddDisposition, //指定与已存在相同证书的操作,例如CERT_STORE_ADD_ALWAYS
PCCERT_CONTEXT* ppStoreContext //一个连接的复制的指针,可以为NULL,说明不需要返回证书的复制。
);
9, CertEnumCertificatesInStore从证书存储区中获取第一或者下一个证书。使用循环,他可以获取存储区所有的证书序列
PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(
HCERTSTORE hCertStore, //证书存储区的句柄
PCCERT_CONTEXT pPrevCertContext //上一个证书内容的CERT_CONTEXT结构指针,当第一次开始列举时参数必须为NULL
);
10,CryptUIDlgViewContext显示一个证书,CTL或者CRL内容
BOOL WINAPI CryptUIDlgViewContext(
DWORD dwContextType, //表示指向何种类型。参数有CERT_STORE_CERTIFICATE_CONTEXT,CERT_STORE_CRL_CONTEXT,CERT_STORE_CTL_CONTEXT
const void* pvContext, //要显示的证书,CRL或者CTL内容
HWND hwnd, //需要显示的窗口句柄,当为NULL的时候默认为桌面窗口
LPCWSTR pwszTitle, //显示的标题名,当为NULL时默认为内容类型
DWORD dwFlags, //暂时没被使用,并且必须为0
void* pvReserved //保留字,为将来使用。
);
例如:
CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT,pCertContext,NULL,NULL,0,NULL);
11,CertGetNameString获取CERT_CONTEXT结构中的主题或者签发者,并且将他转化为以null结尾的字符串
DWORD WINAPI CertGetNameString(
PCCERT_CONTEXT pCertContext, //包含CERT_CONTEXT证书内容的指针
DWORD dwType, //指定如何找到名字,并且输出的格式,例如CERT_NAME_ATTR_TYPE
DWORD dwFlags, //指定需要处理的类型,CERT_NAME_ISSUER_FLAG请求签发者名字,不设置则代表主题名
void* pvTypePara, //或者是一个包含dwStrType的字节指针,或者是一个指定名字属性的对象标志符指针
LPTSTR pszNameString, //转换后返回的字符串指针
DWORD cchNameString //上一字符串长度,以NULL结尾
);
如:CertGetNameString(pCertContext,CERT_NAME_SIMPLE_DISPLAY_TYPE,0,NULL,pszNameString,128)
12,CertEnumCertificateContextProperties获取与证书内容相关的第一个或者下一个扩展属性
DWORD WINAPI CertEnumCertificateContextProperties(
PCCERT_CONTEXT pCertContext, //CERT_CONTEXT结构指针
DWORD dwPropId //Property number of the last property enumerated. 参数为0时,获取第一个属性
);
13,CertGetCertificateContextProperty获取每个扩展属性的信息。
BOOL WINAPI CertGetCertificateContextProperty(
PCCERT_CONTEXT pCertContext, //CERT_CONTEXT指针
DWORD dwPropId, //需要获取的属性,参数众多,例如CERT_ACCESS_STATE_PROP_ID
void* pvData, //接收返回的数据指针
DWORD* pcbData //数据长度指针
);
例如:CertGetCertificateContextProperty(pCertContext, dwPropId , NULL, &cbData)
14,CryptUIDlgSelectCertificateFromStore显示一个对话框,允许在其中选择指定的证书。
PCCERT_CONTEXT WINAPI CryptUIDlgSelectCertificateFromStore(
HCERTSTORE hCertStore, //被查找的证书存储区句柄
HWND hwnd, //要显示的窗口句柄,NULL默认为桌面窗口
LPCWSTR pwszTitle, //对话框标题,NULL默认为“Select Certificate”
LPCWSTR pwszDisplayString, //在选中的对话框中显示的语句,NULL默认为"Select a certificate you wish to use"
DWORD dwDontUseColumn, //排除一些显示的列,例如CRYPTUI_SELECT_ISSUEDTO_COLUMN不显示ISSUEDTO信息
DWORD dwFlags, //暂时设置为0
void* pvReserved //保留字,还未使用。
);
15,CertCompareCertificateName比较两个证书CERT_NAME_BLOB结构是否一致,成功返回true,否则返回false;
BOOL WINAPI CertCompareCertificateName(
DWORD dwCertEncodingType, //指定编码的类型,一般为X509_ASN_ENCODING | PKCS_7_ASN_ENCODING
PCERT_NAME_BLOB pCertName1, //CERT_NAME_BLOB指针
PCERT_NAME_BLOB pCertName2
);
16,BOOL WINAPI CertComparePublicKeyInfo(比较公钥信息。
DWORD dwCertEncodingType,
PCERT_PUBLIC_KEY_INFO pPublicKey1,
PCERT_PUBLIC_KEY_INFO pPublicKey2
);
17,BOOL WINAPI CertCompareCertificate(比较两个证书
DWORD dwCertEncodingType,
PCERT_INFO pCertId1,
PCERT_INFO pCertId2
);
18,BOOL WINAPI CertDeleteCertificateFromStore(从一个证书存储区中删除一个证书。
PCCERT_CONTEXT pCertContext
);
19,BOOL WINAPI CertSerializeCertificateStoreElement(serializes a certificate context's encoded certificate

and its encoded properties
PCCERT_CONTEXT pCertContext, //CERT_CONTEXT指针
DWORD dwFlags, //保留字,为将来使用,设置为0
BYTE* pbElement, //Pointer to a buffer that receives the serialized output, including the

encoded certificate and possibly its properties.
DWORD* pcbElement //上一参数的数据长度。
);
20,CertAddEncodedCertificateToStore从编码证书中创建一个证书内容并且把他加入证书存储区。
BOOL WINAPI CertAddEncodedCertificateToStore(
HCERTSTORE hCertStore, //证书存储区句柄
DWORD dwCertEncodingType, //指定编码的类型,一般为X509_ASN_ENCODING | PKCS_7_ASN_ENCODING
const BYTE* pbCertEncoded, //编码证书指针
DWORD cbCertEncoded, //编码证书长度
DWORD dwAddDisposition, //指定当已存在该证书时的操作。例如CERT_STORE_ADD_ALWAYS
PCCERT_CONTEXT* ppCertContext//证书内容的指针。可以为NULL。
);
例如:CertAddEncodedCertificateToStore(hFileStore,MY_ENCODING_TYPE,pCertContext->pbCertEncoded,pCertContext-

>cbCertEncoded,CERT_STORE_ADD_USE_EXISTING,NULL)
21, CertAddEnhancedKeyUsageIdentifier 增加一个增强密钥用途
BOOL WINAPI CertAddEnhancedKeyUsageIdentifier(
PCCERT_CONTEXT pCertContext,//Cert_context结构。
LPCSTR pszUsageIdentifier //指定需要增加的OID
);
22,CertSetCertificateContextProperty设置指定的证书内容的扩展属性
BOOL WINAPI CertSetCertificateContextProperty(
PCCERT_CONTEXT pCertContext,
DWORD dwPropId,
DWORD dwFlags,
const void* pvData
);
22,CertNameToStr 转换编码后名字到以NULL结尾的字符串中。
DWORD WINAPI CertNameToStr(
DWORD dwCertEncodingType,
PCERT_NAME_BLOB pName,
DWORD dwStrType,
LPTSTR psz,
DWORD csz
);
23,CertStrToName转化一个以NULL结尾的字符串到证书的名字
BOOL WINAPI CertStrToName(
DWORD dwCertEncodingType,
LPCTSTR pszX500,
DWORD dwStrType,
void* pvReserved,
BYTE* pbEncoded,
DWORD* pcbEncoded,
LPCTSTR* ppszError
);

- 作者: sagely 2005年03月21日, 星期一 15:10  回复(7) |  引用(0) 加入博采

windows2003的安装
  1,买了一个windows2003企业版的盘,直接在电脑上将windows2000升级.可是在升级过程中出现oembios.bin文件无法找到,然后重试也没办法找到,只好忽略.居然能够正常升级,并且启动都很正常,心中偷喜,原来安装的时候找不到文件也行.然后输入用户名和密码,突然出现一个错误提示,说无法确认计算机身份,然后进不了系统.连正常关机都不行.
上网找了找这方面资料,原来oembios.bin是必须的,好象是什么激活文件.既然进不了系统,一激动就重装了,安装过程中照样这个文件找不到,这回知道凶多吉少拉,果然安装完以后还是进入不了系统.实在无法,只好找电子市场老板换碟,换回来居然是个坏的,又不能用,只好郁闷,不过忽然一想看看是否这个盘中有oembios.bin文件,搜索一下oembios.bi_,然后expand oembios.bi_ oembios.bin,居然能行,立即把这个文件在安全模式下复制到system32下面,重新启动,一切都好,连MS的自动更新都能用.
  2,可是重装了win2003发现启动的时候不提示我进入linux还是windows就直接进入了windows,难道我linux完蛋了?赶紧查资料,原来是安装的windows将mbr修改了,按照下面的方法可以恢复:
  插入linux第一张盘(当然是选光区启动),按F4;
  输入linux rescue;
  简单配置后在sh#下输入grub;
在grub命令行下输入:find /boot/grub/grub.conf 可能返回root (hd0,7)
在grub命令行下输入:root (hd0,7)
在grub命令行下输入:setup (hd0)
最后,reboot,exit就行了.

- 作者: sagely 2005年03月18日, 星期五 17:20  回复(4) |  引用(0) 加入博采

高级指针话题
在openssl里出现了大量的指向指针的指针和函数指针,一直不太理解,今天看书上有一章介绍指针的高级话题,赶紧把它记录下来。
  1,指针以及初始化
  指针是一个地址,它指向内存中某个指定类型的值,而操作符*就是访问指向这个地址的数据。讨论一下指针的初始化。
  考虑:
       int *a;
       *a=100;
  也许会觉得这样没有错误,因为(*a)就是int型的,所以把100赋予一个int型的没错。但是我们在这里创建了一个指针变量a,但是没有给a初始化,然后用*操作符去访问它,当然是会出错的。

  2,指向指针的指针,下面分别看几个例子
  char string[3]={'c','d','e'}.定义了三个char型的变量string[0]='c',string[1]='d',string[2]='e'.
  char *pstring={"cde"},定义了一个字符串,其中string[0]='c',string[1]='d',string[2]='e'.
  现在明显可以看出上面两者的联系了。其实string=pstring.
  char string[3][3]={'M','o','n';'T','u','e';'W','e','d'};这样string[0][0]='M',,,,,
  char *pstring[3]={"Mon","Tue","Wed"},定义了三个char *string型的变量。string[0]="Mon",string[0][0]='M'
  char **ppstring.那这个是什么呢,他就是个指向指针的指针,可以直接初始化ppstring=pstring,或者可以ppstring=&(pstring[0]),使用的时候可以完全和*pstring[3]差不多使用了。
  所以指向指针的指针也就是多了一个间接访问而已,只要知道了指针就是地址,*就是去访问地址的数据就可以了。
 
  3,函数指针。
  int (*f)(),前面一个括号迫使间接访问在函数调用之前,那么就是说访问内存中的某个位置的函数。这就是函数指针的概念。
  初始化:int f(int);  int (*pf)(inf)=&f;
  调用方式:int ans=pf(25);
  下面讨论两个具体应用的问题:
  1),回调函数
  我们先看看下面这段程序:
  int comp(int a,int b)
  {
        if(a==b)return 0;
        else return 1;
  }
  完成的功能实在是简单,就是比较一下两个数是否一致。但是你是否发现这个只能比较int型的数据,要是比较char的呢,那必须得重新写一个函数,比较float也得重新写一个,这样是不是有点麻烦,并且易用性也不好,换一个类型就要换一个函数。那么我们考虑是否在comp的时候不传具体的类型呢,因为我们根本也不知道要传什么类型给comp。解决难题的办法就是把参数类型声明为void *,表示"一个指向未知类型的指针"。然后加一个回调函数作为参数,这样在按照不同的类型编写不同的回调函数,在上层就保证了comp函数的易用性。下面请看改写的函数
  int comp(void *a,void *b, int (*compare)(void const *,void const *))
  {
 if(compare(a,b))return 1;
 else return 0;
  }
  int compare_int(void const *a,void const *b)
  {
 if(*(int*)a==*(int*)b) return 0;
 else return 1;
  }
  int compare_char(void const *a,void const *b)
  {
 if(*(char*)a==*(char*)b) return 0;
 else return 1;
  }
在主函数中可以这样调用
  int a=2;int b=2;
  comp(&a,&b,compare_int);
  char c='d';char d='d';
  comp(&d,&c,compare_char);
  现在在C++中已经有重载和模板的技术了,上面的任务根本不用这么麻烦实现的。但是openssl是用C语言写的,里面大量的void类型,并且大量的指向函数的指针,希望这点讲解对大家看openssl能有点帮助。

  2),转移表
  我们下面看个例子,在一个计算器的例子中,有如下一些语句:
  switch(oper)
  case ADD:
          result=add(op1,op2);
          break;
  case SUB:
          result=sub(op1,op2);
          break;
  case MUL:
          result=mul(op1,op2);
          break;
  case DIV:
          result=div(op1,op2);
          break;
...
  对于一个功能复杂的计算器,那么switch语句将非常长。为了使用switch语句,表示操作符的代码必须是整数。如果它们是从零开始连续的整数,我们可以使用转换表来完成这个任务。转换表就是一个函数指针数组。
  创建一个转换表需要两个步骤。首先,声明并初始化一个函数指针数组。唯一需要留心之处就是确保这些函数的原形出现在这个数组的声明之前。
  double add(double,double);
  double sub(double,double);
  double mul(double,double);
  ...
  double (*oper_func[])(double,double)={add,sub,mul,div,...};
  初始化列表中各个函数名的正确顺序取决于程序中用于表示每个操作符的整型代码。这个例子假定ADD是0,SUB是1,MUL是3,,,
  第2个步骤是用下面语句替换前面整条switch语句:
  result=oper_func[oper](op1,op2);
  oper从数组中选择正确的函数指针,而函数调用操作符将执行这个函数。

- 作者: sagely 2005年03月16日, 星期三 22:35  回复(0) |  引用(0) 加入博采