RenewCert - Working Version

What is RenewCert?

Microsoft has screwed up with its ClickOnce deployment in Visual Studio 2005©. You are required to have a certificate in order to sign the ClickOnce manifests and, by default, you create one with an expiry of one year.

A year on, your certificate expires and Visual Studio 2005© refuses to allow you to upload any more. If you simply create a new certificate, all your customers get an error:

The deployment identity does not match the subscription.

Not only can the customer not download the newer version, he cannot, owing to the nature of ClickOnce, even continue to use the older version.

Microsoft Workarounds

Microsoft developers know about this problem and have documented it on their support site: http://support.microsoft.com/kb/925521 where they give two "workarounds".

The first "workaround" is a total joke:

Uninstall the ClickOnce application that you signed by using the expired certificate. Then, reinstall the updated ClickOnce application that uses the new certificate.

What they actually mean is that you need to tell each and every one of your users to uninstall your application and reinstall it from scratch. Of course, you have no means to contact the users as all they see when trying to run the program is an unhelpful error message from Microsoft.

Their second workaround is a little better. According to Microsoft, you should:

Create a command-line assembly that updates the certificate.

What they actually mean is that you need to create a new certificate with the same key as the old one but with a date some time in the future. The code supplied tries to set it five years from the date it's run. This would be fine, if the code actually worked.

Microsoft's Code

The Microsoft developers should be ashamed of the code provided. There is no error checking whatsoever; even a simple File not found causes a crash.

The bigger problem is that the workaround doesn't work for keys other than the very simple ones produced as Test Certificates by the signing page. As one correspondent put it, "it worked great for all the certificates but the one I wanted."

The main problem with the Microsoft code is that it loses the CRYPT_KEY_PROV_INFO structure from the original key and thus CertCreateSelfSignCertificate() fails. Of course, in the original code, there is no way to tell what was failing.

The Solution

I have modified the Microsoft code to put in a test for success after each and every function call. I preserve the provider info structure from the old key to use when creating the new key. This seems to work but I have only tested it with a very limited number of keys.

The revised code can be found on my Subversion server in the file RenewCert.cpp. I apologise in advance for the state of this code … I got it to work and stopped fiddling. Maybe one day I'll rewrite it as a Windows application.

In the meanwhile, you can download the project as a zip file or simply download the executable from this site. The project is also available from the Subversion Server, Please let me know how you get on with it. Microsoft developers, please feel free to update your support pages with code from here. Better still, Microsoft, maybe you should re-write the solution properly.

How To Use

On the Microsoft page, it tells you to execute the following command:

renewcert <OldCertificate>.pfx <NewCertificate>.pfx \"CN=<NewCertificateName>\" <Password>

This has confused a number of people as it has the effect of passing the quotes into the third parameter. The correct syntax is:

renewcert <OldCertificate>.pfx <NewCertificate>.pfx CN=<NewCertificateName> <Password>

Where the items in <> (including the <>) are replaced with the appropriate names. If any parameter has a space or backslash in it, you should surround that parameter with quotes. e.g.:

renewcert maybe.pfx "new maybe.pfx" CN=NewName secret

Problems

It seems that a number of people have had an issue where the executable referred to above fails to run. It seems to need something from the Microsoft C++ development environment but, so far, I've been unable to work out what. The solution is to install the free Visual Studio Express version and rebuild the project. If anyone manages to get an executable that runs without this please let me know.

Feedback

If you try this code, I would very much appreciate some feedback. Did it work for you? If it gave an error, please let me have the output. Either way, please mail me and let me know.

Cliff Stanford

Valid XHTML 1.0 Transitional