如何用openssl 生成RSA双密匙;签名证书;加密文件邮件

具体看转载:http://blog.csdn.net/jiangsq12345/article/details/6066275

评价:教授写的很好,但是翻译很烂。另外对大文件生成摘要发送给对方这里翻译得不清晰:是发送大文件生成的密码和摘要的签名两个文件?

很实用的另外一篇文章:

利用openssl进行RSA加密解密

转自:http://www.cnblogs.com/aLittleBitCool/archive/2011/09/22/2185418.html

对于 Openssl 软件包的介绍 (转载自百度百科)

Openssl

众多的密码算法、公钥基础设施标准以及SSL协议,或许这些有趣的功能会让你产生实现所有这些算法和标准的想法。果真如此,在对你表示敬佩的同时,还是忍 不住提醒你:这是一个令人望而生畏的过程。这个工作不再是简单的读懂几本密码学专著和协议文档那么简单,而是要理解所有这些算法、标准和协议文档的每一个 细节,并用你可能很熟悉的C语言字符一个一个去实现这些定义和过程。我们不知道你将需要多少时间来完成这项有趣而可怕的工作,但肯定不是一年两年的问题。 继续阅读

tinyxml和minixml,两个XML库有何不同,看了就知道了

XML库方面,我知道的有expatlibxml2tinyxmlminixml

听说expat应用很广,但我没有用过……libxml2这个东东给我的印象是拥肿。

我今天推荐后两者,一个是基于C++编写的tinyxml库,另一个是基于C编写的minixml库。

我自己最常用的是tinyxml,此库用C++进行封象,适度的面向对象,命名很人性化,是一个很不错的选择。但这个库的Makefile没有带编译为动态库的方法,要编译为动态库,只要把Makefile相关行改为:
DEBUG := NO
TINYXML_USE_STL := NO # 个人认为没必要加入STL的支持
RELEASE_CFLAGS := -Wall -Wno-unknown-pragmas -Wno-format -O3 -fPIC
LIBS := -shared -s
OUTPUT := libtinyxml.so
SRCS行去掉xmltest.cpp
然后保存,make即可生成libtinyxml.so,以后只要include自带那两个h头文件即可使用tinyxml库了

另一个推荐的是minixml库,这个库的出现是因为很多时候没必要用libxml2这个拥肿的东西(听说有10万行, minixml才三千多行)。
这个库我暂时还没用过,有时间会试用一下。这个为自带configure,配置、编译都非常方便,而且是纯C的,所以对各种应该都比较合适,CUPS就是使用minixml库的。

两个库都是很轻量级的,tinyxml编译成动态库后不到78K(O3优化),minixml为44K(Os优化),而且都可以用于windows,因为都自带VC工程文件,可以选择合自己口味的,have fun~

转自:http://imlcl.com/?tag=minixml

在MySQL中调试MTPower

由于我们MySQL小组开发的MTPower版本极多,到现在为止显得有些混乱,这里推荐大家使用改进的MDB(Multi-threaded Disk Buffer)版本,因为这个版本是在原有版本的基础上改进的版本,MDB性能也是最好的。这个版本在八核服务器/home/robin/bishe/source目录中mysql-6.0.9-alpha目录(可用root用户进入),将整个mysql-6.0.9-alpha文件拷贝到自己的目录中:

[code lang=”shell”]
root@localhost source]# pwd
/home/robin/bishe/source
[root@localhost source]# cp -r mysql-6.0.9-alpha /home/somebody
[root@localhost source]# cd /home/somebody
[root@localhost mysql]# ls -la
total 4
drwxr-xr-x 33 root root 4096 May 4 16:13 mysql-6.0.9-alpha
[/code]

然后改变改变mysql-6.0.9-alpha 的拥有者

[code lang=”shell”]
[root@localhost mysql]# chown -R somebody:somebody mysql-6.0.9-alpha
[/code]

退出超级用户,以用户身份进入

[code lang=”shell”]
[root@localhost mysql]# exit
[/code]

进入到mysql-6.0.9-alpha目录下,配置、编译并安装

