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

📄 certutil.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
		buffer[ length ] = '\0';
		printf( "  certificatePolicies.policyInformation.policyIdentifier = "
				"%s.\n", buffer );
		}
	status = cryptGetAttribute( certificate,
							CRYPT_CERTINFO_CRLDISTRIBUTIONPOINT, &value );
	if( cryptStatusOK( status ) && value && \
		cryptSetAttribute( certificate, CRYPT_CERTINFO_CRLDIST_FULLNAME,
						   CRYPT_UNUSED ) == CRYPT_OK )
		{
		puts( "  crlDistributionPoint is/are:" );
		CHK( cryptSetAttribute( certificate, CRYPT_CERTINFO_CURRENT_COMPONENT,
								CRYPT_CURSOR_FIRST ) );
		do
			{
			printDN( certificate );
			printAltName( certificate );
			}
		while( cryptSetAttribute( certificate, CRYPT_CERTINFO_CURRENT_COMPONENT,
								  CRYPT_CURSOR_NEXT ) == CRYPT_OK );
		}

	return( TRUE );
	}

int printCertChainInfo( const CRYPT_CERTIFICATE certChain )
	{
	int value, count, status;

	/* Make sure it really is a cert chain */
	CHK( cryptGetAttribute( certChain, CRYPT_CERTINFO_CERTTYPE, &value ) );
	if( value != CRYPT_CERTTYPE_CERTCHAIN )
		{
		printCertInfo( certChain );
		return( TRUE );
		}

	/* Display info on each cert in the chain.  This uses the cursor
	   mechanism to select successive certs in the chain from the leaf up to
	   the root */
	count = 0;
	CHK( cryptSetAttribute( certChain, CRYPT_CERTINFO_CURRENT_CERTIFICATE,
							CRYPT_CURSOR_FIRST ) );
	do
		{
		printf( "Certificate %d\n-------------\n", count++ );
		printCertInfo( certChain );
		putchar( '\n' );
		}
	while( cryptSetAttribute( certChain,
			CRYPT_CERTINFO_CURRENT_CERTIFICATE, CRYPT_CURSOR_NEXT ) == CRYPT_OK );

	return( TRUE );
	}

/****************************************************************************
*																			*
*								Standalone main()							*
*																			*
****************************************************************************/

#ifdef STANDALONE_PROGRAM

/* Windoze defines ERROR_FILE_EXISTS somewhere even though it's not
   documented */

#undef ERROR_FILE_EXISTS

/* Error codes.  cryptlib return codes are converted to a positive value
   (some OS's don't like negative status codes), application-specific codes
   unrelated to cryptlib are given below */

#define ERROR_BADARG		500		/* Bad argument */
#define ERROR_FILE_EXISTS	501		/* Output file already exists */
#define ERROR_FILE_INPUT	502		/* Error opening input file */
#define ERROR_FILE_OUTPUT	503		/* Error opening/creating output file */

/* Stucture to store DN components passed in by the caller */

typedef struct {
	const CRYPT_CERTINFO_TYPE type;
	const char *name;
	char *value;
	} DN_INFO;

/* Check whether a file already exists */

static int checkFileExists( const char *fileName,
							const BOOLEAN overwriteFile )
	{
	FILE *filePtr;

	/* Make sure the output file doesn't already exist */
	if( fileName == NULL || ( filePtr = fopen( fileName, "rb" ) ) == NULL )
		return( CRYPT_OK );
	fclose( filePtr );
	if( !overwriteFile )
		{
		printf( "Output file %s already exists.\n", fileName );
		return( ERROR_FILE_EXISTS );
		}
	return( CRYPT_OK );
	}

/* Break up a DN into its components */

static int parseDN( DN_INFO *dnInfo, char *dn )
	{
	char *dnPtr = dn;

	while( *dnPtr )
		{
		int i;

		/* Find the info on the current DN component */
		for( i = 0; dnInfo[ i ].type != SENTINEL; i++ )
			if( !strnicmp( dnPtr, dnInfo[ i ].name,
						   strlen( dnInfo[ i ].name ) ) )
				break;
		if( dnInfo[ i ].type == SENTINEL )
			{
			printf( "Bad DN format '%s'.\n", dn );
			return( ERROR_BADARG );
			}
		if( dnInfo[ i ].value != NULL )
			{
			printf( "Duplicate component in DN '%s'.\n", dn );
			return( ERROR_BADARG );
			}
		dnPtr += strlen( dnInfo[ i ].name );
		if( *dnPtr++ != '=' )
			{
			printf( "Missing '=' in DN '%s'.\n", dn );
			return( ERROR_BADARG );
			}

		dnInfo[ i ].value = dnPtr;
		for( i = 0; dnPtr[ i ] != ',' && dnPtr[ i ]; i++ );
		if( dnPtr[ i ] )
			{
			/* There's more to follow, add a terminator and point to the rest
			   of the string */
			dnPtr[ i ] = '\0';
			dnPtr++;
			}
		dnPtr += i;
		}

	return( CRYPT_OK );
	}

