2011年6月3日星期五

测试

测试能不能发贴
从我的 Blackberry® 无线手持设备发送

2009年5月6日星期三

linux2.6内核移植之二-----linux2.6.29.2内核的编译

移植前的准备工作:

1.安装交叉编译器,2.6内核需要3.0以上的编译器。
2.设置PATH环境变量export PATH=/usr/local/arm/3.4.1(编译器版本)/bin:$PATH
3.解压内核
4.在内核根目录下的Makefile文件中指定要用到的编译器和架构(arch),
方法:将ARCH?=(SUBARCH) 改为,ARCH ?=arm CROSS_COMPILE ?=arm-linux-

5.修改默认内核配置文件(./.config)
cp arch/arm/configs/smdk2410_defconfig ./.config

修改源代码

1.在arch/arm/plat-s3c24xx/common-smdk.c中修改smdk_default_nand_part[],注意这个一定要跟bootloader的一致。在我的板子中修改如下:

static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name = "vivi",
.size = 0x00020000,//128K
.offset = 0,
},
[1] = {
.name = "param",
.offset = 0x00020000,
.size = 0x00010000,//64K
},
[2] = {
.name = "kernel",
.offset = 0x00030000,
.size = 0x001d0000,//1M+832K
},
[3] = {
.name = "root",
.offset = 0x00200000,
.size = 0x00100000,//4M
},
[4] = {
.name = "yaffs",
.offset = 0x00600000,
.size = 0x03ad0000,//58M
},
};

另外这个文件还要修改smdk_nand_info如下:
static struct s3c2410_platform_nand smdk_nand_info = {
.tacls = 0, //default is 20
.twrph0 = 30, //default is 60
.twrph1 = 0, //defualt is 20 changed by yangdk
.nr_sets = ARRAY_SIZE(smdk_nand_sets),
.sets = smdk_nand_sets,
};

2.修改nand Flash的校验方式,去掉ECC校验。
在drivers/mtd/nand/s3c2410.c 第669行
将chip->ecc.mode = NAND_ECC_SOFT;
改为 chip->ecc.mode = NAND_ECC_NONE;
注意:这个去掉ECC校验的问题,在内核中明确说明是不建议这样做的,因为这样就等于忽略了对NAND FLASH坏块的检测。而我一开始也是编译的时候就去掉了ECC校验的选项,原以为在编译选项中去掉就可以了,结果一直报这样的错:
end_request: I/O error, dev mtdblock2, sector 0
FAT: unable to read boot sector
VFS: Cannot open root device "mtdblock2" or unknown-block(31,2)
Please append a correct "root=" boot option; here are the available partitions:
1f00 192 mtdblock0 (driver?)
1f01 1856 mtdblock1 (driver?)
1f02 30720 mtdblock2 (driver?)
1f03 32768 mtdblock3 (driver?)
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,2)
郁闷了一个整天。后来发现配置中去掉的这个选项在代码中并没有完全去掉,只是去掉了硬件校验的方式,换成了软件校验。只有在代码中给改成NAND_ECC_NONE,才不会校验,但是这样是不提倡的。可是这有这样最后我的系统才起来,阿弥陀佛!


裁剪内核:make menuconfig

