다음을 통해 공유


Everything you need to know about Authenticode Code Signing

In today’s post, I’ll be discussing the use of Authenticode to sign software programs; this post will be of interest primarily to software developers. Large software companies (like Microsoft) often have an entire team dedicated to the code-signing and release process, but even (especially) small software publishers should sign their code. In this post, I’ll explain why, and tell you everything you need to do to achieve the benefits of shipping signed code.

Why sign your code?

As a software publisher, there are two reasons to sign your code:

  1. To prove its Integrity
  2. To develop its Reputation

The first point is simple: digitally signing your code helps to ensure that it cannot be tampered with, either on your servers, or when it is being downloaded to a user’s computer, especially over an insecure protocol like HTTP or FTP. This provides the user the confidence of knowing that the program they’ve just downloaded is the same one that you built.

Of course, that Integrity alone doesn’t mean a lot. Malicious files can also be signed, and a signature from, say, Bad-Guys-R-Us doesn’t mean that the code is safe to run. That’s where Reputation comes in. Historically, major software publishers like Microsoft, Adobe, Apple, IBM, etc, have worked hard to develop a good reputation in the minds of users. A user who downloads an application signed by Microsoft is usually more likely to trust and install that program than if the program were unsigned, or signed by some company they’ve never heard of. One problem with this scheme is that it doesn’t work too well except for the biggest of publishers—if I’ve never heard of Just Great Software, should I trust a package that bears their signature?

Internet Explorer 9’s SmartScreen Application Reputation feature helps level the playing field. This feature uses a variety of signals to evaluate the reputation of a given download, including the download history and popularity, anti-virus results, reputation of the site it has been delivered from, and more. As a small software publisher, the best way to accumulate your good reputation and allow it to benefit all of your software is to digitally sign your code. Signing your code allows the SmartScreen Application Reputation service to recognize a program’s origins, and allow that origin information to influence the reputation of the program. Small publishers benefit the most from this. For instance, while most users have never heard of me, my freeware programs are digitally signed by my certificate, and the clean reputation for my certificate means that SmartScreen Application Reputation can identify them as non-malicious.

When SmartScreen recognizes non-malicious code, the user benefits from a more streamlined trust experience, and fewer security prompts are shown when downloading and running the program. In contrast, unsigned and unknown programs are treated with suspicion and show more security warnings; our data indicates that 25-40% of such programs are eventually determined to be malicious.

Of course, if I were to ever abuse my good reputation to sign and release malicious code, the SmartScreen system can easily revoke my good reputation—my certificate’s signature would turn from a badge of honor into a flashing signal of untrustworthy software.

Hopefully, I’ve convinced you that signing your code is the right way to go. Now, on to the “how-to” portion of this post.

Step 1: Acquire a Software Publisher’s Digital Certificate

The first step is to get a software publisher’s certificate. Internally, these certificates are slightly different than a HTTPS server certificate (they bear different usage flags), and often cost a bit more because the certificate authority will perform more due diligence in verifying your identity. Certificates are issued by Certificate Authorities (CAs), firms whose job it is to verify the identity of certificate requestors and issue cryptographically-protected certificates that map the private key (which only you know) to a public key (which is contained in the certificate itself).

I purchased my personal Software Publisher’s certificate from Comodo via TuCows, a reseller. Their current prices are $75 for a certificate valid for one year, $140 for two years, or $195 for three years. Generally speaking, it’s a good idea to buy a certificate with the longest possible validity period because renewing certificates is not a fun experience, and it also helps to mitigate the problem of certificate rollover. Certificate rollover occurs when your old certificate expires and you begin signing your code with a new replacement certificate; all of your reputation was accumulated against the old certificate, and hence there may be a time lag for your new certificate to acquire a good reputation.

The process of acquiring a certificate typically takes a few days, and for non-incorporated software publishers like me, requires a fair amount of personal information. For instance, the validation process required that I fax a copy of my drivers license and a few utility bills to the Certificate Authority, so there was reasonable proof of my identity. I also validated my phone number and spoke to a representative. If I were to ever “go rogue” and start using my certificate for evil, I’m sure the terms of service say that this information would be provided to law enforcement so they could come ask me some questions.

