找回密码
 注册
搜索
热搜: 超星 读书 找书
查看: 4654|回复: 0

[【推荐】] 在OpenSSL中添加自定义加密算法

[复制链接]
发表于 2009-8-6 14:52:08 | 显示全部楼层 |阅读模式
1.加密算法的加载... 1

2.密码算法接口的定义... 4

3.示例... 8


1.加密算法的加载

在调用加密算法之前,通过调用OpenSSL_add_all_algorithms来加载加密算法函数和单向散列算法函数

void OpenSSL_add_all_algorithms(void)

{

    OpenSSL_add_all_ciphers(); /* 加载加密算法 */

    OpenSSL_add_all_digests(); /* 加载单向散列函数 */

}



void OpenSSL_add_all_ciphers(void)函数实现如下:



void OpenSSL_add_all_ciphers(void)

    {

    EVP_add_cipher(EVP_rc2_cfb());

    ......

    PKCS12_PBE_add();

    PKCS5_PBE_add();

    }

/* 这个过程的主要任务是向全局变量,static LHASH *names_lh,注册加密算法,如果添加了新的加密算法,必需向names_lh注册。 */



以下是IDEA算法的接口:

#ifndef NO_IDEA

    EVP_add_cipher(EVP_idea_ecb());   /*添加EBC加密模式 */

    EVP_add_cipher(EVP_idea_cfb());    /*添加CFB加密模式 */

    EVP_add_cipher(EVP_idea_ofb());    /*添加OCF加密模式 */

    EVP_add_cipher(EVP_idea_cbc());   /*添加CBC加密模式 */

    EVP_add_cipher_alias(SN_idea_cbc,\"IDEA\");   /*添加cbc加密算法的别名 “IDEA” */

    EVP_add_cipher_alias(SN_idea_cbc,\"idea\"); /*添加cbc加密算法的别名 “idea” */

#endif



在包括IDEA加密算法的情况下,OpenSSL将会选择IDAE加密算法模块!



下面来看看EVP_add_cipher函数是怎么实现的,

int EVP_add_cipher(EVP_CIPHER *c)

{

    int r;



    r=OBJ_NAME_add(OBJ_nid2sn(c->nid),OBJ_NAME_TYPE_CIPHER_METH,(char *)c);

    if (r == 0) return(0);

    r=OBJ_NAME_add(OBJ_nid2ln(c->nid),OBJ_NAME_TYPE_CIPHER_METH,(char *)c);

    return(r);

}



/* 向全决变量names_lh 注册 obj_name_types 变量的过程 */

int OBJ_NAME_add(const char *name, int type, const char *data)

    {

    OBJ_NAME *onp,*ret;

    int alias;



    if ((names_lh == NULL) && !OBJ_NAME_init()) return(0);



    alias=type&OBJ_NAME_ALIAS;

    type&= ~OBJ_NAME_ALIAS;



    onp=(OBJ_NAME *)OPENSSL_malloc(sizeof(OBJ_NAME));

    if (onp == NULL)

       {

       /* ERROR */

       return(0);

       }



    onp->name=name;

    onp->alias=alias;

    onp->type=type;

    onp->data=data;



    ret=(OBJ_NAME *)lh_insert(names_lh,onp);

    if (ret != NULL)

       {

       /* free things */

       if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type))

           {

           /* XXX: I'm not sure I understand why the free

           * function should get three arguments...

           * -- Richard Levitte

           */

           sk_NAME_FUNCS_value(name_funcs_stack,ret->type)

              ->free_func(ret->name,ret->type,ret->data);

           }

       OPENSSL_free(ret);

       }

    else

       {

       if (lh_error(names_lh))

           {

           /* ERROR */

           return(0);

           }

       }

    return(1);

    }



names_lh 是 LHASH的全局变量,用于维护obj_name_types的类型的变量。(在crypt/objects/o_names.c中定义)



(crypt/objects/obj_dat.h)相关的全局变量

static unsigned char lvalues[2896] 全局变量,已经初始化,存放了OpenSSL所有Object的相关信息。

nid_objs 是ASN1_OBJECT结构的数组全局变量,已经初始化,记录了所有OpenSSL用到的类型的名字

static ASN1_OBJECT *sn_objs[NUM_SN] 全局变量,已经初始化。

static ASN1_OBJECT *ln_objs[NUM_LN] 全局变量,已经初始化。



crypt/object/objects.h 中定义的结构

typedef struct obj_name_st

{

    int type;

    int alias;

    const char *name;

    const char *data;

} OBJ_NAME;



注意:crypto/objects 目录下面维护整个OpenSSL模块化的重要的程序,下面逐个做出介绍。

objects.txt 按照一定的语法结构,定义了SN_base, LN_base, NID_base,OBJ_base。经过perl程序objects.pl通过命令perl objects.pl objects.txt obj_mac.num obj_mac.h 处理后,生成了obj_mac.num 和obj_mac.h两个文件。

