Applying PFX Certificates for Signing Internal .NET Applications

Motivation

We have a number of tools we distribute internally that we want to ensure are signed (particularly ClickOnce applications).

The goals were:

  1. Anyone on the team could build the tools (including ClickOnce tools) and publish them.
  2. No one on the team has to go through manual steps: they ought to be able to sync and build.
  3. No dialog popups during the build (such as passwords).
  4. No trust issues when using the tools–Certificates are trusted.

Publishing ClickOnce applications requires strong name signing all assemblies as well as using a certificate to sign the ClickOnce manifest. We needed to get a certificate with both public and private keys to be able to do so.

To enable anyone on the team to be able to sign the application I wanted to be able to submit our certificate (with both public and private key) into Perforce so it is synced with the tools. This would solve 1 & 2.

Submitting a certificate to Perforce would be a security issue if the certificate is issued by an external authority trusted by Windows users. To facilitate this we set up our own Certificate Server. Certificate Server is a Certificate Authority that can be joined to the domain so all domain users would trust certificates issued by this authority, yet not trusted by any normal Windows user. We can then issue code signing certificates at will. This solves 4.

These certificates also allow using Group Policy Objects to control access to the certificate, removing the need for a password. This solves 3.

Environment

We are running Windows Server 2012 R2 for our domain servers and Windows 8.1 for client machines.

Set Up Certificate Server

On the Domain Controller:

  1. Go to Server Manager
  2. Manage
  3. Add Roles and Features
  4. Role-based or feature-based installation
  5. Select the current server
  6. Active Directory Certificate Services, including:
    • Certificate Authority
    • Certificate Enrollment Policy Web Service
    • Certificate Enrollment Web Service
    • Certificate Authority Web Enrollment
    • Note that additional requirements will automatically be included, such as IIS.
  7. Finish the installation

After installation and possibly reboot there will be a task to configure the Certificate Authority. Configure the server as an Enterprise CA. This will simplify requesting new certificates dramatically and enable functionality not available in the non-Enterprise scenario.

Now let’s add the code signing template to the Certificate Authority.

  1. Start CertMgr.msc
  2. Click on “Certificate Templates”
  3. Action->New->Certificate Template to Issue
  4. Select “Code Signing”
  5. OK

Generate the Certificate into Your Personal Certificate Store

  1. Download CodeSigningKeyRequest.inf on GitHub locally
  2. Start cmd.exe
  3. Change to the download directory
  4. certreq -new  CodeSigningKeyRequest.inf CodeSigningKeyRequest.req
  5. certreq -submit  CodeSigningKeyRequest.req

It should pop up a dialog to select a certificate authority. Select the second.

CertSigning_image00

A save dialog will appear. Save the file as a .cer in the same location as the .req file.

  1. certreq -accept CodeSigningKeyRequest.cer

This will import the certificate into your personal certificate store with the private key.

Signing Assemblies

Export the Certificate to a Strong Name Key (SNK) File

  1. Run ExportCert.exe (available from: ExportCert on GitHub)
  2. Double click on the certificate from the certificate store

CertSigning_image03

Note: only certificates that are valid for code signing with the enhanced key usage extensions defined in the inf file above will be listed.

  1. Save the file (to an snk file)
  2. Add the file to source control

Configure the Project for Signing

  1. Open the solution.
  2. Right click on the project
  3. Add Existing File (Note: doing this from any other location in the project in the root will result in the snk file not showing up in the drop down for choosing the snk file. Once the snk file is chosen you can move it after).
  4. Select the exported strong name key file
  5. Select “Add As Link”:

CertSigning_image01

  1. Right Click on the Project
  2. Select Properties
  3. Select the Signing tab
  4. Enable “Sign the Assembly”
  5. Select the snk file in the “Choose a strong name key file”

Signing Click Once Assemblies

Export the Certificate

  1. Run certmgr.msc from the command line
  2. Find the certificate in your certificate store.  It ought to appear under Personal\Certificate with your user name and the same CA issuer you selected above. It will also specify an “Intended Purposes” of “Code Signing”.

CertSigning_image05

  1. Open the certificate (double click or right click and open)
  2. Details Tab
  3. Copy To File button
  4. In the wizard select:
    • Yes, Export the private key, Next
    • Accept default, Next
    • Use Group or User Names, Add

CertSigning_image04

    • Select Advanced

CertSigning_image02

    • Select Find Now
    • Find “Domain Users” in the Search Results and double click on it.
    • Select OK
    • Remove yourself from the user list.
    • Next
    • Save the pfx file out
  1. Add the pfx file that was saved to Perforce

Signing Assemblies with the Certificate

  1. Open the solution.
  2. Right click on the project
  3. Add Existing File (Note: doing this from any other location in the project in the root will result in the snk file not showing up in the drop down for choosing the snk file. Once the snk file is chosen you can move it after).
  4. Select the exported strong name key file
  5. Select “Add As Link”:

CertSigning_image01

  1. Right Click on the Project
  2. Select Properties
  3. Select the Signing tab
  4. Enable “Sign the ClickOnce manifests”
  5. Choose “Select from File”
  6. Select the pfx file. It should load automatically without requiring a password.

References

 

One thought on “Applying PFX Certificates for Signing Internal .NET Applications

Leave a Reply

Your email address will not be published. Required fields are marked *