1.检查系统类型是不是s3c2410 选项:System Type,确定 S3C2410 DMA support被选中(此项不选在声卡驱动的加载是容易出错。)确定Support Thumb user binaries被选中。
2.检查模块加载支持(系统是否允许自动加载模块),这一项很重要
Loadable module support-> 下,确保Enable loadable module support 和Automatic kernel module loading被选中。
3.支持浮点运算,进入Floating point emulation -> 选中NWFPE math emulation被选中。
4.对可执行文件进行支持 Userspace binary formats -> 确保Kernel support for ELF binaries 和Kernel support for a.out and ECOFF binaries 被选中。
5.网络支持 Networking -> 选中 Networking support ,然后选择Networking options -> 下的 Unix domain sockets(支持unix网络)TCP/IP network
选中它下面的IP:Kernel level autoconfiguration 再选中它下面的IP:BOOTP support
6.内存技术设备支持 Device Drivers -> Memory Technology Devices (MTD) ->
选中 Memory Technology Device (MTD) support、MTD partitioning support(MTD分区支持)、Command line partition table  parsing(命令行分区支持)、Direct char device access to MTD devices(允许以字符设备方式访问内存技术设备)、Caching block device access to MTD devices
7.make zImage 进行编译,将内核复制到开发板上会发现不能正常运行,因
为还没有配置文件系统,继续执行make menuconfig 选择File systems-> 去除这一项下面的 Second extended fs support (扩展分区支持)和 Rom file system support (ROM文件系统支持,我们这里使用nand flash)两项的选择。
9.选择File systems -> Pseudo filesystems -> 下面的/dev file system support (OBSOLETE)、Auto matically mount at root、/proc file system support(支持内核镜像)、Virtual memory file system support (former shm fs) (虚拟内存文件系统)
10.设备的支持  选择Device Drivers -> Memory Technology Devices (MTD) -> ARM/ROM/Flash chip drivers -> 下面的 Detect flash chips by Common Flash Interface (CFI) probe (flash通用芯片接口)、Detect non-CFI AMD/JEDEC-compatible flash chips(非CFI接口芯片支持) 、Support for Intel/Sharp flash chips、Support for AMD/Fujitsu flash chips(富士通Flash芯片支持)、Support for RAM chips in bus mapping (支持RAM芯片总线映射)、Support for ROM chips in bus mapping(…ROM…)。
11.支持 2410/2440 Nand flash 设备
Device Drivers -> NAND Flash Device Drivers -> 选中NAND Device Support 和 NAND Flash support for S3C2410/S3C2410/S3C2440 SoC
12.支持块设备 Device Drivers -> Block devices -> 选择下面的 RAM disk support
选择Device Drivers -> Character devices -> 下的 Non-standard serial port support (支持非标准串口)、Legacy (BSD) PTY support(虚拟终端支持)、S3C2410 RTC Driver(支持实时时钟)
13.文件系统支持 File systems -> Miscellaneous filesystems -> 选中Compressed ROM file system support (cramfs)(cramfs支持)
14.File systems -> Network File Systms -> 选中NFS file system support、Provide NFSv3 client support、Provide client support for the NFSv3 ACL protocol extension (NFS扩展)、Root file system on NFS
15.编译: make zImage 将生成的内核放到开发板上运行,会发现提示,找不到/dev文件系统,必须修改内核使它支持/dev 文件系统才可以进行网络引导。

linux的内核目录结构:

1.arch   硬件体系结构相关的核心代码(arm)下arch/arm
2.include  核心头文件,每一个体系结构就会有一个对应的目录
3.init  内核的核心启动代码
4.ipc 进程以及进程间通信相关代码
5.mm 内存管理部分的代码
6.drivers  驱动程序目录(每个设备,在其中都有文件)
7.modules  放置已经编译好的模块(可缷载模块)
8.fs linux  文件系统支持代码
9.kernel  主要核心代码(与处理器结构无关)
10.arch/架构名/kernel 主要核心代码(与处理器结构相关)
11.net  核心网络代码
12.lib  核心库代码
13.scripts 内核配置脚本 
14.Documentation 所有文档

添加对/dev文件系统的支持

此版本的linux内核虽然不支持devfs,但内核中仍保留其代码。

方法:
在fs/kconfig文件中找到
menu "Pseudo filesystems"

source "fs/proc/Kconfig"
source "fs/sysfs/Kconfig"

在此后添加如下代码:
config DEVFS_FS
bool "/dev file system support (OBSOLETE)"
depends on EXPERIMENTAL
help
This is support for devfs, a virtual file system (like /proc) which
provides the file system interface to device drivers, normally found
in /dev. Devfs does not depend on major and minor number
allocations. Device drivers register entries in /dev which then
appear automatically, which means that the system administrator does
not have to create character and block special device files in the
/dev directory using the mknod command (or MAKEDEV script) anymore.
This is work in progress. If you want to use this, you *must* read
the material in , especially
the file README there.
Note that devfs no longer manages /dev/pts! If you are using UNIX98
ptys, you will also need to mount the /dev/pts filesystem (devpts).
Note that devfs has been obsoleted by udev,
.
It has been stripped down to a bare minimum and is only provided for
legacy installations that use its naming scheme which is
unfortunately different from the names normal Linux installations
use.
If unsure, say N.
config DEVFS_MOUNT
bool "Automatically mount at boot"
depends on DEVFS_FS
help
This option appears if you have CONFIG_DEVFS_FS enabled. Setting
this to 'Y' will make the kernel automatically mount devfs onto /dev
when the system is booted, before the init thread is started.
You can override this with the "devfs=nomount" boot option.
If unsure, say N.
config DEVFS_DEBUG
bool "Debug devfs"
depends on DEVFS_FS
help
If you say Y here, then the /dev file system code will generate
debugging messages. See the file
for more details.
If unsure, say N.

重新执行make menuconfig
在file system->Pseudo filesystems下已经可见devfs的相关选项

编译内核

make bzimage

在arch/arm/boot得到压缩后的内核镜像

linux2.6内核移植之一-----vivi的移植