After the verification process was completed, I was given the opportunity to download my new certificate. When downloading your new certificate, you should follow the Certificate Authorities instructions exactly as there are some mistakes that can be very difficult to recover from. In particular, choose a memorable but strong password to protect your private key file. After you have your certificate, be very sure to protect the private key file—if you lose control of your private key, a bad guy could sign code using your certificate. If your certificate is used maliciously, bad reputation will taint everything you’ve ever signed!

Note: Yes, you can also generate a self-signed certificate, but this is only useful if your software will never be used outside of your organization. Inside your organization, you could use Group Policy to deploy your self-signed certificate to all clients so that they trust it. However, any PC that isn’t configured to trust your certificate will block your software as bearing an invalid signature. Unless your company already has an internal PKI (public key infrastructure) deployment, you’re better off getting a publisher certificate that chains to one of the Trusted Root CAs.

Note: In August 2012, Microsoft announced support for a new type of Code-Signing certificate, the Extended Validation (EV) certificate. These certificates tend to be more expensive and harder-to-use (requiring security token hardware) but have the benefit of providing faster accumulation of reputation for SmartScreen.

Step 2: Sign your code

After you have a certificate, you can begin signing your installation executables or MSI install packages. Because you’ll want to do this for every build that you release, automating as much of the signing process as possible using a script or batch file is highly recommended.

Note: The .NET Framework has a different type of code-signing called “Strong Naming”. A strong name is not recognized by anything in Windows except the .NET Framework, and hence I won’t discuss it further here. ShawnFa wrote a good article explaining Strong Names and Authenticode.

To sign your program using Authenticode, you can use the SignCode.exe utility which shipped with the Microsoft .NET Framework version 1.1:

signcode -spc \src\mycert.spc -v \src\mykey.pvk -n "Fiddler2 Web Debugger (Beta)" -i "https://www.fiddler2.com/fiddler2/" -a sha1 -t https://timestamp.comodoca.com/authenticode Fiddler2BetaSetup.exe

You’ll be prompted to enter the password for your PVK file, and after doing so, your program will be signed and time-stamped.

The –n parameter specifies the string that will be shown in the “Name” field identifying the software. The –i parameter specifies the URL that will be launched if the user clicks on the Name hyperlink. The –a parameter specifies which hash algorithm should be used—this should always be sha1 because older hash algorithms are less secure, and will eventually be retired. Internet Explorer on Windows 7 SP1, for instance, disables MD2/MD4 hashes and treats signatures using those algorithms as invalid. The –t parameter specifies the URL of the time-stamping server, discussed later.

These inputs result in a signature that is displayed by various trust prompts like so:

Dialog box showing signature information

Alternatively, you can use the SignTool.exe shipped in the Windows SDK and later versions of the .NET Framework. To use this tool, you’ll need to convert your .SPC & .PVK files into a new PFX file, which you can do from a Visual Studio Command prompt:

pvk2pfx -spc mycert.spc -pvk mykey.pvk -pfx mycert.pfx -pi PVKPassword -po NewPFXPassword

After that, you can use a script like the following to sign your package:

set /P PFXPass=Enter PFX Password:
signtool sign /p %PFXPASS% /f C:\src\mycert.pfx /d "FiddlerCap" /du "https://www.fiddlercap.com/" /t https://timestamp.comodoca.com/authenticode /v FiddlerCap-en.msi
set PFXPass=blank

Easy, huh?

Best Practice: Sign both the installer and the application

When downloading installation packages from the Internet, the browser and/or Windows Shell will only check the digital signature on the installer itself. However, as a best practice, you should also sign the main executable of your application as well. This helps prevent tampering, but more importantly, it helps ensure that any security tools on the user’s machine can more readily identify your code. For instance, many anti-malware or firewall tools will treat unsigned executables with suspicion, and may even block them if they happen to share the same filename as a malicious program. For instance, one of my utilities, SlickRun shared the same filename (sr.exe) as a malicious program, and some anti-malware tools were too primitive to recognize the false positive. However, after I signed sr.exe directly, this problem went away. Similarly, some firewalls assign exceptions to programs based on their digital signature or file hash. If the user approves an exception to allow your program through the local firewall, that exception may be deleted if your program is later updated and the file’s hash changed. Signing your code can help prove to the firewall that the new version of your program should inherit the exemption granted to the older version.