obj_mac.num 用来查阅 OBJ_base与NID_base之间的对应关系。

obj_mac.h 用来提供c语言类型SN_base, LN_base, NID_base,OBJ_base定义。

objects.h 同样提供了c语言类型SN_base, LN_base, NID_base,OBJ_base定义,在obj_mac.h 更新之后,必须对对应的objects.h 中的内容作出同步,及保持与obj_mac.h的定义一至,同时objects.h中也声明了一些对OBJ_name的操作函数。

objects.h 经过perl程序perl obj_dat.pl objects.h obj_dat.h处理之后,生成obj_dat.h头文件。



我们可以通过在objects.txt中的注册算法OID,就可以使用命令perl objects.pl objects.txt obj_mac.num obj_mac.h来生成自定义算法的一系列声明.

以下是我们添加的算法

在其中添加一行条目

rsadsi 3 255  : SSF33   : ssf33

分别生成以下声明

obj_dat.h:780:0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x81,0x7F,/* [5001] OBJ_ssf33 */

obj_dat.h:1949:{\"SSF33\",\"ssf33\",NID_ssf33,9,&(lvalues[5001]),0},

obj_dat.h:3418:&(nid_objs[751]),/* \"ssf33\" */

obj_dat.h:3958:&(nid_objs[751]),/* OBJ_ssf33            1 2 840 113549 3 255 */

objects.txt:1046:rsadsi 3 255  : SSF33     : ssf33

obj_mac.h:3294:#define SN_ssf33     \"SSF33\"

obj_mac.h:3295:#define LN_ssf33     \"ssf33\"

obj_mac.h:3296:#define NID_ssf33        751

obj_mac.h:3297:#define OBJ_ssf33        OBJ_rsadsi,3L,255L

obj_mac.num:751:ssf33      751


2.密码算法接口的定义

typedef struct evp_cipher_st EVP_CIPHER;

/* 加密算法后被names_lh来管理,可以通算法的名称或别名来检索 */

struct evp_cipher_st

    {

    int nid;             /*加密算法的nid*/

    int block_size;        /*数据块的大小 */

    int key_len;      /* Default value for variable length ciphers */

    int iv_len;       /* 对于CBC,CFB,OFB的加密算法初始化矢量*/

    unsigned long flags;    /* Various flags */

    int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key,

         const unsigned char *iv, int enc); /* init key */

    int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out,

           const unsigned char *in, unsigned int inl);/* encrypt/decrypt data */

    int (*cleanup)(EVP_CIPHER_CTX *); /* cleanup ctx */

    int ctx_size;      /* how big the ctx needs to be */

    int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Populate a ASN1_TYPE with parameters */

    int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Get parameters from a ASN1_TYPE */

    int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr); /* Miscellaneous operations */

    void *app_data;       /* Application data */

    };



如果正确定义了EVP_CIPHER变量,这个算法就可以被OpenSSL所接受了。



下面的宏将定义ECB,CBC,CFB,OFB算法EVP_CIPHER定义。

#define BLOCK_CIPHER_defs(cname, kstruct, \\

              nid, block_size, key_len, iv_len, flags,\\

               init_key, cleanup, set_asn1, get_asn1, ctrl)\\

static EVP_CIPHER cname##_cbc = {\\

    nid##_cbc, block_size, key_len, iv_len, \\

    flags | EVP_CIPH_CBC_MODE,\\

    init_key,\\

    cname##_cbc_cipher,\\

    cleanup,\\

    sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\\

       sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\\

    set_asn1, get_asn1,\\

    ctrl, \\

    NULL \\

};\\



EVP_CIPHER *EVP_##cname##_cbc(void) { return &cname##_cbc; }\\

static EVP_CIPHER cname##_cfb = {\\

    nid##_cfb64, 1, key_len, iv_len, \\

    flags | EVP_CIPH_CFB_MODE,\\

    init_key,\\

    cname##_cfb_cipher,\\

    cleanup,\\

    sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\\

       sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\\

    set_asn1, get_asn1,\\

    ctrl,\\

    NULL \\

};\\

EVP_CIPHER *EVP_##cname##_cfb(void) { return &cname##_cfb; }\\

static EVP_CIPHER cname##_ofb = {\\

    nid##_ofb64, 1, key_len, iv_len, \\

    flags | EVP_CIPH_OFB_MODE,\\

    init_key,\\

    cname##_ofb_cipher,\\

    cleanup,\\

    sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\\

       sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\\

    set_asn1, get_asn1,\\

    ctrl,\\

    NULL \\

};\\



EVP_CIPHER *EVP_##cname##_ofb(void) { return &cname##_ofb; }\\

static EVP_CIPHER cname##_ecb = {\\

    nid##_ecb, block_size, key_len, iv_len, \\

    flags | EVP_CIPH_ECB_MODE,\\

    init_key,\\

    cname##_ecb_cipher,\\

    cleanup,\\

    sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\\

       sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\\

    (ctx_size 其中有联合的结构,如何获取EVP_CIPHER_CTX数据长度)

    set_asn1, get_asn1,\\

    ctrl,\\

    NULL \\

};\\