开发板从上电到内核启动需要一个引导程序,在嵌入式Linux系统下称为Boot loader。vivi是韩国MIZI公司为其ARM9系列产品研发的Boot Loader。

   MTD(存储技术器件)是Linux内核采纳的一种设备子系统,它为底层的存储芯片提供了统一的设备接口。

  然而,vivi的Nand Flash分区(简称vivi分区)并不适合Linux2.6内核的需求,必须作出修改。而内核MTD分区是与vivi分区相对应的,随着vivi分区的改变也须重新定制。

Vivi分区和内核MTD分区的解析

  Vivi分区解析

  Vivi分区指的是给引导程序、内核映像、文件系统等在Nand Flash上分配空间及起始地址。在vivi的命令模式下输入命令:part show,可得vivi分区信息。未作修改的vivi分区信息如表1


从信息中可知,vivi把Nand Flash分为4个区,分别为vivi、param、kernel、root。
信息中的offset表示各分区在Nand Flash中的起始位置,
size及的后面128k、64k、768k、1M+256k表示各分区的大小,
flag为标识符。

未修改的vivi给放置内核映像文件zImage的kernel分区只有768k,但2.6内核的映像文件 一般都超过1M。另外,MIZI公司针对其自身产品所设计的vivi只对略大于2M的Nand Flash空间进行了分区;然而,开发板的Nand Flash容量为一般为32M或64M的,还有很大的空间可用。所以,重新定制vivi分区十分必要。


  内核MTD分区解析

  Linux2.6内核的MTD能够支持ROM、RAM、FLASH(NOR和NAND)等存储芯片。MTD同时可提供两类MTD驱动程序,一类是MTD设备地址空间的映射,提供直接访问设备的操作;另一类则为建立文件系统提供基础。

  在基于Linux2.6内核的S3C2410开发板上,Nand Flash上各段存储空间都被定义成MTD分区来管理的,各分区都可以通过Linux系统中的设备文件来访问。所以在内核中必须有MTD对引导程序、内核映像、文件系统在Nand Flash上的分区信息。

  vivi分区与内核MTD分区的关系

  从Nand Flash启动时,S3C2410硬件会自动把Nand Flash前4K代码拷贝芯片内部RAM空间,CPU其实是从内部RAM开始执行代码的,所以vivi必须放到Nand Flash顶端。vivi开始执行后将初始化硬件设备、建立内存空间映射表,为调用内核做好准备;然后把压缩的内核映像加载到SDRAM中;最后跳转到内核映像入口,启动内核。

  内核MTD分区必须与vivi分区相一致。因为,vivi分区中的地址是引导程序、内核映像及文件系统下载到Nand Flash的真正地址;而内核启动时,内核并不是去读vivi分区中的地址,而是去读内核MTD分区设定的地址;所以,如果内核MTD分区与vivi分区不相同,很可能导致不能正常启动内核及读取文件系统。

  vivi和内核MTD的重新分区

  vivi的重新分区

  根据开发板的Nand Flash大小及开发用途确定新的vivi分区,如表2。



打开vivi源代码下的arch/s3c2410/smdk.c文件,在函数:“mtd_partition_default_mtd_partitions[]={}”中可以看到vivi默认的Nand Flash分区信息。根据表2的新分区信息,在上述函数中以相同的格式修改原有分区信息即可完成vivi的重新分区。

内核MTD的重新分区

  在给内核MTD重新分区之前,有一点应该注意,2.6.16(含)以前内核与2.6.17(含)以后内核的MTD重新分区方法是不一样的,前者是需要增加新的分区信息,而后者源代码初始文件中已含分区信息,需要的是修改分区信息。

  Linux2.6.16(含)以前内核的MTD重新分区

  首先,在内核源代码arch/arm/mach-s3c2410/devs.c文件下增加头文件:“linux/mtd /partitions.h”、“asm/arch/nand.h”、“linux/mtd/nand.h”。注意,因为头文件之间也有先后关联的关系,所以要把这三句放到#include“devs.h”下面。若放在其他地方,编译可能报错。

  然后,同样在devs.c文件下,根据表2添加新的分区信息:

  Static struct mtd_partition partition_info[]={
  {name:“vivi”,
size:0x00020000,
offset:0,},{
name:“param”,
size:0x00010000,
offset:0x00020000,},{
name:“kernel”,
size:0x001d0000,
offset:0x00030000,},{
name:“root”,
size:0x00400000,
offset:0x00200000,
mask_flags:mtd_writeable,},{
name:“program”,
size:0x03a00000,
offset:0x00600000,}
  };
  Struct s3c2410_nand_set nandset={nr_partitions:5,partitions:partition_info,};
struct s3c2410_platform_nand superlpplatform={tacls:0,twrph0:30,twrph1:0, sets:& nandset, nr_sets:1,};

  最后,在devs.c文件的s3c_device_nand函数中增加:“.dev={.platform_data=&superlpplatform}”;
