代码改变世界

使用 Openssl 验证自签名证书

2011-06-15 14:11  乱世文章  阅读(1258)  评论(0编辑  收藏  举报

 

iOS的 security framework 框架前面已经介绍。这个框架提供有限的功能,使用它能做到的,比你想象的要少。笔者一直想找一个 iOS 下比较好的功能全面的安全算法库,结果却一无所获。不知道谁能介绍下这方面。

最终还是只有求助于闻名已久的 Openssl library。

Openssl 确实十分强大,然而其糟糕文档仍让人难以满意。当然,网络上使用Openssl 的例子非常多,不过能写这个的似乎都是高手,必然跟菜鸟划清界限——如果你是一个菜鸟,高手是不会跟你解释每行代码分别都是什么意思。坚信求人不如求己,钻研了许久,终于写出了点能够运行的 Code。

主要参考的来源:一是 Openssl 库中的源代码,一是这本书《Openssl编程》(赵春平 著)——说它是书可能有些勉强,因为没有得以出版(不知道出版社的编辑们看到这本书没?)。但它确实是本 Openssl 方面比较全面的介绍(难得的中文参考书),如果你想对 Openssl 有所了解,不妨把它找来看看(openssl.cn 论坛上)。

一、编译 iOS Openssl 静态库

请参考《在你的 iOS App 中使用 OpenSSL 库》。

二、在 Xcode 项目中进行设置

同上

三、使用 Openssl 验证

直接上代码:

#import <OpenSsl/x509.h>

#import <Openssl/x509v3.h>

void loadCert( NSString *, X509 *);

void printX509( X509 *);

void verity( X509 *, NSString *);

int main( int argc, char *argv[]) {

    NSAutoreleasePool * pool = [[ NSAutoreleasePool alloc ] init ];

NSString *file= @"/Users/username/Desktop/client.cer" ;

// 新建一个 x509 结构

X509 *x= X509_new ();

loadCert (file,x);

printX509 (x);

// 开始验证

verity (x,file);

// 释放结构体

X509_free (x);

[pool release ];

    return 0 ;

}

// 加载证书到 X509 结构

void loadCert( NSString * string, X509 * x){

NSData * certData;

unsigned char buf[ 4096 ],*p;

int len;

assert (string!= nil );

// 读取证书文件

certData=[ NSData dataWithContentsOfFile :string];

assert (certData!= nil );

len=certData. length ;

// NSData-->uchar*

[certData getBytes :( void *)buf length :len];

// p-->buf[0]

p=buf;

 

// buf 中的数据进行解码,并返回一个 X509 结构

d2i_X509 (&x,( const unsigned char **)&p,len);

}

// 打印 X509 结构

void printX509( X509 * x){

int ret;

BIO *b;

// 初始化一个文件 BIO

b= BIO_new ( BIO_s_file ());

// 把标准输出 stdout 指向这个文件 BIO

BIO_set_fp (b, stdout , BIO_NOCLOSE );

// X509 结构打印输出到文件 BIO

ret= X509_print (b,x);

// 释放流

BIO_free (b);

}

// 验证自签名证书

void verity( X509 * x1, NSString * string){

int i= 0 ;

X509_LOOKUP *lookup= NULL ;

// 证书 store 结构体

X509_STORE *cert_ctx;

// 证书 store 相关的上下文

X509_STORE_CTX *csc;

// 构造 CA X509_STORE 结构体,包含所有有效证书链和废止证书链,用于校验

cert_ctx= X509_STORE_new ();

// store 中加入一个搜索,可以查找单个的文件

lookup= X509_STORE_add_lookup (cert_ctx, X509_LOOKUP_file ());

assert (lookup!= NULL );

// 通过 lookup 加载 client.cer 内的证书(自签名)

i= X509_LOOKUP_load_file (lookup,[string UTF8String ], X509_FILETYPE_ASN1 );

assert (i!= 0 );

// flags 赋值给 ctx 里面的 flags, 表明了验证证书时需要验证哪些项

// flags 可以是:

// X509_V_FLAG_IGNORE_CRITICAL

// X509_V_FLAG_CB_ISSUER_CHECK

// X509_V_FLAG_CRL_CHECK

// X509_V_FLAG_CRL_CHECK│X509_V_FLAG_CRL_CHECK_ALL

X509_STORE_set_flags (cert_ctx, X509_V_FLAG_CRL_CHECK_ALL );

csc = X509_STORE_CTX_new ();

if (! X509_STORE_CTX_init (csc,cert_ctx ,x1, NULL ))

{

NSLog ( @"Can NOT ctx init" );

return ;

}

// 开始校验

i= 0 ;

i= X509_verify_cert (csc);

X509_STORE_CTX_free (csc);

if (i)

NSLog ( @"cert OK" );

else

{

NSLog ( @"cert error" );

}

}

 

先搞个有效证书,client.cer,放在你的桌面上。运行程序,控制台打印:

cert OK

如果证书失效了(比如把证书有效期改为无效),控制台则打印:

cert error