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

📄 timing.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
					( long ) ( timeCorrSum10 / timesCount10 ) );
		else
		if( noTimes <= 2 && i == 1 )
			printf( "Priv: min.= %d, avg.= %d ", ( long ) timeMin,
					( long ) ( timeCorrSum10 / timesCount10 ) );
		else
			printf( "%6d", ( long ) ( timeCorrSum10 / timesCount10 ) );
#if 0	/* Print difference to fastest time, usually only around 1% */
		printf( "(%4d)", ( timeCorrSum10 / timesCount10 ) - timeMin );
#endif /* 0 */

#ifdef USE_SD
		/* Find the standard deviation */
		for( j = 1; j < NO_TESTS + 1; j++ )
			{
			const HIRES_TIME timeDev = times[ j ][ i ] - timeAvg;

			timeCorrSumSD += ( timeDev * timeDev );
			}
		stdDev = timeCorrSumSD / NO_TESTS;
		stdDev = sqrt( stdDev );

		/* Find the mean time, discarding anomalous results more than two
		   standard deviations out */
		timeCorrSumSD = 0;
		timeDelta = ( HIRES_TIME ) stdDev * 2;
		for( j = 1; j < NO_TESTS + 1; j++ )
			if( times[ j ][ i ] > timeAvg - timeDelta && \
				times[ j ][ i ] < timeAvg + timeDelta )
				{
				timeCorrSumSD += times[ j ][ i ];
				timesCountSD++;
				}
		if( timesCountSD == 0 )
			timesCountSD++;	/* Context switch, fudge it */
		printf( "%6d", timeCorrSumSD / timesCountSD );

#if 1	/* Print difference to fastest and mean times, usually only around
		   1% */
		printf( " (dF = %4d, dM = %4d)\n",
				( timeCorrSumSD / timesCountSD ) - timeMin,
				abs( ( timeCorrSumSD / timesCountSD ) - \
					 ( timeCorrSum10 / timesCount10 ) ) );
#endif /* 0 */
#endif /* USE_SD */
		}
	printf( "\n" );
	}

static HIRES_TIME encOne( const CRYPT_CONTEXT cryptContext,
						  BYTE *buffer, const int length )
	{
	HIRES_TIME timeVal;
	int status;

	memset( buffer, '*', length );
	timeVal = timeDiff( 0 );
	status = cryptEncrypt( cryptContext, buffer, length );
	return( timeDiff( timeVal ) );
	}

static void encTest( const CRYPT_CONTEXT cryptContext,
					 const CRYPT_ALGO_TYPE cryptAlgo, BYTE *buffer,
					 HIRES_TIME times[] )
	{
	int index = 0;

	times[ index++ ] = ( cryptAlgo != CRYPT_ALGO_AES ) ? \
					   encOne( cryptContext, buffer, 8 ) : 0;
	times[ index++ ] = encOne( cryptContext, buffer, 16 );
	times[ index++ ] = encOne( cryptContext, buffer, 64 );
	times[ index++ ] = encOne( cryptContext, buffer, 1024 );
	times[ index++ ] = encOne( cryptContext, buffer, 4096 );
	times[ index++ ] = encOne( cryptContext, buffer, 8192 );
	times[ index++ ] = encOne( cryptContext, buffer, 65536L );
	}