在arch/arm/mach-s3c2410/mach-smdk2410.c文件的“static struct platform_device*smdk2410_devices[]_initdata={}”
中增加“&s3c_device_nand”。目的是使内核在启动时初始化nand flash信息。

  Linux2.6.17(含)以后内核的MTD重新分区

  Linux2.6.17(含)以后内核的MTD分区要比Linux2.6.16(含)以前内核简单很多,因为源代码的初始文件中已含分区信息,只要修改一下就行了。

  在源代码arch/arm/mach-s3c2410/common-smdk.c文件下的函数“mtd_partition smdk_default_nand_part[]={}”中,可以看到默认的MTD分区。根据表1,以相同的格式修改原分区信息即可完成MTD的重新分区。

编译器的选择

vivi需要用2.9版本的交叉编译工具链,linux2.6.29.2需要2.3上以版本的编译器,我用3.4.1版本的成功编译了。


  结语

  基于Linux2.6内核的Linux与ARM9 S3C2410的结合将会在嵌入式领域得到广泛的应用。vivi分区与内核MTD分区是两者进行联合开发的基础。

 参考文献:

  1、 嵌入式Linux系统开发技术详解—基于ARM,孙纪坤、张小全,人民邮电出版社,2006

  2、 ARM9嵌入式技术及Linux高级实践教程,陈赜,北京航空航天大学出版社,2005

  3、 中国Linux公社论坛,《Linux2.6.10以后版本对S3C2410的支持》

  4、 Mizi公司网站http://www.mizi.com/developer/s3c2410

  5、 Linux MTD网站http://www.linux-mtd.infradead.org

原文地址:http://www.eepw.com.cn/article/81624.htm

2009年5月3日星期日

[转]rsa 加密算法

不同于对称加密算法中加密和解密使用同样的密钥,公钥算法分为加密密钥K1和解密密钥K2两部分,而且从K1很难计算推导出K2。这样就可以保密K2而公布K1,从而大大简化了密钥管理。习惯上K1称为公钥,K2称为私钥。

加密使用公钥,解密使用私钥。

ENC(P,K1)= C

DEC(C,K2)= P

RSA加密算法的步骤是这样的:

(1) 找两个随机大素数p和q;

(2) 计算模n=pq和Euler函数φ(n) =(p-1)(q-1);

(3) 选取数e后用扩展Euclid算法求数d满足ed≡1 mod φ(n);

(4) 保密私钥K2=(d, n),发布公钥K1=(e, n);

(5) 加密明文p时,计算密文c = p^e mod n;

(6) 解密c时,计算p = c^d mod n。

RSA算法也可以用来签名:

(7) 对消息m,其签名s = m^d mod n;

(8) 验证(m,s)即判断m =? s^e mod n。

下面介绍OpenSSL中RSA算法的函数接口。

RSA密钥产生

RSA密钥产生函数RSA_generate_key(),需要指定模长比特数bits和公钥指数e。另外两个参数为NULL即可。

RSA * RSA_generate_key(int bits, unsigned long e, void (*callback) (int,int,void *),void *cb_arg);

目前对于长达663比特的RSA模数已经有成功分解的先例,因此当前典型的应用场合使用1024比特模长的RSA算法,此时一个分组是128字节。

如果从文件中读取密钥,可使用函数PEM_read_bio_PrivateKey()/ PEM_read_bio_PUBKEY(),其中EVP_PKEY 中包含一个RSA结构,可以引用。

EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u);

RSA加密和解密

RSA加密函数RSA_public_encrypt()使用公钥部分,解密函数RSA_private_decrypt()使用私钥。填充方式常用的有两种RSA_PKCS1_PADDING和RSA_PKCS1_OAEP_PADDING。出错时返回-1。输入必须比RSA钥模长短至少11个字节(在RSA_PKCS1_PADDING时?)。输出长度等于RSA钥的模长。

int RSA_public_encrypt(int flen, const unsigned char *from,unsigned char *to, RSA *rsa,int padding);

int RSA_private_decrypt(int flen, const unsigned char *from,unsigned char *to, RSA *rsa,int padding);

RSA签名和验证

签名使用私钥,验证使用公钥。RSA签名操作是把被签署消息的散列值编码后用私钥加密,因此函数中参数type用来指示散列函数的类型,一般是NID_md5或NID_sha1。正确情况下返回0。

int RSA_sign(int type, const unsigned char *m, unsigned int m_length, unsigned char *sigret, unsigned int *siglen, RSA *rsa);