Note: Typically, Windows does not itself check the digital signature when running a locally-installed version of your program; it only checks the signature when the program bears a Mark-of-the-Web indicating that it was downloaded from the Internet or extracted from an archive downloaded from the Internet. However, executables written in .NET can be an exception to this. The .NET Framework has the ability to assign security permissions to code based on its signature, called “publisher evidence.” Doing so necessitates that the signature be verified, and verifying the signature may require an expensive network request to check the certificate for revocation. If you are not using the “publisher evidence” feature of .NET, you can modify your application’s manifest to indicate that .NET should not check the signature.

YourApp.exe.config:

 <configuration> 
  <runtime> 
  <generatePublisherEvidence enabled="false"/> 
  </runtime> 
 </configuration>

 

Best Practice: Time-stamping

When signing your code, you have the opportunity to timestamp your code; you should definitely do this. Time-stamping adds a cryptographically-verifiable timestamp to your signature, proving when the code was signed. If you do not timestamp your code, the signature will be treated as invalid upon the expiration of your digital certificate. Since it would probably be cumbersome to re-sign every package you’ve shipped when your certificate expires, you should take advantage of time-stamping. A signed, time-stamped package remains valid indefinitely, so long as the timestamp marks the package as having been signed during the validity period of the certificate.

 

Thanks for helping ensure a secure and streamlined experience for Windows users!

-Eric

Update: Not all publisher certificates are enabled to permit timestamping to provide indefinite lifetime. If the publisher’s signing certificate contains the lifetime signer OID (OID_KP_LIFETIME_SIGNING 1.3.6.1.4.1.311.10.3.13), the signature becomes invalid when the publisher’s signing certificate expires, even if the signature is timestamped. This is to free a Certificate Authority from the burden of maintaining Revocation lists (CRL, OCSP) in perpetuity.

Update: It also appears that some CAs do not provide SPC and PVK files, instead providing the certificate in a different format. You can convert from a .CER file to a SPC file using Cert2SPC.exe in the Windows SDK. If you have a PEM file instead of a .PVK file, you can convert that using OpenSSL's pvk command: pvk -in PEM_KEY_FILE -topvk -out PVK_FILE. https://help.godaddy.com/article/6034 has a step-by-step walkthrough.

Curious about where the Authenticode signature actually goes into the binary? See this whitepaper.

Update: Some developers use tricks to sneak unauthenticated data inside Authenticode-signed binaries. You shouldn't do that.

