⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lib_dsa.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 2 页
字号:

   The input is the 160-bit hash, usually SHA but possibly also RIPEMD-160 */

/* The size of each DSA signature component - 160 bits */

#define DSA_SIGPART_SIZE	20

/* Sign a single block of data  */

int dsaSign( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int noBytes )
	{
	PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
	DLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;
	BIGNUM *p = &pkcInfo->dlpParam_p, *q = &pkcInfo->dlpParam_q;
	BIGNUM *g = &pkcInfo->dlpParam_g, *x = &pkcInfo->dlpParam_x;
	BIGNUM *hash = &pkcInfo->tmp1, *k = &pkcInfo->tmp2, *kInv = &pkcInfo->tmp3;
	BIGNUM *r = &pkcInfo->dlpTmp1, *s = &pkcInfo->dlpTmp2;
	int bnStatus = BN_STATUS, status;

	assert( noBytes == sizeof( DLP_PARAMS ) );
	assert( dlpParams->inParam1 != NULL && \
			dlpParams->inLen1 == DSA_SIGPART_SIZE );
	assert( dlpParams->inParam2 == NULL && \
			( dlpParams->inLen2 == 0 || dlpParams->inLen2 == -999 ) );
	assert( dlpParams->outParam != NULL && \
			dlpParams->outLen >= ( 2 + DSA_SIGPART_SIZE ) * 2 );

	/* Generate the secret random value k.  During the initial self-test
	   the random data pool may not exist yet, and may in fact never exist in
	   a satisfactory condition if there isn't enough randomness present in
	   the system to generate cryptographically strong random numbers.  To
	   bypass this problem, if the caller passes in a second length parameter 
	   of -999, we know that it's an internal self-test call and use a fixed 
	   bit pattern for k which avoids having to call generateBignum() (this 
	   also means we can use the FIPS 186 self-test value for k).  This is a 
	   somewhat ugly use of 'magic numbers', but it's safe because this 
	   function can only be called internally, so all we need to trap is 
	   accidental use of the parameter which is normally unused */
	if( dlpParams->inLen2 == -999 )
		BN_bin2bn( ( BYTE * ) kVal, DSA_SIGPART_SIZE, k );
	else
		{
		/* Generate the random value k.  FIPS 186 requires (Appendix 3)
		   that this be done with:

			k = G(t,KKEY) mod q

		   where G(t,c) produces a 160-bit output, however this produces a
		   slight bias in k which leaks a small amount of the private key in
		   each signature.  Because of this we start with a value which is
		   32 bits larger than q and then do the reduction, eliminating the
		   bias */
		status = generateBignum( k, bytesToBits( DSA_SIGPART_SIZE ) + 32,
								 0, 0 );
		if( cryptStatusError( status ) )
			return( status );
		}
	CK( BN_mod( k, k, q, 				/* Reduce k to the correct range */
				&pkcInfo->bnCTX ) );
	if( bnStatusError( bnStatus ) )
		return( getBnStatus( bnStatus ) );

	/* Move the data from the buffer into a bignum */
	BN_bin2bn( ( BYTE * ) dlpParams->inParam1, DSA_SIGPART_SIZE, hash );

	/* r = ( g ^ k mod p ) mod q */
	CK( BN_mod_exp_mont( r, g, k, p, &pkcInfo->bnCTX, 
						 &pkcInfo->dlpParam_mont_p ) );
	CK( BN_mod( r, r, q, &pkcInfo->bnCTX ) );

	/* s = k^-1 * ( hash + x * r ) mod q */
	CKPTR( BN_mod_inverse( kInv, k, q,	/* temp = k^-1 mod q */
						   &pkcInfo->bnCTX ) );
/*	BN_mul( s, x, r );					// s = x * r */
	CK( BN_mod_mul( s, x, r, q,			/* s = ( x * r ) mod q */
					&pkcInfo->bnCTX ) );
	CK( BN_add( s, s, hash ) );			/* s = s + hash */
	if( BN_cmp( s, q ) > 0 )			/* if s > q */
		CK( BN_sub( s, s, q ) );		/*   s = s - q (fast mod) */
	CK( BN_mod_mul( s, s, kInv, q,		/* s = k^-1 * ( hash + x * r ) mod q */
					&pkcInfo->bnCTX ) );
	if( bnStatusError( bnStatus ) )
		return( getBnStatus( bnStatus ) );

	/* Encode the result as a DL data block */
	status = encodeDLValues( dlpParams->outParam, dlpParams->outLen, r, s,
							 dlpParams->formatType );
	if( !cryptStatusError( status ) )
		{
		dlpParams->outLen = status;
		status = CRYPT_OK;	/* encodeDLValues() returns a byte count */
		}
	return( status );
	}

/* Signature check a single block of data */