[code lang=”shell”]
[liao@localhost mysql]$ cd mysql-6.0.9-alpha/
[liao@localhost mysql-6.0.9-alpha]$
[liao@localhost mysql-6.0.9-alpha]$ ./BUILD/autorun.sh
[liao@localhost mysql-6.0.9-alpha]$ ./configure –prefix=/home/somebody/deploy –with-plugins=mtpower –with-debug=full
[liao@localhost mysql-6.0.9-alpha]$ make
[liao@localhost mysql-6.0.9-alpha]$ make install
[/code]

这里注意几点:

1、./BUILD/autorun.sh是必要的,特别是在MTPower中添加了自己写的C/C++源文件,这一步必不可少;另外若是在此目录下进行第一次编译操作也最好./BUILD/autorun.sh,以后如果还是在此目录下编译或安装都不必再./BUILD/autorun.sh,除非如刚才所说,增删了源文件;

2、–with-plugins=MTPOWER意思是把MTPower编译进mysql并安装,如果是对MTPower进行开发,这个选项肯定要有,默认没有;

3、–with-debug=full 这个选项是调试用的,默认没有(即普通安装,非调试模式)。另外,当我们需要安装MTPower但不需要调试模式时(即–with-debug=full不必写上),还有很重要的一步就是在make之前要吧mysql-6.0.9-alpha/storage/MTPower目录下的Makefile的-O3改成-g,告诉编译器不对MTPower进行优化,否则mtpower会有些难以发现的错误。

4、–prefix=/home/somebody/deploy是设置mysql的安装路径,请务必加上,以免覆盖默认安装目录下的文件。还有一点是安装之后mysql server的启动比较麻烦,如果嫌麻烦,可以配置成–prefix=/home/liao/benchmark/buffer_improved/deploy ,即安装在我的目录下,但需要root权限,即以root用户make install(make install之前的命令用过用户的权限就可以完成)。make install后可以直接进入安装目录运行或调试mysql。据我的经验,这是没有出现什么问题的。

5、在接下来的开发mysql过程中,如果只是增减代码而没有增减文件,每次更改完后不必再/BUILD/autorun.sh和./configure,只需make && make install就可以了。

接下来讲讲如何调试MTPower。如上所述,要对MTPower进行调试,–with-plugins=MTPOWER –with-debug=full必须都要选上,然后再make && make install.
安装完毕后进入到安装目录(这里假设/home/liao/benchmark/buffer_improved/deploy),用ls命令查看。
可以看到有个libexec文件夹,该文件夹下面有个mysqld文件,这个就是服务器端二进制文件,我们要做的就是对这个文件进行调试(调试过程最好用root用户,这样可以避免mysql权限问题)。

如果要设置断点,可以在run -uroot之前设置,比如

(gdb) b ha_mtpower.cc:500 –在ha_mtpower.cc第500行设置断点

(gdb) b ha_mtpower::create –在ha_mtpower类成员函数create中设置断点

另外断点还可以在调试过程中设置。

然后用mysql客户端连接mysql server,

当代码在断点处停止时,就可以进行单步等等之类的调试了,具体可以看gdb使用说明。

另外还可以自己写一些测试程序当作客户端(作为例子可以查看/home/liao/benchmark/buffer_improved/test 目录下的benchmark.c文件),这样就不必每次都在客户端中输入SQL语句了。

文远补充说明:

文远  20:41:22
4.在make install之后,还要执行scripts/mysql_install_db,用于创建数据目录var
文远  20:44:49
cp supoort-files/选一个 /安装目录var/my.cnf,之后在my.cnf中[mysqld]中写入 user = mysqld

用snprintf取代不安全的sprintf,防止程序挂掉(core)

        这里讲的不安全,是指访问内存越界导致程序挂掉。程序挂掉影响大小要看具体的业务。如果程序挂掉导致业务中断,这就是比较严重的,也是不允许的。如果程序真的挂了,也会有相应的机制应对,比如监控并重启。当然了,如果程序不那么重要,比如一些批跑程序,再次运行即可。
MSVC的_snprintf 与gcc的snprintf(C99)行为不一样!!!  _snprintf在buff结尾有可能没有’\0’,所以跨平台时,还是保留最后一个字节安全(长度20的buff,传给snprintf,只用19)snprintf (或者_snprintf )可以用来只计算长度,如:int c = snprintf(NULL,0,……);asprintf 第一个参数是指向指针的指针,它会在heap中自动申请空间(最后要手动free)。使用asprintf ,要加上 #define     _GNU_SOURCE
转帖:
在 C 語言裡,要建立一個字元陣列的字串,常常會使用 sprintf() 這個函數來做格式化的處理。但是實際上,這個函式卻不是那麼「安全」。怎麼說呢?sprintf() 的整個介面長的樣子的是:int sprintf ( char * str, const char * format, … )也就是在使用前,必須要先建立好一個字元陣列的空間,再用這個函式把內容填入,下面就是簡單的例子:

int tmp = 10;
char cstr[20];
sprintf( cstr, “%d * %d = %d”, tmp, tmp, tmp * tmp );

在 這個例子裡,cstr 最後的值,會是「10 * 10 = 100」,看起來好像很好?但是如果把 tmp 的值改成 10000 的話,cstr 則應該要變成「10000 * 10000 = 100000000」,但是由於這時候的字串所需長度為 26,而要寫入的 cstr 的長度只有 20,所以就會造成 buffer overflow 的問題。

像如果是以 Visual C++ 2006 來編譯的話,如果程式裡有用到 sprintf(),他在編譯時就會顯示一個警告訊息:

warning C4996: ‘sprintf’: This function or variable may be unsafe. Consider using sprintf_s instead.

而要怎麼避免 sprintf 的 buffer overflow 的問題呢?除了微軟建議的 sprintf_s() 外,實際上在 C99 裡, 也多了一個 snprinf() 是用來取代現有的 sprintf() 了~他的介面是:

int snprintf(char *str, size_t size, const char * restrict format, …)

應該可以明顯看得出來,snprinf() 這個函式比 sprintf() 多了一個參數 size;這個參數的用處,就是用來限制最大的寫入資料量,可以用來避免 buffer overflow。以上面的例子來說,本來寫:

int tmp = 10000;
char cstr[20];
sprintf( cstr, “%d * %d = %d”, tmp, tmp, tmp * tmp );

的話,會產生 buffer overflow 的問題。而如果改成用 snprinf() 的話,就是變成:

int tmp = 10000;
char cstr[20];
snprintf( cstr, sizeof( cstr ), “%d * %d = %d”, tmp, tmp, tmp * tmp );

這樣一來,snprinf() 在把資料寫到 cstr 時,最多就只會寫入 20 個字元(cstr 的長度),而不會有 buffer overflow 的問題了~

不過比較討厭的是,MSVC 似乎並沒有直接給這個函式,而是另外給了一個 _snprinf()…雖然功能和參數都大同小異,但是光函式名稱不一樣,就已經增加了些麻煩,更別說在行為模式上也有些不同了。而 _snprinf() 和 snprintf() 主要的差別在於:

_snprintf() (MSVC) snprintf()
回傳值 · 當 len <= size 時,會回傳 len· 當 len > size 時,會回傳負值(-1) · 正常狀況會回傳 len。· 如果有錯誤,回傳負值(-1)
字串內容 · 當 len < size 時,str 會包含結尾的 ‘\0’· 當 len >= size 時,str 不會有結尾的 ‘\0’ · str會包含結尾的 ‘\0’
· len:要輸出的字串應有的長度,不包含結尾的 ‘\0’。· size:snprintf/ _snprintf 的第二個參數,寫到 str 的最大資料量。

所以如果要跨平台,大致上應該可以:

如果是使用 MSVC 的話,自行定義 snprintf,讓它變成 _snprintf
#ifdef _MSC_VER
#define snprintf _snprintf
#endif

實際使用,則就可以直接用 snprintf
int tmp = 10000;
char cstr[20];
int size = sizeof( cstr );
int c = snprintf( cstr, size, “%d * %d = %d”, tmp, tmp, tmp*tmp );
if( c > size || c < 0 )
cstr[ size – 1 ] = ‘\0’;

這樣應該就可以在 g++ 和 MSVC 的環境裡,都可以避免 buffer overflow 和字串結尾沒有 ‘\0’ 的問題了~