Comments

  • Anonymous
    March 23, 2011
    Nice article.  Have you ever used USB devices for storing the cert/private key? As to Time-Stamping, when I last worked a lot with code-signing only one PKI company provided a timestamp server.  Do you know if that's still the case?

  • Anonymous
    March 23, 2011
    @Alan: Comodo offers timestamping at the URL provided above; Verisign's endpoint is timestamp.verisign.com/.../timestamp.dll. I'm afraid I have no idea what other authorities have endpoints.

  • Anonymous
    June 30, 2011
    K Software sells Comodo certificates at a significant discount : codesigning.ksoftware.net They'll walk you through the whole process, too.

  • Anonymous
    September 21, 2011
    Excellent article. I've been trying to find out whether or not to sign both the installer and the application. Your article helped heaps. Many thanks!

  • Anonymous
    December 02, 2011
    Certs 4 Less is another resource that offers Thawte Code Signing Certificates for $99.

  • Anonymous
    December 18, 2011
    For those curious about how Signtool actually signs, here is the sequence of Crypto API commands used: AcquireContext() AcquireContext() GetUserKey( AT_SGNATURE ) ExportKey( for public key ) DestroyKey() CreateHash( CALG_SHA1 ) GetHashParam( HP_HASHVAL ) SetHashParam( HP_HASHVAL ) CPSignHash() DestroyHash() ReleaseContext() ReleaseContext()

  • Anonymous
    January 23, 2012
    What will happen if somebody will use our installer after the certificate expries?

  • Anonymous
    January 23, 2012
    @Swati: Read the section titled "Best Practice: Time-stamping."

  • Anonymous
    February 09, 2012
    Excellent post.  One issue that I suffer from is that when I digitally sign my app and specify the timestamp server, sometimes the timestamp server times out for a while.  I was wondering if you knew if it was safe to use a timestamp server that is hosted by a company different from the one you purchased your certificate from.  For example, let's say I have a certificate from Verisign and signcode keeps failing to contact Verisign's timestamp server.  Is it safe for me to sign my app using my Verisign certificate and using Comodoca's timestamp server?

  • Anonymous
    February 09, 2012
    @Chris: As far as I know, that ~should~ work. There may be a slight performance cost because the revocation checks on the certificate chains would be to different organizations, but I've never benchmarked this myself. So far, I haven't had problems with Comodo's Timestamp server, and I'm pretty sure the Verisign guys would be horrified to hear that you're having problems with theirs and are pondering a workaround.

  • Anonymous
    May 06, 2012
    I'd be very interested to read an article on the documented differences between AuthentiCode and Apple's new GateKeeper - it seems to me that GateKeeper is by its very nature unreliable and insecure (certificates are only provided by Apple, and there appears to be no identity vetting process in place to acquire one), but I'd like to know more from someone in the industry...

  • Anonymous
    May 07, 2012
    @Claire: Based on their published statements, it sounds like Gatekeeper provides a PKI infrastructure wherein Apple Inc. is the only trusted CA and manages both identity verification and revocation. If managed properly, this could be a fine approach from a security point-of-view.

  • Anonymous
    June 18, 2012
    I have digitally signed my installable with certificate purchased from Godaddy. And even after 5 days when i download the installable from our website we get the same message that "setup.exe is not commonly downloaded and it could harm the computer". Does it require specific number of download to improve the reputation?

  • Anonymous
    June 21, 2012
    You say that reputation is held against specific certificates, rather than the common name on the cert.  In that case, why not just use Self signed certs?  If it does not matter what the common name is, an you are only recording that no one complains about software signed that way? I understand that it must cost the cert auths much more to issue a long lived cert than a short lived one, all those extra bits they need to toggle...

  • Anonymous
    August 15, 2012
    The comment has been removed

  • Anonymous
    August 16, 2012
    @Jack: Certificates are trusted by Windows, not IE. Having said that, I'm not aware of any change to GoDaddy's certificate status in the last few years.

  • Anonymous
    September 24, 2013
    What do you do when your current certificate is expiring and you need a new one?  Can my reputation from the old certificate be transferred to the new one? And, how long does it take to get a rep?

  • Anonymous
    September 24, 2013
    @Peter Weyzen: Rollover is indeed a challenge with reputation systems; that's one reason why it's generally a good idea to get a certificate with a validity period of multiple years. EV Code-signing certificates were introduced to address the challenge of reputation rollover; please see blogs.msdn.com/.../microsoft-smartscreen-amp-extended-validation-ev-code-signing-certificates.aspx Reputation building time is subject to many factors, including the popularity of the download.

  • Anonymous
    November 19, 2013
    Hi Eric, but if a certificate is outdated, the app will stop working? Thanks for the post. [EricLaw] This is discussed in the post. To wit: Typically, Windows does not itself check the digital signature when running a locally-installed version of your program; it only checks the signature when the program bears a Mark-of-the-Web indicating that it was downloaded from the Internet or extracted from an archive downloaded from the Internet.

  • Anonymous
    December 06, 2013
    Great article.  I have code signed my EXE (as well as all related DLLs) with a valid COMODO code signing certificate.  But when I run the program from a network folder, I still receive a warning saying "We can't verify who created this file.  Are you sure you want to run this file?"  I've checked the file's properties and it shows the program is signed (on the digital signatures tab).   The file is located in a folder on my home network running on an XP machine.  I am calling the EXE from my Win7 machine. Any thoughts what I've missed? [EricLaw] If you copy the file to your desktop, do you see the same prompt? In Spring 2013, the Windows team made a change such that anything executed from a network share will show a prompt even if validly signed.

  • Anonymous
    December 10, 2013
    Eric, no the application runs without warning on my desktop. You are correct.  I've tried running some commercial EXE's from the network PC and do get the same warning.   I'm hoping I don't understand the term "network share".  Would this same error appear on computers running the program on a "real" server?  I may have to make significant changes to my deployment strategy.  (Currently I'm putting the EXE/DLLs in a shared folder on the server with data in a sub folder.) [EricLaw] If the app is launched using a path of something like \serverappsapp1.exe, the prompt will show (prompting for that scenario isn't new, but in the old days, the signature dialog would show the signing information instead of the generic warning). Thanks.

  • Anonymous
    March 17, 2014
    What all do we need to provide to certifying authority to get the certificate? In some blogs i read that we need to send our public key.. Is it so? If so, where and how to get that public key? [EricLaw] Typically, when you buy a certificate from a CA site, the site will use an ActiveX control (like http://blogs.msdn.com/b/ieinternals/archive/2010/05/14/certificate-enrollment-xenroll-vs-certenroll-activex-object.aspx) to generate a public/private key pair locally, and then send a certificate request to the CA. The CA never gets your private key, which is kept on your PC. What are all the files we will get from certifying authority? We will get only .spc file or anything else? In this blog, while signing code using signcode.exe, you have mentioned .pvk file.. where do we get that .pvk file? Thanks. [EricLaw] Typically, the PVK file is exported from your Windows certificate store, where it was placed when the ActiveX control generated it.  

  • Anonymous
    April 01, 2014
    Couple of questions

  1. I can not find anything that says Windows checks the signatures on all the DLL used by an EXE. [EricLaw] Generally speaking, Windows does not check the signatures on DLLs when loaded by an executable. There are exceptions (e.g. DRM-related DLLs, and all modules are signature checked on WindowsRT/ARM).
  2. AppLocker has a way to say only allow running signed executable files, but that is not much use if the DLL used by the EXE are not also checked. [EricLaw] You'd have to ask the AppLocker team about their threat model on that. Perhaps they enforce a signature check or perhaps there's a reason that this is outside of their scope.
  3. When I look at the Windows DLL our application uses, I find that 3 of 32 are signed.  Why doesn't Microsoft sign all DLL they deliver? [EricLaw] Which DLLs specifically? It's important to understand that many Windows binaries are "catalog signed" instead of having an Authenticode signature directly embedded into the file.
  • Anonymous
    April 03, 2014
    Signage On Windows 7 Professional using Visual Studio 2013 compiling for 64-bit release mode, dependency walker says the below DLL are referenced but "signtool verify /pa" says only ntdll.dll is signed. c:windowssystem32ADVAPI32.DLL
    c:windowssystem32API-MS-WIN-DOWNLEVEL-ADVAPI32-L1-1-0.DLL
    c:windowssystem32API-MS-WIN-DOWNLEVEL-NORMALIZ-L1-1-0.DLL ...  Thanks for the quick response to the previous post. [EricLaw] As I mentioned, most Windows files are catalog-signed instead of carrying an Authenticode signature directly in the binary. See http://technet.microsoft.com/en-us/sysinternals/bb897441.aspx. For instance: C:tools>sigcheck c:windowssystem32advapi32.dll Sigcheck v2.03 - File version and signature viewer
    Copyright (C) 2004-2014 Mark Russinovich
    Sysinternals - www.sysinternals.com c:windowssystem32advapi32.dll:
            Verified:       Signed
            Signing date:   12:38 PM 2/23/2014
            Publisher:      Microsoft Windows
            Description:    Advanced Windows 32 Base API
            Product:        Microsoft« Windows« Operating System
            Prod version:   6.3.9600.16384
            File version:   6.3.9600.16384 (winblue_rtm.130821-1623)
            MachineType:    64-bit  

  • Anonymous
    June 08, 2014
    We have now purchased two code signing certificates from Comodo with no apparent change in the download experience for our users.  We keep being told it is a matter of time yet our application never seems to develop a sufficient reputation to be treated as safe. What do we need to do to get our app to be treated as safe?  The certificate cost us more than $300 for the two years and we did not get anything for it.  Talking with Comodo they tell us they cannot help us figure out why it never does what it is supposed to do.  My email - and I would desperately like a reply - is jim at x-gecko.com Thanks!

  • Anonymous
    August 27, 2014
    The comment has been removed

  • Anonymous
    November 12, 2014
    Hi, I am a download SDK provider, an Installer, who signs the package? The software published or the Installer? [EricLaw] It's not clear exactly what you're asking. You should not sign code that you do not trust. Someone should sign the outermost file (e.g. an executable setup.exe)

  • Anonymous
    January 26, 2015
    Personally I feel that the MD5 signature is more serious han the MD2 certificate. MD2 has no practical preimage attack that I know of (don't forget the memory requirement). MD5 has practical chosen prefix attacks. [EricLaw] It's true that there are more dangerous public attacks against MD5, but it's also more broadly deployed and thus harder to deprecate. MD2 in contrast, was retired with relatively little impact. RFC6149 - MD2 to Historic Status - https://tools.ietf.org/html/rfc6149

  • Anonymous
    November 23, 2017
    Does it need an Internet connection to check for reputation?