/* Generate a new key + cert request/self-signed cert */

static int generateKey( const char *keysetName, const char *password,
						const char *label, const DN_INFO *dnInfo,
						const BOOLEAN createSelfSigned )
	{
	CRYPT_KEYSET cryptKeyset;
	CRYPT_CERTIFICATE cryptCert;
	CRYPT_CONTEXT cryptContext;
	const char *keyLabel = ( label == NULL ) ? "Private key" : label;
	int status;

	/* Create a new RSA key */
	cryptCreateContext( &cryptContext, CRYPT_ALGO_RSA, CRYPT_MODE_PKC );
	cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL, keyLabel,
							 strlen( keyLabel ) );
	status = cryptGenerateKey( cryptContext );
	if( cryptStatusError( status ) )
		{
		cryptDestroyContext( cryptContext );
		printf( "Key generation failed with error %d.\n", status );
		return( status );
		}

	/* Write the key to the file keyset */
	status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
							  keysetName, CRYPT_KEYOPT_CREATE );
	if( cryptStatusOK( status ) )
		{
		status = cryptAddPrivateKey( cryptKeyset, cryptContext, password );
		cryptKeysetClose( cryptKeyset );
		}
	if( cryptStatusError( status ) )
		{
		cryptDestroyContext( cryptContext );
		printf( "Private keyset save failed with error code %d.\n", status );
		return( status );
		}

	/* Create the certification request/certificate */
	cryptCreateCert( &cryptCert, createSelfSigned ? \
					 CRYPT_CERTTYPE_CERTIFICATE : CRYPT_CERTTYPE_CERTREQUEST );
	status = cryptSetAttribute( cryptCert,
					CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
	if( cryptStatusOK( status ) )
		{
		int i;

		/* Add each of the DN components */
		for( i = 0; dnInfo[ i ].type != SENTINEL; i++ )
			if( dnInfo[ i ].value != NULL )
				{
				status = cryptSetAttributeString( cryptCert, dnInfo[ i ].type,
							dnInfo[ i ].value, strlen( dnInfo[ i ].value ) );
				if( cryptStatusError( status ) )
					break;
				}
		}
	if( cryptStatusOK( status ) && createSelfSigned )
		{
		/* Make it a self-signed CA cert */
		status = cryptSetAttribute( cryptCert,
					CRYPT_CERTINFO_SELFSIGNED, TRUE );
		if( cryptStatusOK( status ) )
			status = cryptSetAttribute( cryptCert,
					CRYPT_CERTINFO_KEYUSAGE,
					CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN );
		if( cryptStatusOK( status ) )
			status = cryptSetAttribute( cryptCert,
					CRYPT_CERTINFO_CA, TRUE );
		}
	if( cryptStatusOK( status ) )
		status = cryptSignCert( cryptCert, cryptContext );
	cryptDestroyContext( cryptContext );
	if( cryptStatusError( status ) )
		{
		printf( "Certificate creation failed with error code %d.\n",
				status );
		printCertErrorInfo( cryptCert );
		cryptDestroyCert( cryptCert );
		return( status );
		}

	/* Update the private key keyset with the cert request/certificate */
	status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
							  keysetName, CRYPT_KEYOPT_NONE );
	if( cryptStatusOK( status ) )
		{
		status = cryptGetPrivateKey( cryptKeyset, NULL, CRYPT_KEYID_NONE,
									 NULL, password );
		if( cryptStatusOK( status ) )
			status = cryptAddPrivateKey( cryptKeyset, cryptCert, NULL );
		cryptKeysetClose( cryptKeyset );
		}

	/* Clean up */
	cryptDestroyCert( cryptCert );
	if( cryptStatusError( status ) )
		printf( "Private key update failed with error code %d.\n", status );
	return( status );
	}

/* Create a certificate from a cert request */

static int createCertificate( CRYPT_CERTIFICATE *certificate,
							  const CRYPT_CERTTYPE_TYPE certType,
							  const CRYPT_CERTIFICATE certRequest,
							  const CRYPT_CONTEXT caKeyContext )
	{
	int status;

	/* Verify the certification request */
	status = cryptCheckCert( certRequest, CRYPT_UNUSED );
	if( cryptStatusError( status ) )
		return( status );

	/* Create the certificate */
	status = cryptCreateCert( certificate, certType );
	if( cryptStatusError( status ) )
		return( status );
	status = cryptSetAttribute( *certificate,
					CRYPT_CERTINFO_CERTREQUEST, certRequest );
	if( cryptStatusOK( status ) )
		status = cryptSignCert( *certificate, caKeyContext );

	return( status );
	}