static int encTests( const CRYPT_DEVICE cryptDevice,
					 const CRYPT_ALGO_TYPE cryptAlgo,
					 const CRYPT_ALGO_TYPE cryptMode,
					 BYTE *buffer )
	{
	CRYPT_CONTEXT cryptContext;
	HIRES_TIME times[ NO_TESTS + 1 ][ 8 ], timeVal, timeSum = 0;
	int i, status;

	memset( buffer, 0, 100000L );

	/* Set up the context for use */
	if( !checkLowlevelInfo( cryptDevice, cryptAlgo ) )
		return( FALSE );
	for( i = 0; i < 10; i++ )
		{
		timeVal = timeDiff( 0 );
		status = loadContexts( &cryptContext, NULL, cryptDevice,
							   cryptAlgo, cryptMode,
							   ( BYTE * ) "12345678901234567890",
							   ( cryptAlgo == CRYPT_ALGO_DES ) ? 8 : \
							   ( cryptAlgo == CRYPT_ALGO_3DES || \
							     cryptAlgo == CRYPT_ALGO_RC4 || \
								 cryptAlgo == CRYPT_ALGO_AES ) ? 16 : 0 );
		timeVal = timeDiff( timeVal );
		if( status == CRYPT_ERROR_NOTAVAIL || !status )
			return( FALSE );
		timeSum += timeVal;
		if( i < 9 )
			cryptDestroyContext( cryptContext );
		}
	printf( "setup time = %d ticks.\n", timeSum / 10 );
	puts( "     8    16    64    1K    4K    8K   64K" );
	puts( "  ----  ----  ----  ----  ----  ----  ----" );

	/* Run the encryption tests NO_TESTS times, discarding the first set
	   of results since the cache will be empty at that point */
	for( i = 0; i < NO_TESTS + 1; i++ )
		encTest( cryptContext, cryptAlgo, buffer, times[ i ] );
	printTimes( times, 7 );

	/* Re-run the encryption tests with a 1-byte misalignment */
	for( i = 0; i < NO_TESTS + 1; i++ )
		encTest( cryptContext, cryptAlgo, buffer + 1, times[ i ] );
	printTimes( times, 7 );

	/* Re-run the encryption tests with a 4-byte misalignment */
	for( i = 0; i < NO_TESTS + 1; i++ )
		encTest( cryptContext, cryptAlgo, buffer + 4, times[ i ] );
	printTimes( times, 7 );

	/* Re-run the test 1000 times with various buffer alignments */
	timeVal = 0;
	for( i = 0; i < 1000; i++ )
		timeVal += encOne( cryptContext, buffer, 1024 );
	printf( "Aligned: %d ", timeVal / 1000 );
	timeVal = 0;
	for( i = 0; i < 1000; i++ )
		timeVal += encOne( cryptContext, buffer + 1, 1024 );
	printf( "misaligned + 1: %d ", timeVal / 1000 );
	timeVal = 0;
	for( i = 0; i < 1000; i++ )
		timeVal += encOne( cryptContext, buffer + 4, 1024 );
	printf( "misaligned + 4: %d.\n", timeVal / 1000 );

	return( TRUE );
	}

static void performanceTests( const CRYPT_DEVICE cryptDevice )
	{
	BYTE *buffer;

	if( ( buffer = malloc( 100000L ) ) == NULL )
		{
		puts( "Couldn't 100K allocate test buffer." );
		return;
		}
	encTests( cryptDevice, CRYPT_ALGO_DES, CRYPT_MODE_ECB, buffer );
	encTests( cryptDevice, CRYPT_ALGO_DES, CRYPT_MODE_CBC, buffer );
	encTests( cryptDevice, CRYPT_ALGO_3DES, CRYPT_MODE_ECB, buffer );
	encTests( cryptDevice, CRYPT_ALGO_3DES, CRYPT_MODE_CBC, buffer );
	encTests( cryptDevice, CRYPT_ALGO_RC4, CRYPT_MODE_OFB, buffer );
	encTests( cryptDevice, CRYPT_ALGO_AES, CRYPT_MODE_CBC, buffer );
	encTests( cryptDevice, CRYPT_ALGO_MD5, CRYPT_MODE_NONE, buffer );
	encTests( cryptDevice, CRYPT_ALGO_SHA, CRYPT_MODE_NONE, buffer );
	free( buffer );
	}

/****************************************************************************
*																			*
*								PKC Timing Tests							*
*																			*
****************************************************************************/

/* Timing tests for PKC crypto operations.  Since the DH operations aren't
   visible externally, we have to use the kernel API to perform the timing
   test.  To get the necessary definitions and prototypes, we have to use
   crypt.h, however since we've already included cryptlib.h the built-in
   guards preclude us from pulling it in again with the internal-only values
   defined, so we have to explicitly define things like attribute values
   that normally aren't visible externally */

#undef __WINDOWS__
#undef __WIN16__
#undef __WIN32__
#undef BYTE
#undef BOOLEAN
#ifdef _MSC_VER
  #define INC_CHILD
  #include "../crypt.h"
#else
  #include "crypt.h"
#endif /* Braindamaged MSC include handling */

#define CRYPT_IATTRIBUTE_KEY_SPKI	8015

static const BYTE dh1024SPKI[] = {
	0x30, 0x82, 0x01, 0x21,
		0x30, 0x82, 0x01, 0x17,
			0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3E, 0x02, 0x01,
			0x30, 0x82, 0x01, 0x0A,
				0x02, 0x81, 0x81, 0x00,		/* p */
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
					0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
					0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
					0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
					0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
					0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
					0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
					0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
					0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
					0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
					0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
					0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
					0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
					0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
					0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
				0x02, 0x01,					/* g */
					0x02,
				0x02, 0x81, 0x80,			/* q */
					0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
					0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A,
					0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68,
					0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A,
					0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91,
					0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E,
					0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D,
					0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B,
					0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22,
					0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63,
					0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5,
					0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6,
					0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2,
					0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3,
					0x24, 0x94, 0x33, 0x28, 0xF6, 0x73, 0x29, 0xC0,
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
		0x03, 0x04, 0x00,
			0x02, 0x01, 0x00 };				/* y */