int RSA_verify(int type, const unsigned char *m, unsigned int m_length, unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
-------------------------rsa 签名和验证例子


// demo how to sign a piece of data
// by Linden 23:49 2003-4-23

#include
#include
#include

main()
{
#define RSA_KEY_FILE "rsakey.txt"
// > openssl genrsa -out rsakey.txt 1024
RSA* key;
char msg[]="i, i have no data to sign";
unsigned char md[16]; // md5's len
unsigned char sig[128]; // 1024/8
int siglen = sizeof(sig);

int r;

//SSL_library_init();
//SSL_load_error_strings();
//OpenSSL_add_all_algorithms();

key = RSA_new();

#if 1 // gen
puts("genrsa...(maybe a few seconds)");
key = RSA_generate_key(1024, 65537, NULL, NULL);
puts("ok");
#else // read in
{
#if 0 // 曾经ok过吗?忘了
FILE *fp = fopen(RSA_KEY_FILE, "r");
key = PEM_read_RSAPrivateKey(fp, &key, NULL, NULL);
#else
int i;
EVP_PKEY* k;
BIO *in = BIO_new(BIO_s_file_internal());
i = BIO_read_filename(in, RSA_KEY_FILE);
if (i<=0) puts("read key file err"); else k = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); key = RSAPrivateKey_dup(k->pkey.rsa);
EVP_PKEY_free(k);
BIO_free(in);
#endif
}
#endif

#if 0 // display. there's err
{
//BIO *o = BIO_new_fd(fileno(stdout), BIO_NOCLOSE);
BIO *o = BIO_new(BIO_s_file());
RSA_print(o, key, 0);
BIO_free(o);
}
#endif

//int RSA_sign(int type, const unsigned char *m, unsigned int m_length,
// unsigned char *sigret, unsigned int *siglen, RSA *rsa);
MD5(msg, strlen(msg), md);
r = RSA_sign(NID_md5, md, sizeof(md), sig, &siglen, key);
if (!r)
puts("error in sign");

#if 0
sig[0]++; // 假想的错误
#endif

//int RSA_verify(int type, const unsigned char *m, unsigned int m_length,
// unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
r = RSA_verify(NID_md5, md, sizeof(md), sig, siglen, key);
if (!r)
puts("error in verify");
puts("is there errs? no? ok!");

RSA_free(key);

return 0;
}
-----------------------rsa 加解密例子



// demo how to enc a piece of data using RSA
// by Linden 0:23 2003-11-15

#include
#include
#include
#include

#pragma comment(lib,"libeay32.lib")
#pragma comment(lib,"ssleay32.lib")

#if 0
main()
{
#define RSA_KEY_FILE "rsakey.txt"
// > openssl genrsa -out rsakey.txt 1024
RSA* key;
char msg[]="i, i have no data to enc";
char msg2[256];
char msg3[256];
int r;

//SSL_library_init();
//SSL_load_error_strings();
//OpenSSL_add_all_algorithms();

//key = RSA_new();

#if 1 // gen
puts("genrsa...(maybe a few seconds)");
key = RSA_generate_key(1024, 65537, NULL, NULL);
puts("ok");
#else // read in
{
#if 0 // 曾经ok过吗?忘了
FILE *fp = fopen(RSA_KEY_FILE, "r");
key = PEM_read_RSAPrivateKey(fp, &key, NULL, NULL);
#else
int i;
EVP_PKEY* k;
BIO *in = BIO_new(BIO_s_file_internal());
i = BIO_read_filename(in, RSA_KEY_FILE);
if (i<=0) puts("read key file err"); else k = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); key = RSAPrivateKey_dup(k->pkey.rsa);
EVP_PKEY_free(k);
BIO_free(in);
#endif
}
#endif

#if 0 // display. there's err
{
//BIO *o = BIO_new_fd(fileno(stdout), BIO_NOCLOSE);
BIO *o = BIO_new(BIO_s_file());
RSA_print(o, key, 0);
BIO_free(o);
}
#endif

r = RSA_public_encrypt(strlen(msg), msg, msg2,
key, RSA_PKCS1_PADDING); // or RSA_PKCS1_OAEP_PADDING
if (!r)
puts("error in enc");

#if 0
sig[0]++; // 假想的错误
#endif

r = RSA_private_decrypt(r, msg2, msg3,
key, RSA_PKCS1_PADDING);
if (!r)
puts("error in dec");

if (memcmp(msg, msg3, strlen(msg)))
puts("ERROR! text2 != text");
else
{
msg3[strlen(msg)] = 0;
printf("解密后的明文:%s", msg3);
}

puts("is there errs? no? ok!");

RSA_free(key);

return 0;
}
#endif

原文见:http://hi.baidu.com/dongfangjack/blog/item/5027acac399ae4014a36d637.html