/* Display the help info */

static void showHelp( void )
	{
	puts( "Usage: certutil -d<DN> -v -k{s} -s{c} -o -f<private key> -l<key label>" );
	puts( "                -p<password> <infile> <outfile>" );
	puts( "       -k = generate new key and create cert request" );
	puts( "       -ks = create self-signed CA root instead of cert request" );
	puts( "       -s = sign a cert request and create cert" );
	puts( "       -sc = create cert chain instead of cert" );
	puts( "       -u = update a private key with a cert object" );
	puts( "       -v = view/check cert object" );
	puts( "       -x = extract cert object from private key" );
	puts( "" );
	puts( "       -d = specify DN (components = C, SP, L, O, OU, CN, Email, URI)" );
	puts( "       -f = specify private key file" );
	puts( "       -o = overwrite output file" );
	puts( "       -p = specify password" );
	puts( "" );
	puts( "Examples:" );
	puts( "certutil -k -l\"My key\" keyfile         - Generate private key + cert.request" );
	puts( "certutil -k -d\"C=US,O=Foo Corp,CN=John Doe,Email=doe@foo.com\" keyfile   - DN" );
	puts( "certutil -ks keyfile            - Generate private key + self-signed CA cert" );
	puts( "certutil -s -pcakey infile outfile                       - Sign cert request" );
	puts( "certutil -u -puserkey infile  - Update users private key with cert in infile" );
	puts( "certutil -x -pkeyfile outfile      - Extract certificate object from keyfile" );
	puts( "certutil -v infile             - Display certificate object(s), verify sigs." );
	puts( "" );
	puts( "Long example: Create self-signed CA root, certify a cert.request:" );
	puts( "certutil -ks -l\"CA key\" -d<DN> cakey - Generate CA key + self-signed CA root" );
	puts( "certutil -k -l\"User key\" -d<DN> userkey - Generate user key and cert request" );
	puts( "certutil -x -puserkey certreq           - Extract cert request from user key" );
	puts( "certutil -s -pcakey certreq cert            - Sign cert request with CA root" );
	puts( "certutil -u -puserkey cert                   - Update user key with new cert" );
	}

/* The main program.  If we're not calling this from a test wrapper, use it
   as our main() */

#ifndef WRAP_STANDALONE
  #define wrappedMain	main
#endif /* WRAP_STANDALONE */

int wrappedMain( int argc, char **argv )
	{
	CRYPT_CERTIFICATE certificate;
	DN_INFO dnInfo[] = {
		{ CRYPT_CERTINFO_COMMONNAME, "CN", NULL },
		{ CRYPT_CERTINFO_COUNTRYNAME, "C", NULL },
		{ CRYPT_CERTINFO_RFC822NAME, "Email", NULL },
		{ CRYPT_CERTINFO_LOCALITYNAME, "L", NULL },
		{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, "OU", NULL },
		{ CRYPT_CERTINFO_ORGANIZATIONNAME, "O", NULL },
		{ CRYPT_CERTINFO_STATEORPROVINCENAME, "SP", NULL },
		{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, "URI", NULL },
		{ SENTINEL, NULL, NULL }
		};
	char *keyFileName = NULL, *password = NULL, *label = NULL;
	char dnBuffer[ CRYPT_MAX_TEXTSIZE * 8 ];
	BOOLEAN doView = FALSE, doExtract = FALSE, doOverwriteOutput = FALSE;
	BOOLEAN doSign = FALSE, doUpdate = FALSE, doKeygen = FALSE;
	BOOLEAN optionFlag = FALSE;
	int status;

	/* Process the input parameters */
	puts( "Certificate utility for cryptlib 3.0beta.  Copyright Peter Gutmann 1998, 1999." );
	puts( "Warning: This is a debugging tool, not a user program!" );
	puts( "" );
	if( argc < 3 )
		{
		showHelp();
		return( ERROR_BADARG );
		}

	/* VisualAge C++ doesn't set the TZ correctly */
#if defined( __IBMC__ ) || defined( __IBMCPP__ )
	tzset();
#endif /* VisualAge C++ */

	/* Initialise cryptlib */
	status = cryptInit();
	if( cryptStatusError( status ) )
		{
		printf( "cryptlib initialisation failed with error code %d.\n",
				status );
		return( -status );
		}
	atexit( (void(*)(void)) cryptEnd );		/* Auto cleanup on exit */

	/* Check for arguments */
	while( argc > 1 && *argv[ 1 ] == '-' )
		{
		char *argPtr = argv[ 1 ] + 1;

		while( *argPtr )
			{
			switch( toupper( *argPtr ) )
				{
				case 'D':
					argPtr++;
					if( strlen( argPtr ) > CRYPT_MAX_TEXTSIZE * 8 )
						{
						puts( "DN too long" );

⌨️ 快捷键说明

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