A C#/.NET SCEP Client

Source Code: Download Zip Archive

As you have ended up here I must assume that, like me, you have a requirement to interface with a SCEP server using .NET and you have struggled to find any helpful examples of how to achieve this. I hope that this blog entry might be of some help to the few that venture into this obscure territory.

Background

As a little bit of background (there is too much to cover here), when I began my investigations into this area it seemed that there was pretty much only one option for implementing a .NET SCEP client and that was to use the Bouncycastle library, as the CLR System.Security.Cryptography API has some glaring omissions such as representation of a PKCS#10 request or ASN.1 DER type conversion. However this didn’t turn out to be quite the option that I had hoped. Firstly, I struggled to find any examples of a SCEP client implemented using Bouncycastle. Perhaps more importantly using 3rd party libraries always come with a risk, unless you know the code inside-and-out you have to place some trust in the authors to do the right thing. When it comes to integrating with a PKI – a major part of the infrastructure that you use to secure your digital estate – that risk seemed too great and so we had two options: either audit the Bouncycastle code-base or roll our own using the stock CLR APIs. Upon initial investigation of Bouncycastle I discovered quite quickly that it is a huge code-base and so I quickly turned to investigating building our own client, after all Bouncycastle did it so I knew it was possible, how hard could it be?

As it turns out it isn’t that hard, at least once you know the problem space, which turns out to be quite a mountain to climb for the uninitiated such as myself. My hope is that, having investigated the problem space and tackled some of the major hurdles, I am in a position to help some other people out in this area and provide a shortcut worth several days’ of effort that I could have done without.

The Example

To be clear, this isn’t going to be a full introduction into the ASN.1 and PKCS standards, there is plenty of that already very easily accessible on the Internet. Rather this is a simple working example of using the System.Security.Cryptography APIs to interface with a SCEP server. The code is documented with inline and XML comments that should point you to the online reference docs needed to understand the what and the why.

The Certificate Requests

The example I’ve provided here is in the form of a VS 2013 Unit Test project (converted from VS 2010 so beware of the old school Unit Test config!). This PoC was created for the specific case of receiving PKCS#10 signing requests and forwarding them to a PKI for enrolment via SCEP. This means that we were not concerned with creating the requests programmatically. If that is what you are after then I would suggest looking at using CertEnrol or automating the OpenSSL API. There are plenty of examples of using CertEnrol via the CERTCLIENTLib and CERTENROLLib DLLs, which are available on all Windows PC OS versions since, I think, XP. A good one is here: http://blogs.msdn.com/b/alejacma/archive/2008/09/05/how-to-create-a-certificate-request-with-certenroll-and-net-c.aspx?PageIndex=3. I struggled to find a simple way of forming a PKCS#10 request with the challenge password required by most SCEP environments. At any rate, I’m wandering outside the scope of this post and I ended up creating PKCS#10 requests for my tests using Open SSL at the command line.

The SCEP Server

When developing this PoC I was working with the NDES MSCEP component that comes with Active Directory Certificate Services. There are numerous other SCEP servers available, such as OpenSSL and theoretically this PoC should work with all of them. I just felt it was worth pointing this out so that you can bear it in mind while working with the example .

Lets Get Going Already!

You will need to tweak some of the example’s settings to fit within your environment but the logic itself is sound. Start by configuring URL of the SCEP server and the subject name that is used to locate the local/client certificate for signing the SCEP enrolment request. These can both be found at the top of the Unit Test class.

The example project contains a folder named ‘SCEP Tools’ that contains the Open SSL config and batch commands to create the PKCS#10 requests needed for the tests. Once created, update the respective request string variables in each test method with the request contents and you should be good to go!

Source Code: Download Zip Archive

Advertisements
A C#/.NET SCEP Client

9 thoughts on “A C#/.NET SCEP Client

  1. Gaurav says:

    Hi Stephen,

    I tried your code to enroll the certificate with Windows server 2012. It is enrolling the certificate. But the issue is I am not able to receive the certificate as It is not able to decrypt it properly.

    Like

    1. I came across similar issues while developing the integration. I usually found this to be due to the return payload not containing a certificate at all and instead containing an error or status code, usually just a single digit integer. This is usually indicated by a small payload being returned (i.e. the contents of the inner envelope being around 600-800 bytes). Can you check the logs on the AD CS host to see if there are any potential errors there? I say potential as I found the errors to be quite esoteric at the best of times.

      Note that it has been a little while since I dealt with this and I’ll take a proper look at the code again this evening if the above is not helpful.

      Like

  2. Apat says:

    I’ve tested your client example and it works for me but I got some question about the GetCACert part, it returns 3 certificates too for me. In a comment in the function createEnvelopedDataPkcs7() you wrote “you will need a reliable means of determining the correct to fetch”. Being new to this I have not many ideas on how to determining that. I noticed that the 3 certificates have a property called thumbprint but none of those match with the SCEP servers thumbprint which I can see on its admin page (default server/certsrv/mscep_admin).

    The only one that works of the 3 with my SCEP server is the one with index 1 as in your example, but it would be great to know why! 🙂

    Like

    1. If I recall correctly the three certs you are seeing are the root certificate (signing authority) followed by an intermediate certificate (i.e. your AD CA) and the issued cert. I would have thought that you should be able to compare the thumbprints to exclude the root and intermediate certs but now I am wondering if there is a better way. I suspect the ‘proper’ way to do this is to check the signature to establish the correct sequence in the chain and to identify the most derived certificate but that seems like it could be complicated. Let me have a little think about that and I’ll get back to you shortly.

      Like

    2. Yeah, it looks like you want to look for an ‘Issuer’ attribute in each certificate. The issuer contains the Subject of the parent certificate so you can use that to establish the chain and therefore the most derived certificate which will be your newly enrolled cert.

      Like

  3. Apat says:

    Thanks for your replies!

    The ‘Issuer’ attribute is the same for all three certificates. Maybe that is weird I dont know. Anyway I looked at the ‘Extensions’ attribute for each certificate and if a X509KeyUsageExtension is present I check the KeyUsages. For the certificate at index 1 (which works) the KeyUsage is ‘KeyEncipherment’, could that be something to look for when fetching the correct one?

    (If it sounds like I have no idea what I’m doing the sound is correct 🙂 )

    Like

    1. KeyUsage might actually be a reliable (enough) attribute to look at. Any root and intermediate certificates will absolutely have KeyUsage of ‘Certificate signing’ while in the vast majority of cases any certificate issued for client enrollment (i.e. through SCEP) will not. I suppose it depends on your use case. If you are enrolling devices then it is probably safe enough to say that your newly enroled certificate would have a KU or EKU of ‘Key encipherment’ or ‘Client Authentication’ while it would NOT have a KU of ‘Certificate signing’. You could potentially also check the subject as sometimes a CA will honor the requested Subject if it is present in the Request.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s