但是這樣的做法,實際上是產生一個最大長度為 20 的字串,如果超過的話,雖然不會有 buffer overflow 的問題,但是過長的部分還是要切掉。而如果希望可以針對需要,產生一個夠長的字串的話,其實還可以使用 asprintf() 這個函式。他的用法很簡單,基本上和 sprintf() 很像,只是將第一個參數改成一個 char** 而已;下方就是簡單的範例:

char* cstr;
int c = asprintf( &cstr, “%d * %d = %d”, tmp, tmp, tmp*tmp );

如此一來,他就會自動替 cstr 產生一塊夠大的記憶體空間,來存放字串了~

不過 asprintf() 這個函式應該不在 C 語言的標準內,而是 GNU 的 extension(可能要加上「#define     _GNU_SOURCE」才能使用),所以在 MSVC 裡並沒有提供 asprintf() 可以使用。不過雖然沒有現成的可以用,但是還是可以透過執行兩次 snprintf() 來做到同樣的功能~實作的方法,大致上就是:

char* cstr;
int c = snprintf( NULL, 0, “%d * %d = %d”, tmp, tmp, tmp*tmp );
cstr = new char[ c + 1 ];
snprintf( cstr, c + 1, “%d * %d = %d”, tmp, tmp, tmp*tmp );

做法的主要概念,就是第一次的 _snprintf() 實際上並不真正的將字串寫到某個空間,而是單純用來取得字串所需要的長度,然後再根據需要的長度來產生字元陣列,並將資料寫入。

转自:http://heresy.spaces.live.com/blog/cns!E0070FB8ECF9015F!9703.entry

谷歌网页服务器(Google Web Server ,GWS)

谷歌Web服务器软件,它是基于Apache HTTP服务器基础开发的对谷歌应用程序优化版。
GWS是google专用的web服务器.是 google web server 的缩写
以下是google的服务器列表,顺序依次是“domain、OS、web server”:
license.google.com Linux Apache
vmware.sitesearch.google.com Linux unknown
x65.deja.com Linux GWS-GRFE/0.40
x39.deja.com Linux GWS-GRFE/0.40
x23.deja.com Linux GWS/2.1
google.com.ru Linux GWS/2.1
wwwgoogle.com Linux GWS/2.1
w.deja.com Linux GWS-GRFE/0.40
google.ie Linux GWS/2.1
gogle.com unknown GWS/2.1
google.co.nz Linux GWS/2.1
x3.dejanews.com Linux GWS-GRFE/0.40
gogole.com Linux GWS/2.1
deja.com unknown GWS-GRFE/0.40
googel.com Linux GWS/2.1
goolge.com Linux GWS/2.1
google.org Linux GWS/2.1
labs.google.com Linux Apache
x25.deja.com unknown GWS-GRFE/0.40
googlesyndication.com Linux GWS/2.1
research.google.com Linux Apache/1.3.27 (Unix)
google.co.il Linux GWS/2.1
google.com.ar Linux GWS/2.1
x22.deja.com Linux GWS-GRFE/0.40
google.net Linux GWS/2.1
google.ca Linux GWS/2.1
google.com.au Linux GWS/2.1
google.de Linux GWS/2.1
google.nl Linux GWS/2.1
google.fr Linux GWS/2.1
google.fi Linux GWS/2.1
google.co.uk Linux GWS/2.1
dejanews.dejanews.com Linux GWS-GRFE/0.40
groups.google.com Linux GWS-GRFE/0.40
google.pl Linux GWS/2.1
google.co.jp Linux GWS/2.1
google.com.ua Linux GWS/2.1
news.google.com Linux NFE/0.8
api-ab.google.com Linux GFE/1.3
google.it Linux GWS/2.1
google.at Linux GWS/2.1
api.google.com Linux GFE/1.3
google.ch Linux GWS/2.1
dejanews.com Linux GWS-GRFE/0.40
groups.google.fr Linux GWS-GRFE/0.40
services.google.com Linux Apache
x24.deja.com unknown GWS-GRFE/0.40
google.pt Linux GWS/2.1
google.cl Linux GWS/2.1
google.dk unknown GWS/2.1

linux开机启动服务和chkconfig使用方法

  1. 服务概述
    在linux操作系统下,经常需要创建一些服务,这些服务被做成shell脚本,这些服务需要在系统启动的时候自动启动,关闭的时候自动关闭。
    将需要自动启动的脚本/etc/rc.d/init.d目录下,然后用命令chkconfig –add filename将自动注册开机启动和关机关闭。实质就是在rc0.d-rc6.d目录下生成一些文件连接,这些连接连接到/etc/rc.d /init.d目录下指定文件的shell脚本。
  2. 手工创建服务
    在/etc/rc.d/init.d目录下创建shell脚本,文件名auto_run。
    设置脚本的运行权限chmod +x auto_run。
    然后在rc0.d-rc6.d目录下分别创建文件连接。
    ln -s /etc/rc.d/init.d/auto_run /etc/rc.d/rc2.d/S99auto_run
    ln -s /etc/rc.d/init.d/auto_run /etc/rc.d/rc3.d/S99auto_run
    ln -s /etc/rc.d/init.d/auto_run /etc/rc.d/rc5.d/S99auto_run
    ln -s /etc/rc.d/init.d/auto_run /etc/rc.d/rc0.d/K01auto_run
    ln -s /etc/rc.d/init.d/auto_run /etc/rc.d/rc6.d/K01auto_run
    这样系统在启动的时候,就会运行auto_run 并加上start参数,等同于执行命令auto_run start。
    在系统关闭的时候,就会运行auto_run,并加上stop参数,等同于运行命令auto_run stop。
    创建连接的6条命令可以用命令chkconfig –add auto_run来完成,这样就简单多了,还不容易出错。
    下面就介绍一下chkconfig命令。
  3. chkconfig命令用法
    语法:
    chkconfig –list [name]
    chkconfig –add name
    chkconfig –del name
    chkconfig [–level levels] name <on|off|reset>
    chkconfig [–level levels] name
    说明:
    chkconfig提供一种简单的命令行工具来帮助管理员对/etc/rc[0-6].d目录层次下的众多的符号链接进行直接操作。
    此命令使用是由chkconfig命令在IRIX操作系统提供授权。不用在/etc/rc[0-6].d目录下直接维护配置信息,而是直接在/etc/rc[0-6]下管理链接文件。在运行级别的目录下的配置信息通知在将会初始启动哪些服务。
    Chkconfig有五个很明确的功能:为管理增加一个新的功能、删除一个功能、列出当前服务的启动信息、改变一个服务的启动信息和检测特殊服务的启动状态。
    当chkconfig没有参数运行时,它将显示其使用方法。如果只给出了一个服务名,它将检测这个服务名是否已经被配置到了当前运行级别中。如果已经配置,返回真,否则返回假。–level选项可以被用做查询多个运行级别而不仅仅是一个。
    如果在服务名之后指定了on,、off或reset,chkconfig将改变指定服务的启动信息。On或off标记服务被打开或停止,尤其是在运行级别被改变时。Reset标记重置服务的启动信息。
    默认情况下,on或off选项仅对2、3、4、5有影响,而 reset影响所有的运行级。–level选项可以被用于指定哪个运行级别接收影响。
    注意:对于每个服务,每一个运行级都有一个开始角本和一个结束角本。当开或关一个运行级时,init不会重新开始一个已经运行的服务,也不会重新停止一个未运行的服务。
    选项:
    –level levels
    指定一个运行级别适合的操作。范围为0-7。
    –add name
    增加一个新的服务。
    –del name
    删除一个服务
    –list name
    显示服务的情况
    RUNLEVEL FILES
    每个通过chkconfig管理的服务在其init.d目录下的角本中都需要两行或多行的注释。第一行告诉chkconfig在默认情况下什么运行级别的 服务可以开始,也就是所说的开始或结束的优先级别。如果服务没有默认的级别,建造将在所有运行级别中启动。a – 将用于代替运行级列表。第二个注释行包括对此服务的描述,可以通过反斜线符号扩展为多行。

    示例,auto_run的前三行如下:
    #!/bin/sh
    #chkconfig: 2345 80 90
    #description:auto_run
    第一行,告诉系统使用的shell,所以的shell脚本都是这样。
    第二行,chkconfig后面有三个参数2345,80和90告诉chkconfig程序,需要在rc2.d~rc5.d目录下,创建名字为 S80auto_run的文件连接,连接到/etc/rc.d/init.d目录下的的auto_run脚本。第一个字符是S,系统在启动的时候,运行脚 本auto_run,就会添加一个start参数,告诉脚本,现在是启动模式。同时在rc0.d和rc6.d目录下,创建名字为K90auto_run的 文件连接,第一个字符为K,个系统在关闭系统的时候,会运行auto_run,添加一个stop,告诉脚本,现在是关闭模式。
    注意上面的三行是中,地二,第三行是必须的,否则在运行chkconfig –add auto_run时,会报错。

  4. 常见的错误
    “服务不支持 chkconfig”:
    请注意检查脚本的前面,是否有完整的两行:
    #chkconfig: 2345 80 90
    #description:auto_run
    在脚本前面这两行是不能少的,否则不能chkconfig命令会报错误。
    如果运行chkconfig老是报错,如果脚本没有问题,我建议,直接在rc0.d~rc6.d下面创建到脚本的文件连接来解决,原理都是一样的。

来源于网络

理解gcc/g++的编译过程

gcc的编译流程分为了四个步骤,分别为(学过计算机的都知道,不细讲啦)预处理(Pre-Processing),编译(Compiling),汇编(Assembling)和链接(Linking)。

gcc的编译流程及状态流向可以归纳如下(网上转的图示,很生动)

gcc编译过程状态及选项图

gcc编译过程状态及选项图

从中得出几点:
(1) 通过控制gcc的选项,可以得出不同类型的中间文件;
(2) 编译流水为:源文件->汇编文件->目标文件(机器文件)->二进制文件。编译过程不能逆着来,也就是流水只能这样流。假如写了一个汇编文件,也可以流到二进制文件。
(3) gcc用到的处理程序分别是:cpp、ccl、as、ld,也就是说图中的gcc命令可由这些处理程序来进行编译的过程,其结果是一样的。这些命令的使用可参照网上的文章。

下面是一个简单的图示(转账的图片,来源不明)

gcc编译过程

gcc编译过程

不详细理解gcc的编译过程会导致两个问题:
(1) 对编译过程理解含糊,不能熟悉gcc/g++编译的参数和选项;
(2) Makefile不会写,或写不好。
很多人想一天就学好Makefile的熟悉,殊不知对gcc/g++的学习也是基础的一步。另外请看我的另一篇文章–《gcc/g++参数选项》。
先明确几点:
(1) gcc不是一个命令,而是一个工具集,即GNU Compiler Collection(应该没记错哈~);
(2) gcc的-o选项不只是用来重新指定最终的可执行文件名,而是可以指定编译过程中产生的中间文件名称。
接下来先熟悉本文涉及到gcc的几个参数:
-o 定义输出文件
-E 完成预处理/预编译停止
-c 只编译生成.o,不连接

下面就具体来查看一下gcc是如何完成四个步骤的。
首先,有以下hello.c源代码

#include
int main()
{
printf(“Hello World!\n”);
return 0;
}
(1)预处理阶段
在该阶段,编译器将上述代码中的stdio.h编译进来,并且用户可以使用gcc的选项”-E”进行查看,该选项的作用是让gcc在预处理结束后停止编译过程。
gcc -E hello.c -o hello.i
(2)编译阶段
接下来进行的是编译阶段,在这个阶段中,gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc把代码翻译成汇编语言。用户可以使用”-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
gcc -S hello.i -o hello.s
(3)汇编阶段
汇编阶段是把编译阶段生成的”.s”文件转成目标文件,读者在此可使用选项”-c”就可看到汇编代码已转化为”.o”的二进制目标代码了。如下所示:
gcc -c hello.s -o hello.o
(4)链接阶段
在成功编译之后,就进入了链接阶段。在这里涉及库的概念,包括静态库和动态库,请网上查找相关资料熟悉。
完成了链接之后,gcc就可以生成可执行文件,如下所示。
gcc hello.o -o hello

(5)运行该可执行文件
./hello
Hello World!