static BOOLEAN loadDHKey( CRYPT_CONTEXT *cryptContext )
	{
	int status;

	/* Create the DH context */
	status = cryptCreateContext( cryptContext, CRYPT_UNUSED, CRYPT_ALGO_DH );
	if( cryptStatusError( status ) )
		{
		printf( "cryptCreateContext() failed with error code %d.\n",
				status );
		return( FALSE );
		}
	cryptSetAttributeString( *cryptContext, CRYPT_CTXINFO_LABEL,
							 "DH key", strlen( "DH key" ) );
	if( cryptStatusOK( status ) )
		{
		RESOURCE_DATA msgData;

		setMessageData( &msgData, ( void * ) dh1024SPKI,
						sizeof( dh1024SPKI ) );
#if 0
		status = krnlSendMessage( *cryptContext, IMESSAGE_SETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_KEY_SPKI );
#else
		status = cryptDeviceQueryCapability( *cryptContext, 1000,
									( CRYPT_QUERY_INFO * ) &msgData );
#endif /* 0 */
		}
	if( cryptStatusError( status ) )
		{
		printf( "DH key load failed, status = %d, line %d.\n", status,
				__LINE__ );
		return( FALSE );
		}
	return( TRUE );
	}

typedef struct {
	const int nLen; const BYTE n[ 128 ];
	const int eLen; const BYTE e[ 3 ];
	const int dLen; const BYTE d[ 128 ];
	const int pLen; const BYTE p[ 64 ];
	const int qLen; const BYTE q[ 64 ];
	const int uLen; const BYTE u[ 64 ];
	const int e1Len; const BYTE e1[ 64 ];
	const int e2Len; const BYTE e2[ 64 ];
	} RSA_KEY;