[转]OpenSSL For Linux 命令详解

 加密算法:

  对称加密算法:

  DES、IDEA、RC2、RC4、AES、Skipjack ......

  非对称加密算法:

  RSA、DSA、DiffieHellman、PKCS、PGP ......

  单向的HASH算法属于报文摘要算法,虽然有些也出自OpenSSL库。

  命令操作:

  1、生成普通私钥:

[weigw@TEST src]$ openssl genrsa -out privatekey.key 1024

Generating RSA private key, 1024 bit long modulus ....++++++ .......++++++ e is 65537 (0x10001)

  2、生成带加密口令的密钥:

[weigw@TEST src]$ openssl genrsa -des3 -out privatekey.key 1024

Generating RSA private key, 1024 bit long modulus ............++++++ .....................++++++ e is 65537 (0x10001) Enter pass phrase for privatekey.key: Verifying - Enter pass phrase for privatekey.key:

  在生成带加密口令的密钥时需要自己去输入密码。对于为密钥加密现在提供了一下几种算法:

-des encrypt the generated key with DES in cbc mode

-des3 encrypt the generated key with DES in ede cbc mode (168 bit key)

-aes128, -aes192, -aes256 encrypt PEM output with cbc aes

  去除密钥的口令:

[weigw@TEST src]$ openssl rsa -in privatekey.key -out

privatekey.key Enter pass phrase for privatekey.key: writing RSA key

  通过生成的私钥去生成证书:

[weigw@TEST src]$ openssl req -new -x509 -key privatekey.key -out cacert.crt -days 1095

You are about to be asked to enter information that will be incorporated into your certificate request.

What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank.

-----

Country Name (2 letter code) [GB]:CN

State or Province Name (full name) [Berkshire]:beijing

Locality Name (eg, city) [Newbury]:beijing

Organization Name (eg, company) [My Company Ltd]:wondersoft

Organizational Unit Name (eg, section) []:develop

