注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

勇敢的劳尤条

 
 
 

日志

 
 

openssl之RSA编程(1)(环境问题与测试代码)  

2014-01-02 16:31:12|  分类: 软件安全以及传输 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
继上一篇”RSA——公钥与私钥(数字签名 与 加密)“,现在进入RSA编程测试,也为编程环境进行测试。
参考代码来自【参考资料】。

生成一个密钥:

openssl genrsa -out test.key 1024

openssl可以将这个文件中的公钥提取出来:

openssl rsa -in test.key -pubout -out test_pub.key

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<openssl/rsa.h>
#include<openssl/pem.h>
#include<openssl/err.h>
#define OPENSSLKEY "test.key"
#define PUBLICKEY "test_pub.key"
#define BUFFSIZE 1024
char* my_encrypt(char *str,char *path_key);//加密
char* my_decrypt(char *str,char *path_key);//解密
int main(void)
{
    char *source="i like dancing !";
    char *ptr_en,*ptr_de;
    printf("source is    :%s\n",source);
    ptr_en=my_encrypt(source,PUBLICKEY);
    printf("after encrypt:%s\n",ptr_en);
    ptr_de=my_decrypt(ptr_en,OPENSSLKEY);
    printf("after decrypt:%s\n",ptr_de);
    if(ptr_en!=NULL){
        free(ptr_en);
    }   
    if(ptr_de!=NULL){
        free(ptr_de);
    }   
    return 0;
}
char *my_encrypt(char *str,char *path_key)
{
    char *p_en;
    RSA *p_rsa;
    FILE *file;
    int flen,rsa_len;
    if((file=fopen(path_key,"r"))==NULL){
        perror("open key file error");
        return NULL;    
    }   
    if((p_rsa=PEM_read_RSA_PUBKEY(file,NULL,NULL,NULL))==NULL){
    //if((p_rsa=PEM_read_RSAPublicKey(file,NULL,NULL,NULL))==NULL){   换成这句死活通不过,无论是否将公钥分离源文件
        ERR_print_errors_fp(stdout);
        return NULL;
    }   
    flen=strlen(str);
    rsa_len=RSA_size(p_rsa);
    p_en=( char *)malloc(rsa_len+1);
    memset(p_en,0,rsa_len+1);
    if(RSA_public_encrypt(rsa_len,(unsigned char *)str,(unsigned char*)p_en,p_rsa,RSA_NO_PADDING)<0){
        return NULL;
    }
    RSA_free(p_rsa);
    fclose(file);
    return p_en;
}
char *my_decrypt(char *str,char *path_key)
{
    char *p_de;
    RSA *p_rsa;
    FILE *file;
    int rsa_len;
    if((file=fopen(path_key,"r"))==NULL){
        perror("open key file error");
        return NULL;
    }
    if((p_rsa=PEM_read_RSAPrivateKey(file,NULL,NULL,NULL))==NULL){
        ERR_print_errors_fp(stdout);
        return NULL;
    }
    rsa_len=RSA_size(p_rsa);
    p_de=( char *)malloc(rsa_len+1);
    memset(p_de,0,rsa_len+1);
    if(RSA_private_decrypt(rsa_len,(unsigned char *)str,(unsigned char*)p_de,p_rsa,RSA_NO_PADDING)<0){
        return NULL;
    }
    RSA_free(p_rsa);
    fclose(file);
    return p_de;
}

上面说PEM_read_RSAPublicKey无法完成加密,其实是因为公钥的编码方式。下面是我去openssl官网找到的注解。链接如下。http://www.openssl.org/docs/crypto/pem.html#
使用这个命令,可以生成RSAPublicKey可以读取的公钥文件下面有链接
openssl rsa -in test.key -RSAPublicKey_out -out test_pub1.key 

The RSAPublicKey functions process an RSA public key using an RSA structure. The public key is encoded using a PKCS#1 RSAPublicKey structure.

The RSA_PUBKEY functions also process an RSA public key using an RSA structure. However the public key is encoded using a SubjectPublicKeyInfo structure and an error occurs if the public key is not RSA.

基于上述代码,编写了一个makefile如下。

output = rsa
objs = rsa.o
CC = g++
$(output):$(objs)
$(CC) -o $(output) $(objs) -L /usr/local/openssl/lib -lcrypto -ldl
$(objs):$(output).c
$(CC) -c $(output).c -I /usr/local/openssl/include -Wall
.PHONY:clean
clean:
rm -f $(output) *.o