static const RSA_KEY rsa1024Key = {
	/* n */
	1024,
	{ 0x9C, 0x4D, 0x98, 0x18, 0x67, 0xF9, 0x45, 0xBC,
	  0xB6, 0x75, 0x53, 0x5D, 0x2C, 0xFA, 0x55, 0xE4,
	  0x51, 0x54, 0x9F, 0x0C, 0x16, 0xB1, 0xAF, 0x89,
	  0xF6, 0xF3, 0xE7, 0x78, 0xB1, 0x2B, 0x07, 0xFB,
	  0xDC, 0xDE, 0x64, 0x23, 0x34, 0x87, 0xDA, 0x0B,
	  0xE5, 0xB3, 0x17, 0x16, 0xA4, 0xE3, 0x7F, 0x23,
	  0xDF, 0x96, 0x16, 0x28, 0xA6, 0xD2, 0xF0, 0x0A,
	  0x59, 0xEE, 0x06, 0xB3, 0x76, 0x6C, 0x64, 0x19,
	  0xD9, 0x76, 0x41, 0x25, 0x66, 0xD1, 0x93, 0x51,
	  0x52, 0x06, 0x6B, 0x71, 0x50, 0x0E, 0xAB, 0x30,
	  0xA5, 0xC8, 0x41, 0xFC, 0x30, 0xBC, 0x32, 0xD7,
	  0x4B, 0x22, 0xF2, 0x45, 0x4C, 0x94, 0x68, 0xF1,
	  0x92, 0x8A, 0x4C, 0xF9, 0xD4, 0x5E, 0x87, 0x92,
	  0xA8, 0x54, 0x93, 0x92, 0x94, 0x48, 0xA4, 0xA3,
	  0xEE, 0x19, 0x7F, 0x6E, 0xD3, 0x14, 0xB1, 0x48,
	  0xCE, 0x93, 0xD1, 0xEA, 0x4C, 0xE1, 0x9D, 0xEF },

	/* e */
	17,
	{ 0x01, 0x00, 0x01 },

	/* d */
	1022,
	{ 0x37, 0xE2, 0x66, 0x67, 0x13, 0x85, 0xC4, 0xB1,
	  0x5C, 0x6B, 0x46, 0x8B, 0x21, 0xF1, 0xBF, 0x94,
	  0x0A, 0xA0, 0x3E, 0xDD, 0x8B, 0x9F, 0xAC, 0x2B,
	  0x9F, 0xE8, 0x44, 0xF2, 0x9A, 0x25, 0xD0, 0x8C,
	  0xF4, 0xC3, 0x6E, 0xFA, 0x47, 0x65, 0xEB, 0x48,
	  0x25, 0xB0, 0x8A, 0xA8, 0xC5, 0xFB, 0xB1, 0x11,
	  0x9A, 0x77, 0x87, 0x24, 0xB1, 0xC0, 0xE9, 0xA2,
	  0x49, 0xD5, 0x19, 0x00, 0x41, 0x6F, 0x2F, 0xBA,
	  0x9F, 0x28, 0x47, 0xF9, 0xB8, 0xBA, 0xFF, 0xF4,
	  0x8B, 0x20, 0xC9, 0xC9, 0x39, 0xAB, 0x52, 0x0E,
	  0x8A, 0x5A, 0xAF, 0xB3, 0xA3, 0x93, 0x4D, 0xBB,
	  0xFE, 0x62, 0x9B, 0x02, 0xCC, 0xA7, 0xB4, 0xAE,
	  0x86, 0x65, 0x88, 0x19, 0xD7, 0x44, 0xA7, 0xE4,
	  0x18, 0xB6, 0xCE, 0x01, 0xCD, 0xDF, 0x36, 0x81,
	  0xD5, 0xE1, 0x62, 0xF8, 0xD0, 0x27, 0xF1, 0x86,
	  0xA8, 0x58, 0xA7, 0xEB, 0x39, 0x79, 0x56, 0x41 },

	/* p */
	512,
	{ 0xCF, 0xDA, 0xF9, 0x99, 0x6F, 0x05, 0x95, 0x84,
	  0x09, 0x90, 0xB3, 0xAB, 0x39, 0xB7, 0xDD, 0x1D,
	  0x7B, 0xFC, 0xFD, 0x10, 0x35, 0xA0, 0x18, 0x1D,
	  0x9A, 0x11, 0x30, 0x90, 0xD4, 0x3B, 0xF0, 0x5A,
	  0xC1, 0xA6, 0xF4, 0x53, 0xD0, 0x94, 0xA0, 0xED,
	  0xE0, 0xE4, 0xE0, 0x8E, 0x44, 0x18, 0x42, 0x42,
	  0xE1, 0x2C, 0x0D, 0xF7, 0x30, 0xE2, 0xB8, 0x09,
	  0x73, 0x50, 0x28, 0xF6, 0x55, 0x85, 0x57, 0x03 },

	/* q */
	512,
	{ 0xC0, 0x81, 0xC4, 0x82, 0x6E, 0xF6, 0x1C, 0x92,
	  0x83, 0xEC, 0x17, 0xFB, 0x30, 0x98, 0xED, 0x6E,
	  0x89, 0x92, 0xB2, 0xA1, 0x21, 0x0D, 0xC1, 0x95,
	  0x49, 0x99, 0xD3, 0x79, 0xD3, 0xBD, 0x94, 0x93,
	  0xB9, 0x28, 0x68, 0xFF, 0xDE, 0xEB, 0xE8, 0xD2,
	  0x0B, 0xED, 0x7C, 0x08, 0xD0, 0xD5, 0x59, 0xE3,
	  0xC1, 0x76, 0xEA, 0xC1, 0xCD, 0xB6, 0x8B, 0x39,
	  0x4E, 0x29, 0x59, 0x5F, 0xFA, 0xCE, 0x83, 0xA5 },

	/* u */
	511,
	{ 0x4B, 0x87, 0x97, 0x1F, 0x27, 0xED, 0xAA, 0xAF,
	  0x42, 0xF4, 0x57, 0x82, 0x3F, 0xEC, 0x80, 0xED,
	  0x1E, 0x91, 0xF8, 0xB4, 0x33, 0xDA, 0xEF, 0xC3,
	  0x03, 0x53, 0x0F, 0xCE, 0xB9, 0x5F, 0xE4, 0x29,
	  0xCC, 0xEE, 0x6A, 0x5E, 0x11, 0x0E, 0xFA, 0x66,
	  0x85, 0xDC, 0xFC, 0x48, 0x31, 0x0C, 0x00, 0x97,
	  0xC6, 0x0A, 0xF2, 0x34, 0x60, 0x6B, 0xF7, 0x68,
	  0x09, 0x4E, 0xCF, 0xB1, 0x9E, 0x33, 0x9A, 0x41 },

	/* exponent1 */
	511,
	{ 0x6B, 0x2A, 0x0D, 0xF8, 0x22, 0x7A, 0x71, 0x8C,
	  0xE2, 0xD5, 0x9D, 0x1C, 0x91, 0xA4, 0x8F, 0x37,
	  0x0D, 0x5E, 0xF1, 0x26, 0x73, 0x4F, 0x78, 0x3F,
	  0x82, 0xD8, 0x8B, 0xFE, 0x8F, 0xBD, 0xDB, 0x7D,
	  0x1F, 0x4C, 0xB1, 0xB9, 0xA8, 0xD7, 0x88, 0x65,
	  0x3C, 0xC7, 0x24, 0x53, 0x95, 0x1E, 0x20, 0xC3,
	  0x94, 0x8E, 0x7F, 0x20, 0xCC, 0x2E, 0x88, 0x0E,
	  0x2F, 0x4A, 0xCB, 0xE3, 0xBD, 0x52, 0x02, 0xFB },

	/* exponent2 */
	509,
	{ 0x10, 0x27, 0xD3, 0xD2, 0x0E, 0x75, 0xE1, 0x17,
	  0xFA, 0xB2, 0x49, 0xA0, 0xEF, 0x07, 0x26, 0x85,
	  0xEC, 0x4D, 0xBF, 0x67, 0xFE, 0x5A, 0x25, 0x30,
	  0xDE, 0x28, 0x66, 0xB3, 0x06, 0xAE, 0x16, 0x55,
	  0xFF, 0x68, 0x00, 0xC7, 0xD8, 0x71, 0x7B, 0xEC,
	  0x84, 0xCB, 0xBD, 0x69, 0x0F, 0xFD, 0x97, 0xB9,
	  0xA1, 0x76, 0xD5, 0x64, 0xC6, 0x5A, 0xD7, 0x7C,
	  0x4B, 0xAE, 0xF4, 0xAD, 0x35, 0x63, 0x37, 0x71 }
	};

