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

📄 envelope.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
	puts( "..." );

	/* Create the envelope, push in a password and the data, pop the
	   enveloped result, and destroy the envelope */
	if( !createEnvelope( &cryptEnvelope, formatType ) || \
		!addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,
						   TEXT( "Password" ),
						   paramStrlen( TEXT( "Password" ) ) ) )
		return( FALSE );
	if( useAltCipher )
		{
		CRYPT_CONTEXT sessionKeyContext;
		int status;

		/* Test enveloping with an IV-less stream cipher, which tests the
		   handling of algorithms that can't be used to wrap themselves in
		   the RecipientInfo */
		status = cryptCreateContext( &sessionKeyContext, CRYPT_UNUSED,
									 CRYPT_ALGO_RC4 );
		if( status == CRYPT_ERROR_NOTAVAIL )
			{
			puts( "Warning: Couldn't set non-default envelope cipher "
					"RC4, this may be disabled\n         in this build of "
					"cryptlib.\n" );
			destroyEnvelope( cryptEnvelope );
			return( TRUE );
			}
		if( cryptStatusOK( status ) )
			status = cryptGenerateKey( sessionKeyContext );
		if( cryptStatusOK( status ) )
			{
			status = cryptSetAttribute( cryptEnvelope,
										CRYPT_ENVINFO_SESSIONKEY,
										sessionKeyContext );
			cryptDestroyContext( sessionKeyContext );
			}
		if( cryptStatusError( status ) )
			{
			printf( "Couldn't set non-default envelope cipher, error code "
					"%d, line %d.\n", status, __LINE__ );
			return( FALSE );
			}
		}
	if( multiKeys && \
		( !addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,
							 TEXT( "Password1" ),
							 paramStrlen( TEXT( "Password1" ) ) ) || \
		  !addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,
							 TEXT( "Password2" ),
							 paramStrlen( TEXT( "Password2" ) ) ) || \
		  !addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,
							 TEXT( "Password3" ),
							 paramStrlen( TEXT( "Password3" ) ) ) ) )
		return( FALSE );
	if( useDatasize )
		cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,
						   ENVELOPE_TESTDATA_SIZE );
	count = pushData( cryptEnvelope, ENVELOPE_TESTDATA,
					  ENVELOPE_TESTDATA_SIZE, NULL, 0 );
	if( cryptStatusError( count ) )
		return( FALSE );
	count = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );
	if( cryptStatusError( count ) )
		return( FALSE );
	if( !destroyEnvelope( cryptEnvelope ) )
		return( FALSE );

	/* Tell them what happened */
	printf( "Enveloped data has size %d bytes.\n", count );
	debugDump( dumpFileName, globalBuffer, count );

	/* De-envelope the data and make sure that the result matches what we
	   pushed */
	count = envelopePasswordDecrypt( globalBuffer, count );
	if( count <= 0 )
		return( FALSE );
	if( count != ENVELOPE_TESTDATA_SIZE || \
		memcmp( globalBuffer, ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE ) )
		{
		puts( "De-enveloped data != original data." );
		return( FALSE );
		}

	/* Clean up */
	puts( "Enveloping of password-encrypted data succeeded.\n" );
	return( TRUE );
	}

int testEnvelopePasswordCrypt( void )
	{
	if( !envelopePasswordCrypt( "env_pasn", FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )
		return( FALSE );	/* Indefinite length */
	if( !envelopePasswordCrypt( "env_pas", TRUE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )
		return( FALSE );	/* Datasize */
	if( !envelopePasswordCrypt( "env_mpas", TRUE, FALSE, TRUE, CRYPT_FORMAT_CRYPTLIB ) )
		return( FALSE );	/* Datasize, multiple keys */
	if( !envelopePasswordCrypt( "env_pas.pgp", TRUE, FALSE, FALSE, CRYPT_FORMAT_PGP ) )
		return( FALSE );	/* PGP format */
	return( envelopePasswordCrypt( "env_pasr", TRUE, TRUE, FALSE, CRYPT_FORMAT_CRYPTLIB ) );
	}						/* IV-less cipher */

/* Test PKC-encrypted enveloping */

static int envelopePKCDecrypt( BYTE *buffer, const int length,
							   const KEYFILE_TYPE keyFileType,
							   const CRYPT_HANDLE externalCryptKeyset )
	{
	CRYPT_ENVELOPE cryptEnvelope;
	CRYPT_KEYSET cryptKeyset;
	const C_STR keysetName;
	const C_STR password;
	int count, status;

	assert( ( keyFileType != KEYFILE_NONE && \
			  externalCryptKeyset == CRYPT_UNUSED ) || \
			( keyFileType == KEYFILE_NONE && \
			  externalCryptKeyset != CRYPT_UNUSED ) );

	/* Create the envelope and push in the decryption keyset */
	if( !createDeenvelope( &cryptEnvelope ) )
		return( FALSE );
	if( keyFileType != KEYFILE_NONE )
		{
		keysetName = getKeyfileName( keyFileType, TRUE );
		password = getKeyfilePassword( keyFileType );
		status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, 
								  CRYPT_KEYSET_FILE, keysetName, 
								  CRYPT_KEYOPT_READONLY );
		if( cryptStatusError( status ) )
			return( FALSE );
		}
	else
		{
		cryptKeyset = externalCryptKeyset;
		password = NULL;
		}
	status = addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_KEYSET_DECRYPT, 
								cryptKeyset );
	if( keyFileType != KEYFILE_NONE )
		cryptKeysetClose( cryptKeyset );
	if( status <= 0 )
		return( FALSE );

	/* Push in the data */
	count = pushData( cryptEnvelope, buffer, length, password, 0 );
	if( cryptStatusError( count ) )
		return( FALSE );
	count = popData( cryptEnvelope, buffer, BUFFER_SIZE );
	if( cryptStatusError( count ) )
		return( FALSE );
	destroyEnvelope( cryptEnvelope );
	return( count );
	}

