📄 highlvl.c
字号:
int testKeygen( void )
{
if( !keygen( CRYPT_ALGO_RSA, "RSA" ) )
return( FALSE );
if( !keygen( CRYPT_ALGO_DSA, "DSA" ) )
return( FALSE );
if( !keygen( CRYPT_ALGO_ELGAMAL, "Elgamal" ) )
return( FALSE );
if( !keygen( CRYPT_ALGO_DH, "DH" ) )
return( FALSE );
printf( "\n" );
return( TRUE );
}
int testKeygenAsync( void )
{
#if !defined( UNIX_THREADS ) && !defined( WINDOWS_THREADS ) && \
!defined( OS2_THREADS )
return( TRUE );
#else
CRYPT_CONTEXT cryptContext, hashContext;
BYTE hashBuffer[] = "abcdefghijklmnopqrstuvwxyz";
BYTE buffer[ BUFFER_SIZE ];
int cancelCount = 0, length, status;
puts( "Testing asynchronous key generation..." );
/* Create an encryption context and generate a longish (3K bit) key
into it. This ensures that we can see the async operation in
action, anything smaller and it's done almost immediately (note
that this may cause problems with some external implementations
that cap the keysize at 2K bits) */
cryptCreateContext( &cryptContext, CRYPT_UNUSED, CRYPT_ALGO_RSA );
cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,
TEXT( "Private key" ),
paramStrlen( TEXT( "Private key" ) ) );
cryptSetAttribute( cryptContext, CRYPT_CTXINFO_KEYSIZE, 384 );
status = cryptGenerateKeyAsync( cryptContext );
if( cryptStatusError( status ) )
{
printf( "cryptGenerateKeyAsync() failed with error code %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
/* Hang around a bit to allow things to start. This value is a bit of a
difficult quantity to get right since VC++ can spend longer than the
startup time thrashing the drive doing nothing so it has to be high,
but on faster PC's even a 3K bit key can be generated in a few
seconds, so it can't be too high or the keygen will have finished.
The following value was safe for a 700MHz PIII, but the next step
would be to move to 4K bit keys (4096 bits, 512 in the above keygen
call). For the Unix version it's also going to cause problems on
the faster systems */
printf( "Delaying 2s to allow keygen to start..." );
delayThread( 2 );
puts( "done." );
/* Check that the async keygen is still in progress */
status = cryptAsyncQuery( cryptContext );
if( status == CRYPT_ERROR_TIMEOUT )
puts( "Async keygen in progress." );
else
{
/* If the machine's really fast, the keygen could have completed
already */
if( status == CRYPT_OK )
{
printf( "The async keygen has completed before the rest of the "
"test code could run.\nTo fix this, either decrease "
"the startup delay on line %d\nof " __FILE__ " or "
"increase the size of the key being generated to slow\n"
"down the generation process.\n\n", __LINE__ - 15 );
cryptDestroyContext( cryptContext );
return( TRUE );
}
printf( "Async keygen failed with error code %d, line %d.\n", status,
__LINE__ );
return( FALSE );
}
/* Cancel the async keygen */
status = cryptAsyncCancel( cryptContext );
if( cryptStatusError( status ) )
{
printf( "cryptAsyncCancel() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
printf( "Cancelling async operation..." );
while( cryptAsyncQuery( cryptContext ) == CRYPT_ERROR_TIMEOUT )
{
cancelCount++;
printf( "*" );
delayThread( 1 );
}
puts( "...done." );
/* Check the context to make sure the keygen was actually cancelled */
cryptCreateContext( &hashContext, CRYPT_UNUSED, CRYPT_ALGO_SHA );
cryptEncrypt( hashContext, hashBuffer, 26 );
cryptEncrypt( hashContext, hashBuffer, 0 );
status = cryptCreateSignature( buffer, BUFFER_SIZE, &length,
cryptContext, hashContext );
if( cryptStatusOK( status ) )
{
/* We have to be a bit careful here to try and eliminate false
positives due to fast CPUs. As a rule of thumb, it shouldn't
take more than 1s for a cancel to propagate through the system.
On the other hand we can also run into problems with very slow
CPUs that take so long to get started that the cancel never
arrives, to handle the entire spectrum of system types we just
print a warning but don't abort if there's a problem */
if( cancelCount <= 1 )
puts( "The async keygen completed even though the operation was "
"cancelled. This was\nprobably because the CPU was fast "
"enough that the keygen completed before the\ncancel could "
"take effect." );
else
puts( "The async keygen completed even though the operation was "
"cancelled. The\ncancel should have stopped the keygen from "
"completing.\n" );
}
/* Clean up */
cryptDestroyContext( cryptContext );
cryptDestroyContext( hashContext );
puts( "Asynchronous key generation succeeded.\n" );
return( TRUE );
#endif /* Systems with threading support */
}
/****************************************************************************
* *
* High-level Routines Test *
* *
****************************************************************************/
/* Test the code to export/import a CMS key */
int testKeyExportImportCMS( void )
{
CRYPT_OBJECT_INFO cryptObjectInfo;
CRYPT_KEYSET cryptKeyset;
CRYPT_CONTEXT cryptContext;
CRYPT_CONTEXT sessionKeyContext1, sessionKeyContext2;
BYTE *buffer;
int status, length;
puts( "Testing CMS public-key export/import..." );
/* Get a private key with a cert chain attached */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
USER_PRIVKEY_FILE, CRYPT_KEYOPT_READONLY );
if( cryptStatusOK( status ) )
{
status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
CRYPT_KEYID_NAME, USER_PRIVKEY_LABEL,
TEST_PRIVKEY_PASSWORD );
cryptKeysetClose( cryptKeyset );
}
if( cryptStatusError( status ) )
{
printf( "Couldn't read private key, status %d, line %d.\n", status,
__LINE__ );
return( FALSE );
}
/* Create triple-DES encryption contexts for the exported and imported
session keys */
cryptCreateContext( &sessionKeyContext1, CRYPT_UNUSED, CRYPT_ALGO_3DES );
cryptGenerateKey( sessionKeyContext1 );
cryptCreateContext( &sessionKeyContext2, CRYPT_UNUSED, CRYPT_ALGO_3DES );
/* Find out how big the exported key will be */
status = cryptExportKeyEx( NULL, 0, &length, CRYPT_FORMAT_SMIME,
cryptContext, sessionKeyContext1 );
if( cryptStatusError( status ) )
{
printf( "cryptExportKeyEx() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
printf( "cryptExportKeyEx() reports CMS exported key will be %d bytes "
"long\n", length );
if( ( buffer = malloc( length ) ) == NULL )
return( FALSE );
/* Export the key */
status = cryptExportKeyEx( buffer, length, &length, CRYPT_FORMAT_SMIME,
cryptContext, sessionKeyContext1 );
if( cryptStatusError( status ) )
{
printf( "cryptExportKeyEx() failed with error code %d, line %d.\n",
status, __LINE__ );
free( buffer );
return( FALSE );
}
/* Query the encrypted key object */
status = cryptQueryObject( buffer, length, &cryptObjectInfo );
if( cryptStatusError( status ) )
{
printf( "cryptQueryObject() failed with error code %d, line %d.\n",
status, __LINE__ );
free( buffer );
return( FALSE );
}
printf( "cryptQueryObject() reports object type %d, algorithm %d, mode "
"%d.\n", cryptObjectInfo.objectType, cryptObjectInfo.cryptAlgo,
cryptObjectInfo.cryptMode );
memset( &cryptObjectInfo, 0, sizeof( CRYPT_OBJECT_INFO ) );
debugDump( "cms_ri", buffer, length );
/* Import the encrypted key and load it into the session key context */
status = cryptImportKey( buffer, length, cryptContext,
sessionKeyContext2 );
if( cryptStatusError( status ) )
{
printf( "cryptImportKey() failed with error code %d, line %d.\n",
status, __LINE__ );
free( buffer );
return( FALSE );
}
/* Make sure the two keys match */
if( !compareSessionKeys( sessionKeyContext1, sessionKeyContext2 ) )
return( FALSE );
/* Clean up */
destroyContexts( CRYPT_UNUSED, sessionKeyContext1, sessionKeyContext2 );
cryptDestroyContext( cryptContext );
puts( "Export/import of CMS session key succeeded.\n" );
free( buffer );
return( TRUE );
}
/* Test the code to create an CMS signature */
static const CERT_DATA cmsAttributeData[] = {
/* Content type */
{ CRYPT_CERTINFO_CMS_CONTENTTYPE, IS_NUMERIC, CRYPT_CONTENT_SPCINDIRECTDATACONTEXT },
/* Odds and ends. We can't (portably) set the opusInfo name since it's
a Unicode string, so we only add this one under Windows */
#ifdef __WINDOWS__
{ CRYPT_CERTINFO_CMS_SPCOPUSINFO_NAME, IS_WCSTRING, 0, L"Program v3.0 SP2" },
#endif /* __WINDOWS__ */
{ CRYPT_CERTINFO_CMS_SPCOPUSINFO_URL, IS_STRING, 0, TEXT( "http://bugs-r-us.com" ) },
{ CRYPT_CERTINFO_CMS_SPCSTMT_COMMERCIALCODESIGNING, IS_NUMERIC, CRYPT_UNUSED },
{ CRYPT_ATTRIBUTE_NONE, IS_VOID }
};
static int signDataCMS( const char *description,
const CRYPT_CERTIFICATE signingAttributes )
{
CRYPT_KEYSET cryptKeyset;
CRYPT_CERTIFICATE cmsAttributes = signingAttributes;
CRYPT_CONTEXT signContext, hashContext;
BYTE *buffer, hashBuffer[] = "abcdefghijklmnopqrstuvwxyz";
int status, length;
printf( "Testing %s...\n", description );
/* Create an SHA hash context and hash the test buffer */
cryptCreateContext( &hashContext, CRYPT_UNUSED, CRYPT_ALGO_SHA );
cryptEncrypt( hashContext, hashBuffer, 26 );
cryptEncrypt( hashContext, hashBuffer, 0 );
/* Get a private key with a cert chain attached */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
USER_PRIVKEY_FILE, CRYPT_KEYOPT_READONLY );
if( cryptStatusOK( status ) )
{
status = cryptGetPrivateKey( cryptKeyset, &signContext,
CRYPT_KEYID_NAME, USER_PRIVKEY_LABEL,
TEST_PRIVKEY_PASSWORD );
cryptKeysetClose( cryptKeyset );
}
if( cryptStatusError( status ) )
{
printf( "Couldn't read private key, status %d, line %d.\n", status,
__LINE__ );
return( FALSE );
}
/* Find out how big the signature will be */
status = cryptCreateSignatureEx( NULL, 0, &length, CRYPT_FORMAT_SMIME,
signContext, hashContext, cmsAttributes );
if( cryptStatusError( status ) )
{
printf( "cryptCreateSignatureEx() failed with error code %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
printf( "cryptCreateSignatureEx() reports CMS signature will be %d "
"bytes long\n", length );
if( ( buffer = malloc( length ) ) == NULL )
return( FALSE );
/* Sign the hashed data */
status = cryptCreateSignatureEx( buffer, length, &length,
CRYPT_FORMAT_SMIME, signContext,
hashContext, cmsAttributes );
if( cryptStatusError( status ) )
{
printf( "cryptCreateSignatureEx() failed with error code %d, line "
"%d.\n", status, __LINE__ );
free( buffer );
return( FALSE );
}
debugDump( ( signingAttributes == CRYPT_USE_DEFAULT ) ? \
"cms_sigd" : "cms_sig", buffer, length );
/* Check the signature on the hash */
status = cryptCheckSignatureEx( buffer, length, signContext, hashContext,
( cmsAttributes == CRYPT_USE_DEFAULT ) ? NULL : &cmsAttributes );
if( cryptStatusError( status ) )
{
printf( "cryptCheckSignatureEx() failed with error code %d, line "
"%d.\n", status, __LINE__ );
free( buffer );
return( FALSE );
}
/* Display the signing attributes */
if( cmsAttributes != CRYPT_USE_DEFAULT )
printCertInfo( cmsAttributes );
/* Clean up */
cryptDestroyContext( hashContext );
cryptDestroyContext( signContext );
cryptDestroyCert( cmsAttributes );
printf( "Generation and checking of %s succeeded.\n\n", description );
free( buffer );
return( TRUE );
}
int testSignDataCMS( void )
{
CRYPT_CERTIFICATE cmsAttributes;
int status;
/* First test the basic CMS signature with default attributes (content
type, signing time, and message digest) */
if( !signDataCMS( "CMS signature", CRYPT_USE_DEFAULT ) )
return( FALSE );
/* Create some CMS attributes and sign the data with the user-defined
attributes */
status = cryptCreateCert( &cmsAttributes, CRYPT_UNUSED,
CRYPT_CERTTYPE_CMS_ATTRIBUTES );
if( cryptStatusError( status ) || \
!addCertFields( cmsAttributes, cmsAttributeData ) )
return( FALSE );
status = signDataCMS( "complex CMS signature", cmsAttributes );
cryptDestroyCert( cmsAttributes );
return( status );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -