34

I need to make some changes to a ClickOnce application that I haven't touched for over a year and therefore the certificate has expired.

I've read that publishing with a new certificate will make the application fail, because it will be signed with a different key.

Therefore I think I need to use the same certificate but not sure how to renew it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
HAdes
  • 16,713
  • 22
  • 58
  • 74

5 Answers5

18

If you're after a quick solution, then you can "renew" your existing certificate and just give it a longer expiry date.

Cliff Stanford has cleaned up the Microsoft "workaround" and made it available as a simple command line exe - available here: http://may.be/renewcert/ - Nice work Cliff !

Andy Blackman
  • 1,235
  • 1
  • 11
  • 14
  • 7
    There are a couple of problems with that, just FYI. Might want to check this out. http://robindotnet.wordpress.com/2010/01/26/how-to-extend-an-existing-certificate-even-if-it-has-expired/ – RobinDotNet Feb 08 '11 at 06:38
  • 2
    I know this old, but it's (quite ridiculously) still an issue. What if a co-worker already created a new certificate (thus "extending" one year), but when we go to publish, it warns about the signature changing. This is a huge issue, as once the signature changes, the clients can no longer receive updates: "Cannot update application. Please contact the vendor." or something. And if they do manually install it again, it'll create "Name -1" icons/links. – Keith Apr 09 '15 at 15:21
  • The renewcert tool often doesn't work without certain VC++ dependencies, if you run into a case where you can't get that figured out, you can manually compile and run another tool, see https://stackoverflow.com/a/54120387/579234 – Sogger Jan 10 '19 at 00:26
  • 2
    The link is dead. It looks like the project was moved to GitHub? https://github.com/andreasbotsikas/RenewCert – Ama Jul 31 '20 at 09:51
9

Here's the definitive MSDN article on certificate expiration, which also includes a link to an update on RenewCert. http://msdn.microsoft.com/en-us/library/ff369721.aspx This covers all cases.

If you are targeting .NET 3.5, using automatic updates, and don't have a VSTO app, OR you are targeting .NET 4, changing the certificate will not cause you any problems.

RobinDotNet
  • 11,723
  • 3
  • 30
  • 33
7

Update: @OceanAirdrop did all the work below and made it available on github: https://github.com/OceanAirdrop/ExtendClickOnceCertificate, he has usage instructions on the readme landing page.


Original Details:

Renewing the pfx is the way to go as @Andy Blackman states, but renewcert has issues running on modern windows when I tried to use it. To fix the may.be/renewcert dependencies another guy rewrote it in C# so you can use it on modern Visual Studio:

https://nathanpjones.com/2013/01/renewing-temporary-certificate/

Download the source from his website, compile, and run.


If you get a "system.accessviolationexception" on the marshalling in CertNameToStr for wcslen, then make the following changes so the marshalling doesn't blow up:

  1. In Crypt.cs:Line 130 change the psz variable to use char[] instead of string:

     [DllImport("crypt32.dll", CharSet = CharSet.Auto)]
    -        internal static extern int CertNameToStr(X509Encoding dwCertEncodingType, ref CRYPT_DATA_BLOB pName, CertNameType dwStrType, ref string psz, int csz);
    +        internal static extern int CertNameToStr(X509Encoding dwCertEncodingType, ref CRYPT_DATA_BLOB pName, CertNameType dwStrType, [In, Out] char[] psz, int csz);
    
  2. In Program.cs:Line 131 use a char buffer instead of a string:

    -                //var buffer = new char[1024];
    -                string buffer = new string('\0', 1024);
    +                char[] buffer = new char[1024];
    +                //string buffer = new string('\0', 1024);
                     int d;
    -                if ((d = Crypt.CertNameToStr(Crypt.X509Encoding.ASN_Encodings, ref certNameBlob, Crypt.CertNameType.CERT_X500_NAME_STR, ref buffer, 1024 * sizeof(char))) != 0)
    +                if ((d = Crypt.CertNameToStr(Crypt.X509Encoding.ASN_Encodings, ref certNameBlob, Crypt.CertNameType.CERT_X500_NAME_STR, buffer, 1024 * sizeof(char))) != 0)
    
  3. rebuild

To run it to just quickly renew cert for default five years, use a cmd like:

"[path-to-renew-cert-proj-dir\bin\Debug\]renewCert.exe" [old-cert-path\]old_cert_name.pfx [new-cert-path\]new_cert_name.pfx
Sogger
  • 15,962
  • 6
  • 43
  • 40
  • 4
    Thanks.. This worked for me. I have taken the above code, added your fixes and increased the expiry date by 105 years. You can find the project on github here: https://github.com/OceanAirdrop/ExtendClickOnceCertificate – Ocean Airdrop Mar 10 '19 at 19:02
  • 1
    @OceanAirdrop Nice! I will put that at top of my answer! – Sogger May 21 '19 at 17:48
  • The main thanks go to you @Sogger, as you found the original solution. Helped me out a ton! – Ocean Airdrop May 22 '19 at 19:19
  • 2
    This is hilarious. That's my original code at nathanpjones.com and your answer is what came up when I ran across this same issue. Small world! Thanks for the fixes everyone. – N Jones Jun 20 '19 at 03:48
  • I'm trying to use this tool to extend my SHA256 test certificate but it always generates as SHA1. Anyone knows how to tell it to use SHA256? – bkqc Sep 01 '20 at 20:19
1

If I remember correctly, I ran into the same problem and just created a new certificate.

I think the automatic update broke between those versions, but there was no lasting damage. It might have helped that my application was for internal use only, so I didn't need a properly signed certificate.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
gillonba
  • 897
  • 9
  • 24
1

Basically you have to build an app to extend the expiry of your certificate. The links above will get you to the C++ source code for the app. If you are lucky and just signed it yourself it may work. If you used Verisign etc. to sign it you are SOL. You will need to uninstall and re-install every app. It's like you buy a new car the engine blows and the manufacturer gives you a book on re-building engines instead of replacing or fixing it. ClickOnce is not.