1,DSA简介
struct dsa_st { /* This first variable is used to pick up errors where * a DSA is passed instead of of a EVP_PKEY */ int pad; long version; int write_params; BIGNUM *p; BIGNUM *q; /* == 20 */ BIGNUM *g; BIGNUM *pub_key; /* y public key */ BIGNUM *priv_key; /* x private key */ BIGNUM *kinv; /* Signing pre-calc */ BIGNUM *r; /* Signing pre-calc */ int flags; /* Normally used to cache montgomery values */ BN_MONT_CTX *method_mont_p; int references; CRYPTO_EX_DATA ex_data; const DSA_METHOD *meth; /* functional reference if 'meth' is ENGINE-provided */ ENGINE *engine; };
Digital Signature Algorithm (DSA)算法是一种公钥算法。其密钥由如下部分组成:
1)p一个大素数,长度为L(64的整数倍)比特。
2)q一个160比特素数。
3)g =h(p-1)/q mod p,其中h小于p-1。
4)x小于q。
5) y=gx mod p。
其中x为私钥,y为公钥。p、q和g是公开信息(openssl中称为密钥参数)。
DSA签名包括两部分,如下:
r = (gk mod p) mod q
s = (k-1 (H(m) + xr)) mod q
其中,H(m)为摘要算法;
DSA验签如下:
w = s-1 mod q
u1 = (H(m) * w) mod q
u2 = (rw) mod q
v = ((gu1 * yu2) mod p) mod q
如果v=r,则验证通过。
2,DSA 算法调用过程
1)初始化DSA结构体
DSA* DSA_new();在该函数中会设置meth首先看一下,meth的结构体原型,有代码中我们可以清晰的看到meth结构是函数指针,后面签名等函数的调用就是调用结构体函数指针。首先我们来看一下DSA_new()中对meth的设置。
struct dsa_method { const char *name; DSA_SIG * (*dsa_do_sign)(const unsigned char *dgst, int dlen, DSA *dsa); int (*dsa_sign_setup)(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp); int (*dsa_do_verify)(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa); int (*dsa_mod_exp)(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont); int (*bn_mod_exp)(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); /* Can be null */ int (*init)(DSA *dsa); int (*finish)(DSA *dsa); int flags; char *app_data; /* If this is non-NULL, it is used to generate DSA parameters */ int (*dsa_paramgen)(DSA *dsa, int bits, const unsigned char *seed, int seed_len, int *counter_ret, unsigned long *h_ret, BN_GENCB *cb); /* If this is non-NULL, it is used to generate DSA keys */ int (*dsa_keygen)(DSA *dsa); };
2)在生成密钥之前需要先生成密钥参数。调用
int DSA_generate_parameters_ex(DSA *ret,int bits,const unsigned char *seed_in, int seed_len,int *counter_ret, unsigned long *h_ret, BN_GENCB *cb)
其中bits设置是为了选择哪一种hash算法。该函数功能是生成前面所讲的P、Q、G 三个参数。
在我们们跟踪到具体的代码发现,所有的都用基本上都是通过调用DSA结构体中的meth,而该结构成员基本上都是结构体指针。
3)生成密钥,即生成DSA中的pub_key和priv_key
int DSA_generate_key(DSA *dsa)4)最后进行sign和verify
int DSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig, unsigned int *siglen, DSA *dsa); int DSA_verify(int type, const unsigned char *dgst, int dgst_len, const unsigned char *sigbuf, int siglen, DSA *dsa);