Create a Computer Request Including DNS Subject Alternative Name
Applies To: Windows Server 2008
This example demonstrates how to create a computer certificate request that includes the computer Domain Name System (DNS) Name in the Subject Alternative Name extension. If the request is created from the computer context (for example, running as local system), the request should be initialized using ContextMachine. If the request is created from a user account (for example, running as Administrator), the request should be initialized using ContextAdministratorForceMachine.
The requirements for subject name and subject alternative name are dependent on the configuration of certificate templates.
Certificate templates can be configured to enable the subject name to be set automatically by a certification authority (CA) based on the authenticated requester’s Active Directory account. If a certificate template is configured to build the subject name based on Active Directory, values for subject name and subject alternative name should be omitted from the certificate request. If a value is provided, it will not be used.
Certificate templates can also be configured to require that a value for subject name or subject alternative name is included in the certificate request. If a certificate template is configured to require a value for subject name or subject alternative name, a value must be included in the certificate request.
For additional information about configuring certificate templates, see Administering Certificate Templates (https://go.microsoft.com/fwlink/?LinkId=178068).
C#:
CX509CertificateRequestPkcs10Class request = new CX509CertificateRequestPkcs10Class();
request.Initialize( X509CertificateEnrollmentContext.ContextAdministratorForceMachine);
// Build the request altname.
CAlternativeNameClass altname = new CAlternativeNameClass();
altname.InitializeFromString( AlternativeNameType.XCN_CERT_ALT_NAME_DNS_NAME, DNSName);
CAlternativeNamesClass altnames = new CAlternativeNamesClass();
altnames.Add(altname);
CX509ExtensionAlternativeNamesClass altnameext = new CX509ExtensionAlternativeNamesClass();
altnameext.InitializeEncode(altnames);
request.X509Extensions.Add((CX509Extension)altnameext);
request.PrivateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE;
request.PrivateKey.ProviderName = myProvider;
CObjectId algobj = new CObjectId();
algobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_ANY_GROUP_ID, ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY, AlgorithmFlags.AlgorithmFlagsNone, "ECDSA_P521");
request.PrivateKey.Algorithm = algobj;
CObjectId hashobj = new CObjectId();
hashobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID, ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY, AlgorithmFlags.AlgorithmFlagsNone, "SHA256");
request.HashAlgorithm = hashobj;
request.Encode();
C++:
BSTR alg = SysAllocString(L"ECDSA_P521");
BSTR hashAlg = SysAllocString(L"SHA256");
IX509CertificateRequestPkcs10* request = NULL;
IObjectId* Algorithm = NULL;
IObjectId* HashObj = NULL;
IAlternativeName* altname = NULL;
IAlternativeNames* altnames = NULL;
IX509ExtensionAlternativeNames* altnameext = NULL;
IX509Extensions* exts = NULL;
IX509PrivateKey *pKey = NULL;
HRESULT hr = S_OK;
hr = CoCreateInstance(
__uuidof(CX509CertificateRequestPkcs10),
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
__uuidof(IX509CertificateRequestPkcs10),
(void **) &request);
_JumpIfError(hr, error, _T("CoCreateInstance CX509CertificateRequestPkcs10"));
hr = request->Initialize( ContextAdministratorForceMachine );
_JumpIfError(hr, error, _T("request->Initialize"));
// Build the request altname.
hr = CoCreateInstance(
__uuidof(CAlternativeName),
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
__uuidof(IAlternativeName),
(void **) &altname);
_JumpIfError(hr, error, _T("CoCreateInstance CAlternativeName"));
hr = altname->InitializeFromString( XCN_CERT_ALT_NAME_DNS_NAME, DNSName);
_JumpIfError(hr, error, _T("altname->InitializeFromString"));
hr = CoCreateInstance(
__uuidof(CAlternativeNames),
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
__uuidof(IAlternativeNames),
(void **) &altnames);
_JumpIfError(hr, error, _T("CoCreateInstance CAlternativeNames"));
hr = altnames->Add(altname);
_JumpIfError(hr, error, _T("altnames->Add"));
hr = CoCreateInstance(
__uuidof(CX509ExtensionAlternativeNames),
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
__uuidof(IX509ExtensionAlternativeNames),
(void **) &altnameext);
_JumpIfError(hr, error, _T("CoCreateInstance CX509ExtensionAlternativeNames"));
hr = altnameext->InitializeEncode(altnames);
_JumpIfError(hr, error, _T("altnameext->InitializeEncode"));
hr = request->get_X509Extensions( &exts );
_JumpIfError(hr, error, _T("request->get_X509Extensions"));
hr = exts->Add( altnameext );
_JumpIfError(hr, error, _T("exts->Add"));
hr = request->get_PrivateKey( &pKey );
_JumpIfError(hr, error, _T("request->get_PrivateKey"));
hr = pKey->put_KeySpec( XCN_AT_SIGNATURE );
_JumpIfError(hr, error, _T("pKey->put_KeySpec"));
hr = pKey->put_ProviderName( myProvider );
_JumpIfError(hr, error, _T("pKey->put_ProviderName"));
hr = CoCreateInstance(
__uuidof(CObjectId),
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
__uuidof(IObjectId),
(void **) &Algorithm);
_JumpIfError(hr, error, _T("CoCreateInstance CObjectId - Algorithm"));
hr = Algorithm->InitializeFromAlgorithmName(XCN_CRYPT_ANY_GROUP_ID, XCN_CRYPT_OID_INFO_PUBKEY_ANY, AlgorithmFlagsNone, alg);
_JumpIfError(hr, error, _T("Algorithm->InitializeFromAlgorithmName"));
hr = pKey->put_Algorithm( Algorithm );
_JumpIfError(hr, error, _T("pKey->put_Algorithm"));
hr = CoCreateInstance(
__uuidof(CObjectId),
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
__uuidof(IObjectId),
(void **) &HashObj);
_JumpIfError(hr, error, _T("CoCreateInstance CObjectId - Hash"));
hr = HashObj->InitializeFromAlgorithmName(XCN_CRYPT_HASH_ALG_OID_GROUP_ID, XCN_CRYPT_OID_INFO_PUBKEY_ANY, AlgorithmFlagsNone, hash);
_JumpIfError(hr, error, _T("HashObj->InitializeFromAlgorithmName"));
hr = request->put_HashAlgorithm( HashObj );
_JumpIfError(hr, error, _T("request->put_HashAlgorithm"));
hr = request->Encode();
_JumpIfError(hr, error, _T("request->Encode"));
goto noerror;
error:
if (NULL != request ) request->Release();
noerror:
if (NULL != Algorithm ) Algorithm->Release();
if (NULL != HashObj ) HashObj->Release();
if (NULL != altname ) altname->Release();
if (NULL != altnames ) altnames->Release();
if (NULL != altnameext ) altnameext->Release();
if (NULL != exts ) exts->Release();
if (NULL != pKey ) pKey->Release();
VBScript:
Dim request, algobj, hashobj, template, altname, altnames, altnameext
Set request = CreateObject( "X509Enrollment.CX509CertificateRequestPkcs10" )
request.Initialize( ContextAdministratorForceMachine )
' Build the request altname.
Set altname = CreateObject( "X509Enrollment.CAlternativeName" )
altname.InitializeFromString XCN_CERT_ALT_NAME_DNS_NAME, DNSName
Set altnames = CreateObject( "X509Enrollment.CAlternativeNames" )
altnames.Add altname
Set altnameext = CreateObject( "X509Enrollment.CX509ExtensionAlternativeNames" )
altnameext.InitializeEncode altnames
request.X509Extensions.Add altnameext
If sign Then
request.PrivateKey.KeySpec = XCN_AT_SIGNATURE
Else
request.PrivateKey.KeySpec = XCN_AT_KEYEXCHANGE
End If
request.PrivateKey.ProviderName = myProvider
Set algobj = CreateObject( "X509Enrollment.CObjectId" )
algobj.InitializeFromAlgorithmName XCN_CRYPT_ANY_GROUP_ID, XCN_CRYPT_OID_INFO_PUBKEY_ANY, AlgorithmFlagsNone, "ECDSA_P521"
request.PrivateKey.Algorithm = algobj
Set hashobj = CreateObject( "X509Enrollment.CObjectId" )
hashobj.InitializeFromAlgorithmName XCN_CRYPT_HASH_ALG_OID_GROUP_ID, XCN_CRYPT_OID_INFO_PUBKEY_ANY, AlgorithmFlagsNone, "SHA256"
request.HashAlgorithm = hashobj
request.Encode
VB.NET:
Dim request As New CX509CertificateRequestPkcs10Class
request.Initialize(X509CertificateEnrollmentContext.ContextAdministratorForceMachine)
Dim altname As New CAlternativeNameClass
altname.InitializeFromString(AlternativeNameType.XCN_CERT_ALT_NAME_DNS_NAME, DNSName)
Dim altnames As New CAlternativeNamesClass
altnames.Add(altname)
Dim altnameext As New CX509ExtensionAlternativeNamesClass
altnameext.InitializeEncode(altnames)
request.X509Extensions.Add(DirectCast(altnameext, CX509Extension))
request.PrivateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE
request.PrivateKey.ProviderName = myProvider
Dim algobj As CObjectId = New CObjectIdClass
algobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_ANY_GROUP_ID, ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY, AlgorithmFlags.AlgorithmFlagsNone, "ECDSA_P521")
request.PrivateKey.Algorithm = algobj
Dim hashobj As CObjectId = New CObjectIdClass
hashobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID, ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY, AlgorithmFlags.AlgorithmFlagsNone, "SHA256")
request.HashAlgorithm = hashobj
request.Encode()
If the request is dumped, the following extension can be seen in the request.
2.5.29.17: Flags = 0, Length = 17
Subject Alternative Name
DNS Name=vistapc.contoso.com
Certificates expire after a period of time and need to be renewed. This example shows how to create a CMC request from an existing computer certificate. The request is created by calling the Encode method.
C#:
// Find an old certificate – this example picks the first in the store
X509Store store = new X509Store("My", StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
if (store.Certificates.Count == 0)
{
Console.WriteLine("No certificate to renew");
return null;
}
X509Certificate2 cert = store.Certificates[0];
string oldcert = Convert.ToBase64String(cert.RawData);
store.Close();
// Create a request and initialize from old certificate
CX509CertificateRequestCmcClass req = new CX509CertificateRequestCmcClass();
req.InitializeFromCertificate(
X509CertificateEnrollmentContext.ContextAdministratorForceMachine,
true,
oldcert,
EncodingType.XCN_CRYPT_STRING_BASE64,
X509RequestInheritOptions.InheritDefault | X509RequestInheritOptions.InheritPrivateKey);
// encode the request
req.Encode();
C++:
IX509CertificateRequestCmc* request = NULL;
HRESULT hr = S_OK;
HCERTSTORE hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY" );
if ( hStore == NULL )
{
_tprintf( _T("CertOpenStore: 0x%x\n"), GetLastError()); goto error;
}
// Find an old certificate – this example picks the first in the store
PCCERT_CONTEXT pcert = CertFindCertificateInStore( hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL );
if ( pcert == NULL )
{
_tprintf( _T("CertFindCertificateInStore: 0x%x\n"), GetLastError()); goto error;
}
hr = CoCreateInstance(
__uuidof(CX509CertificateRequestCmc),
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
__uuidof(IX509CertificateRequestCmc),
(void **) &request);
_JumpIfError(hr, error, _T("CoCreateInstance CX509CertificateRequestCmc"));
BSTR BinCert = SysAllocStringLen( NULL, pcert->cbCertEncoded );
memcpy( BinCert, pcert->pbCertEncoded, pcert->cbCertEncoded );
hr = request->InitializeFromCertificate( ContextAdministratorForceMachine, TRUE, BinCert, XCN_CRYPT_STRING_BINARY, (X509RequestInheritOptions) (InheritDefault | InheritPrivateKey ) );
_JumpIfError(hr, error, _T("request->InitializeFromCertificate"));
hr = request->Encode();
_JumpIfError(hr, error, _T("request->Encode"));
goto noerror;
error:
if (NULL != request ) request->Release();
noerror:
if ( NULL != pcert ) CertFreeCertificateContext(pcert);
if ( NULL != hStore ) CertCloseStore( hStore, 0 );
VBScript:
Dim request, cert, oldcert, store, first
Set store = CreateObject( "CAPICOM.Store")
Store.Open CAPICOM_LOCAL_MACHINE_STORE, "My", CAPICOM_STORE_OPEN_READ_ONLY OR CAPICOM_STORE_OPEN_EXISTING_ONLY
first = true
For each cert in Store.Certificates
If first Then
oldcert = cert.Export( CAPICOM_ENCODE_BASE64 )
first = false
End If
Next
Set request = CreateObject( "X509Enrollment.CX509CertificateRequestPkcs10" )
request.InitializeFromCertificate ContextAdministratorForceMachine, oldcert, XCN_CRYPT_STRING_BASE64, InheritDefault Or InheritPrivateKey
request.Encode
VB.NET:
Dim store As New X509Store("My", StoreLocation.LocalMachine)
store.Open(OpenFlags.ReadOnly)
Dim cert As X509Certificate2 = store.Certificates.Item(0)
Dim req As New CX509CertificateRequestCmcClass
req.InitializeFromCertificate( X509CertificateEnrollmentContext.ContextMachine, Convert.ToBase64String(cert.RawData), EncodingType.XCN_CRYPT_STRING_BASE64, X509RequestInheritOptions.InheritDefault)
store.Close()
req.Encode()