The Ultimate Guide to Code Signing Best Practices


The Top 11 Code Signing Best Practices to Protect Your Customers and Keep Your Software Tamper-Free

Want to protect your home from thieves? A security system is a popular option. However, it’s not very effective if you don’t install it properly, fail to activate it when you aren’t home, or use “123456” as the security code. The same applies to code signing certificates. They’re the best way to protect the integrity of your software and prevent tampering by hostile third parties, but only if code signing best practices are followed. Otherwise, you might as well not even bother.

 If you still need convincing, just look at the recent SolarWinds breach. Sloppy code signing practices left the door wide open for hackers, and they were able to inject malicious code into legitimate software updates without anyone noticing. As Mike Nelson, DigiCert’s VP of IoT Security, explains:

Code signing works. Poorly implemented code signing puts your business at greater risk. In the case of SolarWinds, they were using a code signing certificate to sign the files. The problem wasn’t the code signing certificate, the problem was the way they were practicing code signing.

Those SolarWinds updates got pushed to nearly 18,000 customers, including Microsoft, Nvidia, Intel, and Cisco, who were suddenly left exposed via a backdoor hidden within the SolarWinds software. It’s nothing new – a similar situation occurred with Asus in 2019 – and attackers will continue to attempt code tampering as long as companies are lax with their processes.

So, what is code signing exactly? Why is it such an important part of the software development cycle? And, most importantly, what are the code signing best practices that your organization should always follow?

Let’s hash it out.

What is Code Signing?

First, let’s take a step back and review what code signing is and how it works. Code signing certificates help to:

  • Protect your code as it’s distributed online
  • Verify that you are the author of the file
  • Signal if the software has been tampered with
  • Provide a permanent, irreversible timestamp that allows for verification after certificate expiration or revocation

Code signing uses public key infrastructure (PKI) to apply a digital signature as proof of legitimacy and integrity. Extended Validation (EV) code signing certificates go a step further. A more vigorous verification process is carried out before certificate issuance, and the certificate itself is stored on a physical USB device as an additional layer of security. EV code signing also gets rid of Microsoft SmartScreen and other browser/operating system (OS) warnings thanks to the higher level of identity verification that’s initially required.

windows installation warnings
Without code signing, Windows generates the warning message on the left prior to installation. The warning goes away when a signed application is detected, as seen on the right.

Code signing is widely performed across all software platforms, device types, and application categories. In fact, some platforms actually make code signing a requirement for publishing.

Why is Code Signing Important?

Users want to be confident when downloading a file, and if there is any doubt in their mind then they will tend to reject the software altogether. Code signing acts as a sort of “digital shrink wrap” that tells the user that not only is the file coming from a verified source, but also that it hasn’t been tampered with in the meantime.

Code signing provides peace of mind and builds trust with end users, making them much more likely to install your application on their machine. It leads to more downloads, more users, and an improved reputation and brand image.

How Does Code Signing Work?

As we touched on earlier, code signing certificates are similar to other types of digital certificates in that they’re built on PKI. Their implementation and use depends on whether we’re talking about the developer or the consumer. We’ll start with the developer.

Code Signing and Developers

The general code signing process that’s carried out during the software development cycle is typically as follows:

  1. The developer generates a certificate signing request (CSR) and private-public key pair.
  2. The CSR (which includes the public key) is sent to the Certificate Authority (CA), who verifies the identity of the developer and issues the code signing certificate.
  3. The developer hashes their code. This must be performed prior to signing. Basically, a hashing algorithm is used (most commonly SHA-256 nowadays) to convert the code into an arbitrary, fixed value (and is a one-way process). The result of the hashing is called a digest.
  4. The code signing certificate is used to create a signature block. The signature block is attached/included with the software file.
  5. The software has now been code-signed and is ready for distribution.

Code Signing and Consumers

Code signing more straightforward for users. Most operating systems will check for a code signing certificate prior to software installation. When a code signing signature is detected in the application, the OS will:

  1. Verify the legitimacy of the certificate.
  2. Use the public key from the CA to decrypt the digest.
  3. Use the same hash function to generate a new digest from the code.
  4. Compare the new digest with the original that was generated by the developer.
  5. If they match, then it confirms that they code hasn’t been tampered with.
  6. The OS proceeds with installation.
code signing certificate details
Viewing the properties of a code signing certificate.

The Top 11 Code Signing Best Practices

