Retired Microsoft Blog disclaimer

This directory is a mirror of retired "Decrypt My World" MSDN blog and is provided as is. All posting authorship and copyrights belong to respective authors.

Posts on this page:

Original URL: https://blogs.msdn.microsoft.com/alejacma/2010/07/28/how-to-request-an-smartcard-logon-cert-programmatically-c/
Post name: How to request an smartcard logon cert programmatically (C#)
Original author: Alejandro Campos Magencio
Posting date: 2010-07-28T03:50:00+00:00


Hi all,

The other day I created this C# sample which shows how to request an smartcard logon cert to a CA. It is based on this other sample: How to create a certificate request with CertEnroll and .NET (C#).

using System;

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

// Add the CertEnroll namespace
using CERTENROLLLib;
using CERTCLIENTLib;

namespace CATest
{
public partial class Form1 : Form
{
private const int CC_DEFAULTCONFIG = 0;
private const int CC_UIPICKCONFIG = 0x1;
private const int CR_IN_BASE64 = 0x1;
private const int CR_IN_FORMATANY = 0;
private const int CR_IN_PKCS10 = 0x100;
private const int CR_DISP_ISSUED = 0x3;
private const int CR_DISP_UNDER_SUBMISSION = 0x5;
private const int CR_OUT_BASE64 = 0x1;
private const int CR_OUT_CHAIN = 0x100;

public Form1()
{
InitializeComponent();
}

// Create request
private void createRequestButton_Click(object sender, EventArgs e)
{
// Create all the objects that will be required
CX509CertificateRequestPkcs10 objPkcs10 = new CX509CertificateRequestPkcs10Class();
CX509PrivateKey objPrivateKey = new CX509PrivateKeyClass();
CCspInformations objCSPs = new CCspInformationsClass();
CX500DistinguishedName objDN = new CX500DistinguishedNameClass();
CX509Enrollment objEnroll = new CX509EnrollmentClass();
CObjectIds objObjectIds = new CObjectIdsClass();
CObjectId objObjectId = new CObjectIdClass();
CX509ExtensionKeyUsage objExtensionKeyUsage = new CX509ExtensionKeyUsageClass();
CX509ExtensionEnhancedKeyUsage objX509ExtensionEnhancedKeyUsage = new CX509ExtensionEnhancedKeyUsageClass();
CX509ExtensionTemplateName objExtensionTemplate = new CX509ExtensionTemplateName();
string strRequest;

try
{
requestText.Text = "";

// Get all available CSPs
objCSPs.AddAvailableCsps();

// Provide key info
objPrivateKey.ContainerName = "Alex";
objPrivateKey.ProviderName = "eToken Base Cryptographic Provider";
objPrivateKey.ProviderType = X509ProviderType.XCN_PROV_RSA_FULL;
objPrivateKey.Length = 1024;
objPrivateKey.KeySpec = X509KeySpec.XCN_AT_KEYEXCHANGE;
objPrivateKey.KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_ALL_USAGES;
objPrivateKey.MachineContext = false;
objPrivateKey.CspInformations = objCSPs;

// Create the actual key pair
objPrivateKey.Create();

// Initialize the PKCS#10 certificate request object based on the private key.
// Using the context, indicate that this is a user certificate request and don't
// provide a template name
objPkcs10.InitializeFromPrivateKey(
X509CertificateEnrollmentContext.ContextUser,
objPrivateKey,
""
);

// Key Usage Extension
objExtensionKeyUsage.InitializeEncode(
X509KeyUsageFlags.XCN_CERT_DIGITAL_SIGNATURE_KEY_USAGE |
X509KeyUsageFlags.XCN_CERT_NON_REPUDIATION_KEY_USAGE |
X509KeyUsageFlags.XCN_CERT_KEY_ENCIPHERMENT_KEY_USAGE |
X509KeyUsageFlags.XCN_CERT_DATA_ENCIPHERMENT_KEY_USAGE
);
objPkcs10.X509Extensions.Add((CX509Extension)objExtensionKeyUsage);

// Enhanced Key Usage Extension
objObjectId.InitializeFromValue("1.3.6.1.4.1.311.20.2.2"); // OID for Smartcard logon
objObjectIds.Add(objObjectId);
objX509ExtensionEnhancedKeyUsage.InitializeEncode(objObjectIds);
objPkcs10.X509Extensions.Add((CX509Extension)objX509ExtensionEnhancedKeyUsage);

// Template Extension
objExtensionTemplate.InitializeEncode("SmartcardLogon");
objPkcs10.X509Extensions.Add((CX509Extension)objExtensionTemplate);

// Encode the name in using the Distinguished Name object
objDN.Encode(
"CN=AlejaCMa",
X500NameFlags.XCN_CERT_NAME_STR_NONE
);

// Assing the subject name by using the Distinguished Name object initialized above
objPkcs10.Subject = objDN;

// Create enrollment request
objEnroll.InitializeFromRequest(objPkcs10);
strRequest = objEnroll.CreateRequest(
EncodingType.XCN_CRYPT_STRING_BASE64
);

requestText.Text = strRequest;

} catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

// Submit request to CA and get response
private void sendRequestButton_Click(object sender, EventArgs e)
{
// Create all the objects that will be required
CCertConfig objCertConfig = new CCertConfigClass();
CCertRequest objCertRequest = new CCertRequestClass();
string strCAConfig;
string strRequest;
int iDisposition;
string strDisposition;
string strCert;

try
{
strRequest = requestText.Text;

// Get CA config from UI
//strCAConfig = objCertConfig.GetConfig(CC_DEFAULTCONFIG);
strCAConfig = objCertConfig.GetConfig(CC_UIPICKCONFIG);

// Submit the request
iDisposition = objCertRequest.Submit(
CR_IN_BASE64 | CR_IN_FORMATANY,
strRequest,
null,
strCAConfig
);

// Check the submission status
if (CR_DISP_ISSUED != iDisposition) // Not enrolled
{
strDisposition = objCertRequest.GetDispositionMessage();

if (CR_DISP_UNDER_SUBMISSION == iDisposition) // Pending
{
MessageBox.Show("The submission is pending: " + strDisposition);
return;
}
else // Failed
{
MessageBox.Show("The submission failed: " + strDisposition);
MessageBox.Show("Last status: " + objCertRequest.GetLastStatus().ToString());
return;
}
}

// Get the certificate
strCert = objCertRequest.GetCertificate(
CR_OUT_BASE64 | CR_OUT_CHAIN
);

responseText.Text = strCert;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

// Install response from CA
private void acceptPKCS7Button_Click(object sender, EventArgs e)
{
// Create all the objects that will be required
CX509Enrollment objEnroll = new CX509EnrollmentClass();
string strCert;

try
{
strCert = responseText.Text;

// Install the certificate
objEnroll.Initialize(X509CertificateEnrollmentContext.ContextUser);
objEnroll.InstallResponse(
InstallResponseRestrictionFlags.AllowUntrustedRoot,
strCert,
EncodingType.XCN_CRYPT_STRING_BASE64,
null
);

MessageBox.Show("Certificate installed!");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}


I hope this helps.

Regards,

Alex (Alejandro Campos Magencio)

Original URL: https://blogs.msdn.microsoft.com/alejacma/2010/07/28/cryptoapi-and-5-bytes-exponent-public-keys/
Post name: CryptoAPI and 5 bytes exponent public keys
Original author: Alejandro Campos Magencio
Posting date: 2010-07-28T03:22:18+00:00


Hi all,

One customer of mine wanted to import a public key he got from a partner. That public key had a 2048 bits modulus and a 5 bytes exponent.

The problem was that CryptoAPI's RSAPUBKEY structuredoesn't allow a 5 bytes exponent because it defines the public exponent with a DWORD (4 bytes max):

typedef struct _RSAPUBKEY {
DWORD magic ;
DWORD bitlen ;
DWORD pubexp ;
} RSAPUBKEY;

CryptoAPI only supports 4 byte exponents with MS CSPs (Cryptographic Service Providers). CNG overcomes this limitation on Vista and later:

Key Storage and Retrieval
"
CNG is more flexible with regard to RSA key pairs. For example, CNG supports public exponents larger than 32-bits in length, and it supports keys in which p and q are different lengths.
"

Please, note that the restriction of 4 byte exponents are for MS CSPs only. CryptoAPI should be able to work with 5 byte exponents if using a third-party CSP.

Regards,

Alex (Alejandro Campos Magencio)

Original URL: https://blogs.msdn.microsoft.com/alejacma/2010/07/28/invalid-provider-type-specified-when-using-cng-providers-with-net-cms-classes/
Post name: "Invalid provider type specified" when using CNG providers with .NET CMS classes
Original author: Alejandro Campos Magencio
Posting date: 2010-07-28T03:08:31+00:00


Hi all,

The other day a customer of mine got this exception when trying to use SignedCms and EnvelopedCms class with a CNG provider in their .NET 3.5 application:

Exception type: System.Security.Cryptography.CryptographicException
Message: Invalid provider type specified.

They needed touseSHA-2 and AES algorithms with those CMS classes, and we already saw that we need a CNG provider for that on Vista and later:

"An internal error ocurred" when using SHA-2 algorithms with SignedCMS

"An internal error ocurred" when using AES algorithms with EnvelopedCms

 

The reason for this exception is that .NET doesn't support CNG on those types yet. Current CNG support in the .NET Framework extends only to explicit algorithm wrappers with CNG suffixes (ECDsaCng, SHA256Cng, etc.). None of the higher level services have CNG plumbed through (for instance, CMS, SignedXml, X509Certificate, etc).

There are some open source.NET extensions in CodePlex site to work with CNG, butthey don't support CMS stuff as far as I can tell: CLR Security.

So an alternative we have to workwith CMS and SHA2 or AES algorithms, is to call CryptMsg API directly through p/invoke and use a CNG provider.

Sample on how to call CryptMsg API from .NET (no CNG included, sorry): How to call CryptMsg API in streaming mode (C#)

I hope this helps.

Regards,

 

Alex (Alejandro Campos Magencio)

Original URL: https://blogs.msdn.microsoft.com/alejacma/2010/06/07/an-internal-error-ocurred-when-using-aes-algorithms-with-envelopedcms/
Post name: "An internal error ocurred" when using AES algorithms with EnvelopedCms
Original author: Alejandro Campos Magencio
Posting date: 2010-06-07T08:38:00+00:00


Hi all,

The other day a customer of mine got this exception when trying to useAES algorithms with EnvelopedCms class in their .NET 3.5 application:

Exception type: System.Security.Cryptography.CryptographicException
Message: An internal error occurred.

They got the exception on Windows Vista SP2/Server 2008 SP2 and later versions when using using a third-party CSP. Why?

EnvelopedCms class uses CAPI2 (CryptMsg* API) behind the scenes. CAPI2 requires a CNG provider for any algorithm that is not on this list:

CryptFindOIDInfo Function
"
Symmetric Encryption Algorithms:

CALG_DES
CALG_3DES
CALG_RC2
CALG_RC4

Algorithms that are not listed are supported by using Cryptography API: Next Generation (CNG) only;
"

In customer's scenario, third-party CSP was a legacy CSP and not a CNG provider.

Summing up, if you want to work with i.e. AES128, AES192 & AES256 algorithms, you will need a CNG provider.

Now, I will post about this in greater detail soon, but EnvelopedCms class doesn't support CNG. So basically, we cannot useAES algorithms with that class under this scenario.

I hope this helps.
Regards,

Alex (Alejandro Campos Magencio)

 

PS: This post is related to this: "An internal error ocurred" when using SHA-2 algorithms with SignedCMS. For any algorithms not included in CryptFindOIDInfo Function, we will have to use CNG instead of legacy providers.

Original URL: https://blogs.msdn.microsoft.com/alejacma/2010/06/02/an-internal-error-ocurred-when-using-sha-2-algorithms-with-signedcms/
Post name: "An internal error ocurred" when using SHA-2 algorithms with SignedCMS
Original author: Alejandro Campos Magencio
Posting date: 2010-06-02T08:58:00+00:00


Hi all,

The other day a customer of mine got this exception when trying to use SHA-2 algorithms with SignedCms class in their .NET 3.5 application:

Exception type: System.Security.Cryptography.CryptographicException
Message: An internal error occurred.

They got the exception on Windows Vista SP2/Server 2008 SP2 and later versions when using using a third-party CSP. Why?

SignedCMS class uses CAPI2 (CryptMsg* API) behind the scenes. CAPI2 requires a CNG provider for any algorithm that is not on this list:

CryptFindOIDInfo Function
"
Hash Algorithms:

CALG_SHA1
CALG_MD5
CALG_MD4
CALG_MD2

Algorithms that are not listed are supported by using Cryptography API: Next Generation (CNG) only;
"

In customer's scenario, third-party CSP was a legacy CSP and not a CNG provider.

Summing up, if you want to work with i.e. SHA256, SHA384 & SHA512 algorithms, you will need a CNG provider.

Now, I will post about this in greater detail soon, but SignedCMS class doesn't support CNG. So basically, we cannot use SHA-2 algorithms with that class under this scenario.

I hope this helps.
Regards,

Alex (Alejandro Campos Magencio)