openssl DSA 算法学习

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)算法是一种公钥算法。其密钥由如下部分组成:

1p一个大素数,长度为L(64的整数倍)比特。

2q一个160比特素数。

3=h(p-1)/q mod p,其中h小于p-1

4x小于q

5) y=gx mod p

其中x为私钥,y为公钥。pqg是公开信息(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的设置。

openssl DSA 算法学习_第1张图片

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);





你可能感兴趣的:(openssl DSA 算法学习)