static BOOLEAN loadRSAKey( const CRYPT_DEVICE cryptDevice,
						   CRYPT_CONTEXT *cryptContext,
						   CRYPT_CONTEXT *decryptContext )
	{
	CRYPT_PKCINFO_RSA *rsaKey;
	const RSA_KEY *rsaKeyTemplate = &rsa1024Key;
	const BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;
	int status;

	/* Allocate room for the public-key components */
	if( ( rsaKey = ( CRYPT_PKCINFO_RSA * ) malloc( sizeof( CRYPT_PKCINFO_RSA ) ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );

	/* Create the encryption context */
	if( cryptContext != NULL )
		{
		if( isDevice )
			status = cryptDeviceCreateContext( cryptDevice, cryptContext,
											   CRYPT_ALGO_RSA );
		else
			status = cryptCreateContext( cryptContext, CRYPT_UNUSED,
										 CRYPT_ALGO_RSA );
		if( cryptStatusError( status ) )
			{
			printf( "crypt%sCreateContext() failed with error code %d.\n",
					isDevice ? "Device" : "", status );
			return( FALSE );
			}
		cryptSetAttributeString( *cryptContext, CRYPT_CTXINFO_LABEL,
								 "RSA public key", strlen( "RSA public key" ) );
		cryptInitComponents( rsaKey, CRYPT_KEYTYPE_PUBLIC );
		cryptSetComponent( rsaKey->n, rsaKeyTemplate->n, rsaKeyTemplate->nLen );
		cryptSetComponent( rsaKey->e, rsaKeyTemplate->e, rsaKeyTemplate->eLen );
		status = cryptSetAttributeString( *cryptContext,
										  CRYPT_CTXINFO_KEY_COMPONENTS, rsaKey,
										  sizeof( CRYPT_PKCINFO_RSA ) );
		cryptDestroyComponents( rsaKey );
		if( cryptStatusError( status ) )
			{
			printf( "Key load failed with error code %d.\n", status );
			return( FALSE );
			}
		if( decryptContext == NULL )
			{
			/* We're only using a public-key context, return */
			free( rsaKey );
			return( TRUE );
			}
		}

	/* Create the decryption context */
	if( isDevice )
		status = cryptDeviceCreateContext( cryptDevice, decryptContext,
										   CRYPT_ALGO_RSA );
	else
		status = cryptCreateContext( decryptContext, CRYPT_UNUSED,

⌨️ 快捷键说明

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