static int envelopePKCDecryptDirect( BYTE *buffer, const int length,
									 const KEYFILE_TYPE keyFileType )
	{
	CRYPT_ENVELOPE cryptEnvelope;
	CRYPT_CONTEXT cryptContext;
	int count, status;

	/* Create the envelope and get the decryption key */
	if( !createDeenvelope( &cryptEnvelope ) )
		return( FALSE );
	status = getPrivateKey( &cryptContext,
							getKeyfileName( keyFileType, TRUE ),
							getKeyfileUserID( keyFileType, TRUE ),
							getKeyfilePassword( keyFileType ) );
	if( cryptStatusError( status ) )
		return( FALSE );

	/* Push in the data */
	count = pushData( cryptEnvelope, buffer, length, NULL, cryptContext );
	cryptDestroyContext( cryptContext );
	if( cryptStatusError( count ) )
		return( FALSE );
	count = popData( cryptEnvelope, buffer, BUFFER_SIZE );
	if( cryptStatusError( count ) )
		return( FALSE );
	destroyEnvelope( cryptEnvelope );
	return( count );
	}

static int envelopePKCCrypt( const char *dumpFileName,
							 const BOOLEAN useDatasize,
							 const KEYFILE_TYPE keyFileType,
							 const BOOLEAN useRecipient,
							 const BOOLEAN useMultipleKeyex,
							 const BOOLEAN useAltAlgo,
							 const BOOLEAN useDirectKey,
							 const CRYPT_FORMAT_TYPE formatType,
							 const CRYPT_CONTEXT externalCryptContext,
							 const CRYPT_HANDLE externalCryptKeyset )
	{
	CRYPT_ENVELOPE cryptEnvelope;
	CRYPT_KEYSET cryptKeyset;
	CRYPT_HANDLE cryptKey;
	const C_STR keysetName = TEXT( "<None>" );
	const C_STR keyID = TEXT( "<None>" );
	int count, status;

	assert( ( keyFileType != KEYFILE_NONE && \
			  externalCryptContext == CRYPT_UNUSED && \
			  externalCryptKeyset == CRYPT_UNUSED ) || \
			( keyFileType == KEYFILE_NONE && \
			  externalCryptContext != CRYPT_UNUSED && \
			  externalCryptKeyset != CRYPT_UNUSED ) );

	if( !keyReadOK )
		{
		puts( "Couldn't find key files, skipping test of public-key "
			  "encrypted enveloping..." );
		return( TRUE );
		}
	if( keyFileType != KEYFILE_NONE )
		{
		/* When reading keys we have to explicitly use the first matching
		   key in the PGP 2.x keyring since the remaining keys are (for some
		   reason) stored unencrypted, and the keyring read code will
		   disallow the use of the key if it's stored in this manner */
		keysetName = getKeyfileName( keyFileType, FALSE );
		keyID = ( keyFileType == KEYFILE_PGP ) ? \
				TEXT( "test" ) : getKeyfileUserID( keyFileType, FALSE );
		}
	printf( "Testing %spublic-key encrypted enveloping",
			( formatType == CRYPT_FORMAT_PGP ) ? \
				( ( keyFileType == KEYFILE_PGP ) ? "PGP " : "OpenPGP " ) : "" );
	if( useDatasize && ( formatType != CRYPT_FORMAT_PGP ) && \
		!( useRecipient || useMultipleKeyex || useDirectKey ) )
		printf( " with datasize hint" );
	printf( " using " );
	printf( ( keyFileType == KEYFILE_PGP || \
			  keyFileType == KEYFILE_OPENPGP ) ? \
				( ( formatType == CRYPT_FORMAT_PGP ) ? \
					"PGP key" : "raw public key" ) : \
			  "X.509 cert" );
	if( useRecipient && !useAltAlgo )
		printf( " and recipient info" );
	if( useMultipleKeyex )
		printf( " and additional keying info" );
	if( useAltAlgo )
		printf( " and alt.encr.algo" );
	if( useDirectKey )
		printf( " and direct key add" );
	puts( "..." );

	/* If we're using OpenPGP keys we have to use a recipient rather than
	   adding the key directly because there's no way to tell in advance, when
	   reading a dual DSA/Elgamal key, which one is actually needed.  Since
	   the signing private key is the one which is usually needed in
	   standalone reads, a straight read will return the DSA rather than
	   Elgamal key.  It's only through the use of recipient info that the
	   (cryptlib-internal) code can specify a preference for an encryption
	   key */
	assert( ( keyFileType == KEYFILE_OPENPGP && useRecipient ) || \
			( keyFileType != KEYFILE_OPENPGP ) );

	/* Open the keyset and either get the public key the hard (to make sure
	   that this version works) or leave the keyset open to allow it to be
	   added to the envelope */
	if( keyFileType != KEYFILE_NONE )
		{
		status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, 
								  CRYPT_KEYSET_FILE, keysetName, 
								  CRYPT_KEYOPT_READONLY );
		if( cryptStatusError( status ) )
			{
			printf( "Couldn't open keyset '%s', status %d, line %d.\n", 
					keysetName, status, __LINE__ );
			return( FALSE );
			}
		if( !useRecipient )
			{
			status = cryptGetPublicKey( cryptKeyset, &cryptKey, 
										CRYPT_KEYID_NAME, keyID );
			cryptKeysetClose( cryptKeyset );
			if( cryptStatusError( status ) )
				{
				puts( "Read of public key from file keyset failed." );
				return( FALSE );
				}
			}
		}
	else
		{
		cryptKey = externalCryptContext;
		cryptKeyset = externalCryptKeyset;
		}

	/* Create the envelope, push in the recipient info or public key and data,
	   pop the enveloped result, and destroy the envelope */
	if( !createEnvelope( &cryptEnvelope, formatType ) )
		return( FALSE );
	if( useAltAlgo )
		{
		/* Specify the use of an alternative (non-default) bulk encryption
		   algorithm */
		if( !addEnvInfoNumeric( cryptEnvelope, CRYPT_OPTION_ENCR_ALGO,
								CRYPT_ALGO_BLOWFISH ) )
			return( FALSE );
		}
	if( useRecipient )
		{
		/* Add recipient information to the envelope.  Since we can't
		   guarantee for enveloping with cryptlib native key types that we
		   have a real public-key keyset available at this time (it's created
		   by a different part of the self-test code that may not have run
		   yet) we're actually reading the public key from the private-key
		   keyset.  Normally we couldn't do this, however since PKCS #15
		   doesn't store email addresses as key ID's (there's no need to),
		   the code will drop back to trying for a match on the key label.
		   Because of this we specify the private key label instead of a real
		   recipient email address.  Note that this trick only works because
		   of a coincidence of two or three factors and wouldn't normally be
		   used, it's only used here because we can't assume that a real
		   public-key keyset is available for use.

		   An additional test that would be useful is the ability to handle
		   multiple key exchange records, however the keyset kludge makes
		   this rather difficult.  Since the functionality is tested by the
		   use of multiple passwords in the conventional-encryption test
		   earlier on this isn't a major issue */
		if( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_KEYSET_ENCRYPT,
								cryptKeyset ) || \
			!addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_RECIPIENT,
							   keyID, paramStrlen( keyID ) ) )
			return( FALSE );
		cryptKeysetClose( cryptKeyset );
		}
	else
		{
		if( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_PUBLICKEY,
								cryptKey ) )
			return( FALSE );
		if( keyFileType != KEYFILE_NONE )
			cryptDestroyObject( cryptKey );
		}
	if( useMultipleKeyex && \
		!addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,
						   TEXT( "test" ), paramStrlen( TEXT( "test" ) ) ) )
		return( FALSE );
	if( useDatasize )
		cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,
						   ENVELOPE_TESTDATA_SIZE );
	count = pushData( cryptEnvelope, ENVELOPE_TESTDATA,
					  ENVELOPE_TESTDATA_SIZE, NULL, 0 );
	if( cryptStatusError( count ) )
		return( FALSE );
	count = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );
	if( cryptStatusError( count ) )
		return( FALSE );
	if( !destroyEnvelope( cryptEnvelope ) )
		return( FALSE );

	/* Tell them what happened */
	printf( "Enveloped data has size %d bytes.\n", count );
	debugDump( dumpFileName, globalBuffer, count );

	/* De-envelope the data and make sure that the result matches what we
	   pushed */
	if( useDirectKey )
		count = envelopePKCDecryptDirect( globalBuffer, count, keyFileType );
	else
		count = envelopePKCDecrypt( globalBuffer, count, keyFileType, externalCryptKeyset );
	if( count <= 0 )
		return( FALSE );
	if( count != ENVELOPE_TESTDATA_SIZE || \
		memcmp( globalBuffer, ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE ) )
		{
		puts( "De-enveloped data != original data." );
		return( FALSE );
		}

	/* Clean up */
	puts( "Enveloping of public-key encrypted data succeeded.\n" );
	return( TRUE );
	}

int testEnvelopePKCCrypt( void )
	{
	if( cryptQueryCapability( CRYPT_ALGO_IDEA, NULL ) == CRYPT_ERROR_NOTAVAIL )
		{
		puts( "Skipping raw public-key and PGP enveloping, which requires "
			  "the IDEA cipher to\nbe enabled.\n" );
		}
	else

⌨️ 快捷键说明

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