Common Name (eg, your name or your server's hostname) []:WeiGW

Email Address []:weigongwan@sina.com
  在生成证书的时候需要按照提示输入一些个人信息。

  通过私钥生成公钥:

[weigw@TEST src]$ openssl rsa -in privatekey.key -pubout -out pubkey.key writing RSA key

  格式转换:(证书、私钥、公钥)(PEM <----->DER)

[weigw@TEST src]$ openssl x509 -in cacert.crt -inform PEM -out cacert.der -outform DER

[weigw@TEST src]$

[weigw@TEST src]$ openssl rsa -in privatekey.key -inform PEM -out privatekey.der -outform DER

writing RSA key

[weigw@TEST src]$ openssl rsa -pubin -in pubkey.key -inform PEM -pubout -out pubkey.der -outform DER

writing RSA key

  从DER格式转换成PEM格式一样,就是把inform的格式改成DERoutform的格式改成PEM即可。


  下面是一个服务器和客户端认证的证书、私钥生成方法:(server.crt、client.crt、ca.crt)

  第一步: 生成私钥



[weigw@TEST bin]$ openssl genrsa -out server.key 1024


Generating RSA private key, 1024 bit long modulus .++++++ ..
.........++++++ e is 65537 (0x10001)


[weigw@TEST bin]$ openssl genrsa -out client.key 1024


Generating RSA private key, 1024 bit long modulus ...++++++ ......
..........++++++ e is 65537 (0x10001)


[weigw@TEST bin]$ openssl genrsa -out ca.key 1024

Generating RSA private key, 1024 bit long modulus .......
..++++++ .........++++++ e is 65537 (0x10001)


[weigw@TEST bin]$



  第三步: 申请证书(为请求文件签名)

[weigw@TEST bin]$ openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key

[weigw@TEST bin]$ openssl ca -in client.csr -out client.crt -cert ca.crt -keyfile ca.key

  如果在这步出现错误信息:

[weigw@TEST bin]$ openssl ca -in client.csr -out client.crt -cert ca.crt -keyfile ca.key

Using configuration from /usr/share/ssl/openssl.cnf I am unable to access the ./demoCA/newcerts directory ./demoCA/newcerts: No such file or directory

[weigw@TEST bin]$

  自己手动创建一个CA目录结构:
  [weigw@TEST bin]$ mkdir ./demoCA
  [weigw@TEST bin]$ mkdir demoCA/newcerts
  创建个空文件:
  [weigw@TEST bin]$ vi demoCA/index.txt
  向文件中写入01:
  [weigw@TEST bin]$ vi demoCA/serial

  合并证书文件(crt)和私钥文件(key):

[weigw@TEST bin]$ cat client.crt client.key > client.pem [weigw@TEST bin]$ cat server.crt server.key > server.pem

  合并成pfx证书:

[weigw@TEST bin]$ openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12

Enter Export Password:

Verifying - Enter Export Password:

[weigw@TEST bin]$openssl pkcs12 -export -clcerts -in server.crt -inkey server.key -out server.p12
Enter Export Password:
Verifying - Enter Export Password:

  文本化证书:

[weigw@TEST bin]$ openssl pkcs12 -in client.p12 -out client.txt Enter Import Password:

MAC verified OK

Enter PEM pass phrase: Verifying - Enter PEM pass phrase:

[weigw@TEST bin]$openssl pkcs12 -in server.p12 -out server.txt

Enter Import Password:

MAC verified OK

Enter PEM pass phrase: Verifying - Enter PEM pass phrase:

  屏幕模式显式:(证书、私钥、公钥)

[weigw@TEST bin]$ openssl x509 -in client.crt -noout -text -modulus

[weigw@TEST bin]$ openssl rsa -in server.key -noout -text -modulus

[weigw@TEST bin]$ openssl rsa -in server.pub -noout -text -modulus

  得到DH:

[weigw@TEST bin]$ openssl dhparam -out dh1024.pem 1024

原文见:http://www.cnblogs.com/kangtr/archive/2008/05/17/1201205.html

2009年4月28日星期二

[转]Linux C 下使用openssl 进行SHA1加密

/*
Code snippet to calculate SHA1sum using openssl libs.
Copyright 2005 Junichi Uekawa, given to public domain.

$ gcc openssltest.c -lssl
$ ./a.out < ./a.out
eae8189278303caaa78f2d89e6a6ebeb7d37b554
$ sha1sum ./a.out
eae8189278303caaa78f2d89e6a6ebeb7d37b554 ./a.out
*/

#include
#include

main ()
{
SHA_CTX s;
int i, size;
char c[512];
unsigned char hash[20];

SHA1_Init(&s);
while ((size=read (0, c, 512)) > 0)
SHA1_Update(&s, c, size);
SHA1_Final(hash, &s);

for (i=0; i < 20; i++)
printf ("%.2x", (int)hash[i]);
printf ("\n");
}

[转]Linux网络编程一步一步学-利用OpenSSL提供的SSL操作函数进行加密通讯原始例子

首先,大家知道SSL这一目前“事实上的Internet加密标准”吧?一般的网站是没有用到SSL的,所以如果你用TCPDUMP就可以很容易地看到别人上网的帐号、密码之类的,当然,现在有些已经改用安全通讯方式进行验证了,比如 google的邮件服务gmail,而象银行、证券等行业,从一开始就要求用加密通讯,你在哪个银行网站上输入帐号和密码后点击提交不是通过加密方式提交的呢?事实上,SSL也正是在银行这些行业的需求下才产生的。
现在大家经常上网会上到一些https://开头的网站,那就是把SSL标准应用到HTTP上从而变成了HTTPS。另外大家可能都不用telnet这个明文传输工具来进行远程登录了,都改用ssh了,ssh正是SSL的一个实现,用来进行远程加密通讯的。

其次,要在我们现有的TCP程序上加上SSL,你得安装开发包libssl-dev,这个包的描述是这样的:
Package: libssl-dev
Priority: optional
Section: libdevel
Installed-Size: 5552
Maintainer: Debian OpenSSL Team

也就是说这个libssl-dev包是库函数、头文件以及相关编程说明文档的集合。

安装完成之后在/usr/share/doc/libssl-dev/demos目录下有一些编程示例。你可以参照里面的文档自己来写加密通讯程序。

/************关于本文档********************************************
*filename: Linux网络编程一步一步学-利用OpenSSL提供的SSL操作函数进行加密通讯原始例子
*purpose: 说明了如果在Linux下利用OpenSSL库函数进行SSL加密通讯程序开发
*tidied by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-01-28 19:00
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Thanks to: Google.com
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/

比如/usr/share/doc/libssl-dev/demos/bio目录下提供的一个服务器端例子,代码如下:
/* NOCW */
/* demos/bio/saccept.c */

/* A minimal program to server an SSL connection.
* It uses blocking.
* saccept host:port
* host is the interface IP to use. If any interface, use *:port
* The default it *:4433
*
* cc -I../../include saccept.c -L../.. -lssl -lcrypto
*/

#include
#include
#include
#include

#define CERT_FILE "server.pem"

BIO *in=NULL;

void close_up()
{
if (in != NULL)
BIO_free(in);
}

int main(argc,argv)
int argc;
char *argv[];
{
char *port=NULL;
BIO *ssl_bio,*tmp;
SSL_CTX *ctx;
SSL *ssl;
char buf[512];
int ret=1,i;

if (argc <= 1)
port="*:4433";
else
port=argv[1];

signal(SIGINT,close_up);

SSL_load_error_strings();

#ifdef WATT32
dbug_init();
sock_init();
#endif

/* Add ciphers and message digests */
OpenSSL_add_ssl_algorithms();

ctx=SSL_CTX_new(SSLv23_server_method());
if (!SSL_CTX_use_certificate_file(ctx,CERT_FILE,SSL_FILETYPE_PEM))
goto err;
if (!SSL_CTX_use_PrivateKey_file(ctx,CERT_FILE,SSL_FILETYPE_PEM))
goto err;
if (!SSL_CTX_check_private_key(ctx))
goto err;

/* Setup server side SSL bio */
ssl=SSL_new(ctx);
ssl_bio=BIO_new_ssl(ctx,0);

if ((in=BIO_new_accept(port)) == NULL) goto err;

/* This means that when a new connection is acceptede on 'in',
* The ssl_bio will be 'dupilcated' and have the new socket
* BIO push into it. Basically it means the SSL BIO will be
* automatically setup */
BIO_set_accept_bios(in,ssl_bio);

again:
/* The first call will setup the accept socket, and the second
* will get a socket. In this loop, the first actual accept
* will occur in the BIO_read() function. */

if (BIO_do_accept(in) <= 0) goto err;

for (;;)
{
i=BIO_read(in,buf,512);
if (i == 0)
{
/* If we have finished, remove the underlying
* BIO stack so the next time we call any function
* for this BIO, it will attempt to do an
* accept */
printf("Done\n");
tmp=BIO_pop(in);
BIO_free_all(tmp);
goto again;
}
if (i < 0) goto err;
fwrite(buf,1,i,stdout);
fflush(stdout);
}

ret=0;
err:
if (ret)
{
ERR_print_errors_fp(stderr);
}
if (in != NULL) BIO_free(in);
exit(ret);
return(!ret);
}

对应的一个客户端例子代码如下:
/* NOCW */
/* demos/bio/sconnect.c */

/* A minimal program to do SSL to a passed host and port.
* It is actually using non-blocking IO but in a very simple manner
* sconnect host:port - it does a 'GET / HTTP/1.0'
*
* cc -I../../include sconnect.c -L../.. -lssl -lcrypto
*/
#include
#include
#include
#include
#include

extern int errno;

int main(argc,argv)
int argc;
char *argv[];
{
char *host;
BIO *out;
char buf[1024*10],*p;
SSL_CTX *ssl_ctx=NULL;
SSL *ssl;
BIO *ssl_bio;
int i,len,off,ret=1;

if (argc <= 1)
host="localhost:4433";
else
host=argv[1];

#ifdef WATT32
dbug_init();
sock_init();
#endif

/* Lets get nice error messages */
SSL_load_error_strings();

/* Setup all the global SSL stuff */
OpenSSL_add_ssl_algorithms();
ssl_ctx=SSL_CTX_new(SSLv23_client_method());

/* Lets make a SSL structure */
ssl=SSL_new(ssl_ctx);
SSL_set_connect_state(ssl);

/* Use it inside an SSL BIO */
ssl_bio=BIO_new(BIO_f_ssl());
BIO_set_ssl(ssl_bio,ssl,BIO_CLOSE);

/* Lets use a connect BIO under the SSL BIO */
out=BIO_new(BIO_s_connect());
BIO_set_conn_hostname(out,host);
BIO_set_nbio(out,1);
out=BIO_push(ssl_bio,out);

p="GET / HTTP/1.0\r\n\r\n";
len=strlen(p);

off=0;
for (;;)
{
i=BIO_write(out,&(p[off]),len);
if (i <= 0)
{
if (BIO_should_retry(out))
{
fprintf(stderr,"write DELAY\n");
sleep(1);
continue;
}
else
{
goto err;
}
}
off+=i;
len-=i;
if (len <= 0) break;
}

for (;;)
{
i=BIO_read(out,buf,sizeof(buf));
if (i == 0) break;
if (i < 0)
{
if (BIO_should_retry(out))
{
fprintf(stderr,"read DELAY\n");
sleep(1);
continue;
}
goto err;
}
fwrite(buf,1,i,stdout);
}

ret=1;

if (0)
{
err:
if (ERR_peek_error() == 0) /* system call error */
{
fprintf(stderr,"errno=%d ",errno);
perror("error");
}
else
ERR_print_errors_fp(stderr);
}
BIO_free_all(out);
if (ssl_ctx != NULL) SSL_CTX_free(ssl_ctx);
exit(!ret);
return(ret);
}

编译程序里象一般的gcc命令一样,但需要链接ssl库,比如
gcc -Wall saccept.c -o sslserver -lssl
gcc -Wall sconnect.c -o sslclient -l ssl