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

📄 certutil.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
		}
	if( certType == CRYPT_CERTTYPE_CMS_ATTRIBUTES )
		{
		time_t signingTime;

		status = cryptGetAttributeString( certificate,
										  CRYPT_CERTINFO_CMS_SIGNINGTIME,
										  &signingTime, &length );
		if( cryptStatusOK( status ) )
			printf( "Signing time %s", ctime( &signingTime ) );
		return( TRUE );
		}
	if( certType == CRYPT_CERTTYPE_PKIUSER )
		{
		CHK( cryptGetAttributeString( certificate, CRYPT_CERTINFO_PKIUSER_ID,
									  buffer, &length ) );
		buffer[ length ] ='\0';
		printf( "  PKI user ID = %s.\n", buffer );
		CHK( cryptGetAttributeString( certificate,
									  CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD,
									  buffer, &length ) );
		buffer[ length ] ='\0';
		printf( "  PKI user issue password = %s.\n", buffer );
		CHK( cryptGetAttributeString( certificate,
									  CRYPT_CERTINFO_PKIUSER_REVPASSWORD,
									  buffer, &length ) );
		buffer[ length ] ='\0';
		printf( "  PKI user revocation password = %s.\n", buffer );
		return( TRUE );
		}
	status = cryptGetAttribute( certificate,
								CRYPT_CERTINFO_KEYUSAGE, &value );
	if( cryptStatusOK( status ) && value )
		printf( "  keyUsage = %02X.\n", value );
	status = cryptGetAttribute( certificate,
								CRYPT_CERTINFO_EXTKEYUSAGE, &value );
	if( cryptStatusOK( status ) && value )
		{
		BOOLEAN firstTime = TRUE;

		printf( "  extKeyUsage types = " );
		CHK( cryptSetAttribute( certificate, CRYPT_CERTINFO_CURRENT_EXTENSION,
								CRYPT_CERTINFO_EXTKEYUSAGE ) );
		do
			{
			CHK( cryptGetAttribute( certificate, CRYPT_CERTINFO_CURRENT_FIELD,
									&value ) );
			printf( "%s%d", firstTime ? "" : ", ", value );
			firstTime = FALSE;
			}
		while( cryptSetAttribute( certificate, CRYPT_CERTINFO_CURRENT_FIELD,
								  CRYPT_CURSOR_NEXT ) == CRYPT_OK );
		printf( ".\n" );
		}
	status = cryptGetAttribute( certificate, CRYPT_CERTINFO_CA, &value );
	if( cryptStatusOK( status ) && value )
		printf( "  basicConstraints.cA = %s.\n", value ? "True" : "False" );
	status = cryptGetAttribute( certificate, CRYPT_CERTINFO_PATHLENCONSTRAINT,
								&value );
	if( cryptStatusOK( status ) && value )
		printf( "  basicConstraints.pathLenConstraint = %d.\n", value );
	status = cryptGetAttributeString( certificate,
							CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER, buffer, &length );
	if( cryptStatusOK( status ) )
		{
		printf( "  subjectKeyIdentifier = " );
		printHex( buffer, length );
		}
	status = cryptGetAttributeString( certificate,
							CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER, buffer, &length );
	if( cryptStatusOK( status ) )
		{
		printf( "  authorityKeyIdentifier = " );
		printHex( buffer, length );
		}
	status = cryptGetAttributeString( certificate,
							CRYPT_CERTINFO_CERTPOLICYID, buffer, &length );
	if( cryptStatusOK( status ) )
		{
		buffer[ length ] = '\0';
		printf( "  certificatePolicies.policyInformation.policyIdentifier = "
				"%s.\n", buffer );
		status = cryptGetAttributeString( certificate,
							CRYPT_CERTINFO_CERTPOLICY_CPSURI, buffer, &length );
		if( cryptStatusOK( status ) )
			{
			buffer[ length ] = '\0';
			printf( "  certificatePolicies.policyInformation.cpsURI = "
					"%s.\n", buffer );
			}
		status = cryptGetAttributeString( certificate,
							CRYPT_CERTINFO_CERTPOLICY_ORGANIZATION, buffer, &length );
		if( cryptStatusOK( status ) )
			{
			buffer[ length ] = '\0';
			printf( "  certificatePolicies.policyInformation.organisation = "
					"%s.\n", buffer );
			}
		status = cryptGetAttributeString( certificate,
							CRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT, buffer, &length );
		if( cryptStatusOK( status ) )
			{
			buffer[ length ] = '\0';
			printf( "  certificatePolicies.policyInformation.explicitText = "
					"%s.\n", buffer );
			}
		}
	if( cryptStatusOK( \
			cryptGetAttribute( certificate, 
							   CRYPT_CERTINFO_CRLDIST_FULLNAME, &value ) ) )
		{
		CHK( cryptSetAttribute( certificate, CRYPT_CERTINFO_CURRENT_FIELD,
								CRYPT_CERTINFO_CRLDIST_FULLNAME ) );
		puts( "  crlDistributionPoint is/are:" );
		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_ATTRIBUTE_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_UNUSED, CRYPT_ALGO_RSA );
	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, CRYPT_UNUSED, 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 );
		printErrorAttributeInfo( 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, CRYPT_UNUSED, 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 },

⌨️ 快捷键说明

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