int dsaSigCheck( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int noBytes )
	{
	PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
	DLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;
	BIGNUM *p = &pkcInfo->dlpParam_p, *q = &pkcInfo->dlpParam_q;
	BIGNUM *g = &pkcInfo->dlpParam_g, *y = &pkcInfo->dlpParam_y;
	BIGNUM *r = &pkcInfo->tmp1, *s = &pkcInfo->tmp2;
	BIGNUM *u1 = &pkcInfo->tmp3, *u2 = &pkcInfo->dlpTmp1;	/* Doubles as w */
	int bnStatus = BN_STATUS, status;

	assert( noBytes == sizeof( DLP_PARAMS ) );
	assert( dlpParams->inParam1 != NULL && dlpParams->inLen1 == 20 );
	assert( dlpParams->inParam2 != NULL && \
			( ( dlpParams->formatType == CRYPT_FORMAT_CRYPTLIB && \
				( dlpParams->inLen2 >= 42 && dlpParams->inLen2 <= 48 ) ) || \
			  ( dlpParams->formatType == CRYPT_FORMAT_PGP && \
				( dlpParams->inLen2 >= 42 && dlpParams->inLen2 <= 44 ) ) || \
			  ( dlpParams->formatType == CRYPT_IFORMAT_SSH && \
				dlpParams->inLen2 == 40 ) ) );
	assert( dlpParams->outParam == NULL && dlpParams->outLen == 0 );

	/* Decode the values from a DL data block and make sure r and s are
	   valid */
	status = decodeDLValues( dlpParams->inParam2, dlpParams->inLen2, &r, &s,
							 dlpParams->formatType );
	if( cryptStatusError( status ) )
		return( status );
	if( BN_cmp( r, q ) >= 0 || BN_cmp( s, q ) >= 0 )
		return( CRYPT_ERROR_BADDATA );

	BN_bin2bn( ( BYTE * ) dlpParams->inParam1, DSA_SIGPART_SIZE, u1 );

	/* w = s^-1 mod q */
	CKPTR( BN_mod_inverse( u2, s, q,	/* w = s^-1 mod q */
						   &pkcInfo->bnCTX ) );

	/* u1 = ( hash * w ) mod q */
	CK( BN_mod_mul( u1, u1, u2, q,		/* u1 = ( hash * w ) mod q */
					&pkcInfo->bnCTX ) );

	/* u2 = ( r * w ) mod q */
	CK( BN_mod_mul( u2, r, u2, q,		/* u2 = ( r * w ) mod q */
					&pkcInfo->bnCTX ) );

	/* v = ( ( ( g^u1 ) * ( y^u2 ) ) mod p ) mod q */
	CK( BN_mod_exp2_mont( u2, g, u1, y, u2, p, &pkcInfo->bnCTX,
						  &pkcInfo->dlpParam_mont_p ) );
	CK( BN_mod( s, u2, q, &pkcInfo->bnCTX ) );
	if( bnStatusError( bnStatus ) )
		return( getBnStatus( bnStatus ) );

	/* if r == s signature is good */
	return( BN_cmp( r, s ) ? CRYPT_ERROR_SIGNATURE : CRYPT_OK );
	}

/****************************************************************************
*																			*
*								Key Management								*
*																			*
****************************************************************************/

/* Load key components into an encryption context */

int dsaInitKey( CONTEXT_INFO *contextInfoPtr, const void *key, 
				const int keyLength )
	{
	int status;

#ifndef USE_FIPS140
	/* Load the key component from the external representation into the
	   internal bignums unless we're doing an internal load */
	if( key != NULL )
		{
		PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
		const CRYPT_PKCINFO_DLP *dsaKey = ( CRYPT_PKCINFO_DLP * ) key;

		contextInfoPtr->flags |= ( dsaKey->isPublicKey ) ? \
							CONTEXT_ISPUBLICKEY : CONTEXT_ISPRIVATEKEY;
		BN_bin2bn( dsaKey->p, bitsToBytes( dsaKey->pLen ),
				   &pkcInfo->dlpParam_p );
		BN_bin2bn( dsaKey->q, bitsToBytes( dsaKey->qLen ),
				   &pkcInfo->dlpParam_q );
		BN_bin2bn( dsaKey->g, bitsToBytes( dsaKey->gLen ),
				   &pkcInfo->dlpParam_g );
		BN_bin2bn( dsaKey->y, bitsToBytes( dsaKey->yLen ),
				   &pkcInfo->dlpParam_y );
		if( !dsaKey->isPublicKey )
			BN_bin2bn( dsaKey->x, bitsToBytes( dsaKey->xLen ),
					   &pkcInfo->dlpParam_x );
		contextInfoPtr->flags |= CONTEXT_PBO;
		}
#endif /* USE_FIPS140 */

	/* Complete the key checking and setup */
	status = initDLPkey( contextInfoPtr, FALSE );
	if( cryptStatusOK( status ) )
		status = checkDLPkey( contextInfoPtr, FALSE );
	if( cryptStatusOK( status ) )
		status = calculateKeyID( contextInfoPtr );
	return( status );
	}

/* Generate a key into an encryption context */

int dsaGenerateKey( CONTEXT_INFO *contextInfoPtr, const int keySizeBits )
	{
	int status;

	status = generateDLPkey( contextInfoPtr, ( keySizeBits / 64 ) * 64, 160,
							 TRUE );
	if( cryptStatusOK( status ) )
		status = calculateKeyID( contextInfoPtr );
	return( status );
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -