📄 certutil.c
字号:
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 + -