简单讲解下:/usr/local/openssl是我安装openssl的目录。ubuntu12.04 源码编译安装openssl1.0.1e
但是其中的-ldl是什么呢?
我之前没有-ldl的时候,出现了下面的错误,很明显libcrypto库要求dl库的支持,所以我必须加上-ldl(-l library),而dl库在系统默认的路径里,所以不必指定-L。

/usr/local/openssl/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_globallookup':
dso_dlfcn.c:(.text+0x21): undefined reference to `dlopen'
dso_dlfcn.c:(.text+0x34): undefined reference to `dlsym'
dso_dlfcn.c:(.text+0x3f): undefined reference to `dlclose'
/usr/local/openssl/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_bind_func':
dso_dlfcn.c:(.text+0x354): undefined reference to `dlsym'
dso_dlfcn.c:(.text+0x3fb): undefined reference to `dlerror'
/usr/local/openssl/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_bind_var':
dso_dlfcn.c:(.text+0x474): undefined reference to `dlsym'
dso_dlfcn.c:(.text+0x52e): undefined reference to `dlerror'
/usr/local/openssl/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_load':
dso_dlfcn.c:(.text+0x5a4): undefined reference to `dlopen'
dso_dlfcn.c:(.text+0x612): undefined reference to `dlclose'
dso_dlfcn.c:(.text+0x640): undefined reference to `dlerror'
/usr/local/openssl/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_pathbyaddr':
dso_dlfcn.c:(.text+0x6be): undefined reference to `dladdr'
dso_dlfcn.c:(.text+0x721): undefined reference to `dlerror'
/usr/local/openssl/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_unload':
dso_dlfcn.c:(.text+0x77a): undefined reference to `dlclose'

至此,编译成功之后运行程序,如下。
openssl之RSA编程第一步 - yuanshuilee - 勇敢的劳尤条


C::B
之后,将代码放到CodeBlocks里面运行,必须如下链接才能运行。其中的mysql和pthread是我的其他工程用到的,这里并不是必需的。至此,编译完成。
openssl之RSA编程第一步 - yuanshuilee - 勇敢的劳尤条 
openssl之RSA编程第一步 - yuanshuilee - 勇敢的劳尤条
 

最后的ps:
        我发现当我在linker setting那里加入"-lcrypto"的时候,编译器告诉我说,”cannot find -lcrypto“当我把 "-lmysqlpp  -lpthread  -ldl" 全部删掉以后,程序仍然能够编译成功。所以,我猜测,C::B根据Link libraries找到链接,并不依赖于-l library功能,而makefile依赖于-l library,因为makefile只需要-ldl即可自己找到/usr/lib/x86_64-linux-gnu/libdl.so。
        以后如果出现 ”cannot find -lcrypto“等类似问题,首先 "locate libcrypto.so libcrypto.a" 等,通过查找可以知道系统里面到底有没有libcrypto的动态库和静态库。经过查看发现有libcrypto.so.1.0.0,这个是系统自带。因为我在安装的时候,并没有选上动态库,所以默认没装。可以用系统自带的,也可以选择重装openssl。
 openssl之RSA编程第一步 - yuanshuilee - 勇敢的劳尤条
运行 :ln -s /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 /usr/local/openssl/lib/libcrypto.so 
就可以创建动态共享库的链接,从而满足需求。

最后附上openssl里面"rsa.h"的一部分,从这里可以看出RSA_generate_key这个版本已经被废弃了,以后尽量用新版本RSA_generate_key_ex

/* Deprecated version */
#ifndef OPENSSL_NO_DEPRECATED
RSA * RSA_generate_key(int bits, unsigned long e,void
(*callback)(int,int,void *),void *cb_arg);
#endif /* !defined(OPENSSL_NO_DEPRECATED) */

/* New version */
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);

int RSA_check_key(const RSA *);
/* next 4 return -1 on error */
int RSA_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,int padding);
int RSA_private_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,int padding);
int RSA_public_decrypt(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);
void RSA_free (RSA *r);


参考资料:
下面四个链接,都来自openssl官网,分别有rsa和genrsa工具的使用,以及pem和rsa部分api介绍。
http://www.openssl.org/docs/apps/rsa.html#

http://fossies.org/dox/openssl-1.0.1f/index.html (详细源码)

  评论这张
 
阅读(1760)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017