EVP_CIPHER *EVP_##cname##_ecb(void) { return &cname##_ecb; }

上面的宏在经过处理之后,变成了四中加密模式的EVP_CIPHER定义,这个结构中封装了加密操作汉书,密钥初始化函数,以及密钥的清理函数。除了实现加密算法之外,还比需实现对应的密钥结构!



EVP_CIPHER_CTX就是密钥结构,完成对加密算法密钥的管理。

typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;

struct evp_cipher_ctx_st

{

    const EVP_CIPHER *cipher;

    int encrypt;      /* encrypt or decrypt */

    int buf_len;      /* number we have left */



    unsigned char oiv[EVP_MAX_IV_LENGTH];  /* original iv */

    unsigned char iv[EVP_MAX_IV_LENGTH];   /* working iv */

    unsigned char buf[EVP_MAX_IV_LENGTH];   /* saved partial block */

    int num;            /* used by cfb/ofb mode */



    void *app_data;       /* application stuff */

    int key_len;      /* May change for variable length cipher */

/* 通过联合的方式管理密钥,对各种密钥实现灵活的管理 */

    union   {

#ifndef NO_RC4

       struct

           {

           unsigned char key[EVP_RC4_KEY_SIZE];

           RC4_KEY ks; /* working key */

           } rc4;

#endif

#ifndef NO_DES

       des_key_schedule des_ks;/* key schedule */

       struct

           {

           des_key_schedule ks;/* key schedule */

           des_cblock inw;

           des_cblock outw;

           } desx_cbc;

       struct

           {

           des_key_schedule ks1;/* key schedule */

           des_key_schedule ks2;/* key schedule (for ede) */

           des_key_schedule ks3;/* key schedule (for ede3) */

           } des_ede;

#endif

#ifndef NO_IDEA

       IDEA_KEY_SCHEDULE idea_ks;/* key schedule */

#endif

#ifndef NO_RC2

       struct {

           int key_bits;  /* effective key bits */

           RC2_KEY ks;/* key schedule */

       } rc2;

#endif

#ifndef NO_RC5

       struct {

           int rounds;   /* number of rounds */

           RC5_32_KEY ks;/* key schedule */

       } rc5;

#endif

#ifndef NO_BF

       BF_KEY bf_ks;/* key schedule */

#endif

#ifndef NO_CAST

       CAST_KEY cast_ks;/* key schedule */

#endif

       } c;

};


3.示例

熟悉了这些结构,我们就可以通过这些ssf33的算法的申明添加自定义算法了,这里我们以RC4算法为模板只是修改名字来创建我们的算法.

在crypto\\evp\\下添加e_ssf33.c,内容如下

#include <stdio.h>

#include \"cryptlib.h\"



#ifndef OPENSSL_NO_RC4



#include <openssl/evp.h>

#include <openssl/objects.h>

#include <openssl/rc4.h>



/* FIXME: surely this is available elsewhere? */

#define EVP_SSF33_KEY_SIZE   16



typedef struct

  {

  RC4_KEY ks; /* working key */

  } EVP_SSF33_KEY;



#define data(ctx) ((EVP_SSF33_KEY *)(ctx)->cipher_data)



static int ssf33_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,

      const unsigned char *iv,int enc);

static int ssf33_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,

       const unsigned char *in, unsigned int inl);

static const EVP_CIPHER ssf33_evp_cipher=

  {

  NID_ssf33,

  1,EVP_SSF33_KEY_SIZE,0,

  EVP_CIPH_VARIABLE_LENGTH,

  ssf33_init_key,

  ssf33_cipher,

  NULL,

  sizeof(EVP_SSF33_KEY),

  NULL,

  NULL,

  NULL,

  NULL

  };

const EVP_CIPHER *EVP_ssf33(void)

  {

  return(&ssf33_evp_cipher);

  }



static int ssf33_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,

      const unsigned char *iv, int enc)

  {

  RC4_set_key(&data(ctx)->ks,EVP_CIPHER_CTX_key_length(ctx),

      key);

  return 1;

  }



static int ssf33_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,

       const unsigned char *in, unsigned int inl)

  {

  RC4(&data(ctx)->ks,inl,in,out);

  return 1;

  }

#endif

接下来在evp.h中添加对算法的声明

evp.h:const EVP_CIPHER *EVP_ssf33(void);

这样我们只要在c_allc.c文件中修改OpenSSL_add_all_ciphers函数,使用EVP_add_cipher注册加密函数就可以了.

EVP_add_cipher(EVP_ssf33());

就可以使用此函数了!可以通过evp_test测试实例!^_^
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|网上读书园地

GMT+8, 2024-12-22 20:07 , Processed in 0.156006 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表