Now that we know all about how code signing works and why it’s so beneficial, let’s get into the code signing best practices. These should always be used by your organization in order to maximize the effectiveness of your code signing certificates.

1. Limit Key Access

  • Restrict access to private keys based on roles
  • Minimize the number of machines that store code signing keys
  • Minimize the number of staff members that can access the keys
  • Employ physical security controls in order to minimize key access such as key card-protected doors and locked drawers/cabinets
  • Always keep the private key behind lock-and-key

2. Maximize Key Security

  • Protect private keys with secure vaults and Hardware Security Modules (HSMs), which are special cryptographic processors solely designed for safeguarding keys
An example of a Hardware Security Module (HSM).
  • Key-protection products should be at least FIPS-140 Level 2 certified
  • For transportation of private keys, use hardware that is protected with a strong password of at least 16 characters and contains uppercase and lowercase letters, numbers, and special characters
  • Ensure that private keys are never (for any reason) added to easily accessible places like GitHub, PasteBin, publicly accessible servers, etc.

3. Perform Time-Stamping

  • Time-stamps allow for verification of code even after the original code signing certificate has expired or was revoked
  • Time-stamp certificates can be used to validate for up to 11 years after issuance

4. Use Test-Signing Only When Appropriate

  • Test-signing certificates are either self-signed or come from an internal, private CA and should therefore only be used in a secure test environment
  • Test-signing certificates don’t require the same level of security as production code signing certificates
  • Test-signing certificates cannot chain to the same root as your production certificates
  • The test-signing infrastructure should be completely separate from the production infrastructure

5. Review Code Prior to Signing

  • Code should be thoroughly reviewed and authenticated prior to signing
  • A code signing submission and approval process should be created and used to avoid the signing of unapproved and/or malicious code
  • All code signing activities should be logged in case of future audits or security incidents

6. Scan First

  • It’s important to remember that code signing doesn’t ensure the safety of what’s inside – you can code sign a virus or malware if you really wanted to
  • Be extra careful when incorporating open-source code from external sources
  • Perform virus and malware scanning prior to code signing
  • Malware scanners can’t detect everything, so ensure that each code/component change has been manually vetted

7. Don’t Rely on One Certificate

  • Using multiple certificates helps to distribute risks
  • Multiple certificates can help make it easier to track any issues that may arise

8. Don’t Hesitate to Revoke

  • Any compromised certificates should be immediately revoked and reported to the certificate authority
  • “Compromised” means any suspicion that the private key may have gotten into the hands of an unauthorized user, or that the certificate was used to sign an application containing malware or other malicious code
  • Use time stamps to determine the latest possible revocation date that can be used in order to minimize the impact on safe code

9. Centralize Certificate Management

  • Certificate management platforms, such as DigiCert’s CertCentral or Sectigo Certificate Manager, use automation to simplify the certificate management process, reduce errors, and improve security of keys
  • Continuously monitor the status of your code signing certificates, another area where certificate management platforms help – they give you visibility and can provide alerts for possible issues
  • Regularly audit key usage to ensure policies are accurate
How a user requests a code signing certificate within DigiCert’s CertCentral certificate management platform.

10. Keep Up to Date

  • Stay informed regarding any new cryptographic algorithms or industry practices to ensure you have the best available protection
  • Immediately respond if any new security flaws or vulnerabilities are discovered

11. Create Organizational Policies and Procedures

  • Create a written policy document that everyone in the organization should follow – it should be a “living document” that adapts to any internal or external changes
  • Your code signing policy should address:
    • Who can sign code
    • What code signing tools are approved for use
    • Which kind of certificates are permitted
    • Who is the approver of code signing requests
    • How/where private keys are stored & protected
  • Train your staff on these best practices once per year

All Signs Point to Best Practices

As with any security measure, code signing is only as effective as its implementation and use. No company intends to fall victim to software tampering and end up like SolarWinds or Asus, but it only takes one mistake to leave yourself exposed. As Nelson of DigiCert says:

For those of you who may be down the road with some of these bad practices — stop. Get control of what you’re doing and minimize the risk for your business. SolarWinds isn’t the only organization with bad code signing practices — let’s use this compromise to improve the way we operate and keep our businesses safe.

The human element in the code signing process is most often the weak link, but technical mistakes can doom you as well. By following the best practices that we’ve outlined, you can minimize risk and educate your staff about how to sign code as effectively as possible. That way, you can consistently protect your software, your customers, and the brand that you’ve worked so hard to build.