What is Code Signing?
Code signing is the digital equivalent of having an official letterhead on a document, then having it laminated. It's ensuring that it was written by who it says it was (the letterhead and author) as well as ensuring it has not been changed (laminated). To accomplish this in the digital world, we utilize cryptography. A level deeper specifically, encryption/decryption and Public Key Infrastructure (PKI) are used in combination to "sign" digital files.
Why should I sign my code?
There are multiple reasons to sign your code. The main two reasons are:
- Ensure that the code has not been changed between its author and the recipient(s). That is, no malware has been attached and/or that the file hasn't been corrupted.
- Ensure that it was created by the entity claiming to be the author. This way, you know it's authentic.
What does this do for security?
For one, it ensures that no malware has been injected into the code itself. In fact, some operating systems and even applications will prevent unsigned files from running. This results in a couple of situations for secops staff; either shut off that functionality (resulting in a security hole) or manage an exception list of unsigned code that's allowed to run (resulting in a considerable amount of effort on your secops group to manage). Releasing only signed code prevents both situations.
Signing files means that anyone who receives the file knows that it was authored by the entity in the certificate; any changes would result in a mismatched signature meaning the document was tampered with. Ideally, an end-user would have enough information at that point to realize the file has been tampered with and to not use it.
What is the actual process of code signing?
Code signing may seem complex, but it's quite simple when broken down. Specific tools are used (examples; Microsoft uses a tool called "Signtool.exe" to sign most of their executables and libraries, while there is a Java tool called "Jarsigner" that signs Java Archive files, etc.) Each tool does the same basic thing but may have specific way of appending signatures to code.
Code signing starts with the hashing (that is, using a one-way hash algorithm, typically SHA-256) to generate a hash. These hashes are easily replicable as there is no "key" to a hash so anyone who hashes the same file will get the same hash result. However, a hash is one way, meaning that you can't reverse the operation and get the file back from the hash. This alone can be used to ensure the file hasn't been changed - however it does not attribute the file to any one individual or organization.
Enter code signing - that same hash from the discussion above is ENCRYPTED with the private key. Why the private key? Because in asymmetric cryptography, encrypting with one key (in this case, the private key) means you can ONLY decrypt with the other (in this case again, the public key).
To verify, you'll use the certificate associated with the private key to DECRYPT that hash. If the hash your system decrypted (using the certificate) matches the hash your system generated (again, hashes are the same as long as the same algorithm is used, i.e. SHA-256) then you know not only that the file hasn't been tampered with but that it indeed came from the entity identified in the certificate. This is why it is crucial to protect private keys and prevent them from being used by unauthorized users.
Please also read the blog on Dual Control on Code Signing
Where do I get started?
First, you'll need a certificate to properly sign code. This ensures that the code you sign is authentic to you (or your entity.) This is where some confusion can set in about what a "certificate" is; let me explain:
A certificate (by itself) is typically nothing but the public key (of a private/public key pair) with attributes (you, your organization, email, phone number, etc.) added to it THEN signed by (ideally) a public Certificate Authority (CA). Ideally, the private key is NEVER exposed to anyone but yourself (or your organization).
The "private" key is named so as it is meant to be protected by any means necessary - not just left on a file system where it can be accessed by anyone. Leaving it prone means anyone could sign code with it (and therefore, imitate you or your organization!) as well as not having any auditing capabilities or even knowing WHO has it.
Traditionally, a CA could create that public/private key pair themselves for you, then send you a resulting file that many referred to as a "certificate" - but in reality, this is both the CA signed certificate AND the private key in a password protected file known as a PFX file.
That private key has been out of your control and was not generated by you, so you don't truly know if it has been exposed or not. Not to mention, using only a password to protect that private key is ineffective at best, as it exists in a file that can be passed around (or worse, exfiltrated) and brute-force cracked. Remember, protecting the private key is the most important aspect.
Now comes the regulation; the Certificate Authority/Browser (CA/B) forum mandates that all private keys for code signing be stored in a Federal Information Processing Standards (FIPS) 140-2 Level 3 Hardware Security Module (HSM.)
The whole point of this regulation is to ensure that your private key stays private - and not in a relatively insecure file (PFX file as mentioned above.) That way the CA's can ensure that their customers are doing their job to keep that private key - PRIVATE. Keep in mind, that with code signing – the private key is what actually does the “signing” so to speak, not the certificate.
[See section 6.2.7 in the CA/B's 'Baseline Requirements for the Issuance and Management of Code Signing Certificates']
What does that mean? First off, FIPS is a standard set by the US government. 140-2 is the specific section regarding cryptographic key generation and storage; level 3 means that the storage medium MUST be some sort of hardware (it can be anything from a simple certified USB stick, up to a network appliance).
Levels 1 and 2 can be software based but are obviously far less secure - while level 4 (the highest) has extremely stringent requirements (think top secret government agencies, where taking the device on a plane or probing it would erase all the keys to prevent exposure!)
Most customers request and most regulations require level 3 for their HSM's. While it is a federal standard, it’s a standard that everyone can agree on. Hardware devices have the advantage of being able to fully control the generation of keys (and use a "true" random number generator as opposed to a "pseudo" random number generator) as well as the storage of the keys.
Keys generally do not leave the HSM, but operations needing cryptographic keys are sent to the HSM where they are processed instead. This may seem like it would add significant delay to the process, but there are many methods that make it nearly invisible to the overall operation.
Since I mentioned that the "hardware" element can be a USB stick, most CA's will gladly send you a code signing certificate (with the private key) on a USB stick, but at a significant cost. USB HSM's themselves are not cheap at all, and not a cost-effective solution by any means.
That is, not to mention that there's no knowing who used that key nor is there any kind of auditing/logging of usage; that is, if you manage to keep control of it by users. A network appliance type HSM is ideal for this, as not only can it securely generate the public/private key pair itself, it can keep that private key secure, apply RBAC to its use and since it never actually leaves the HSM itself - maintain an immutable audit log of all management and usage of that private key as well.
A USB HSM cannot do either of these things and is also prone to being lost - not to mention it can only be used by one person (or process) at a time.
The process of acquiring a "certificate" at this point is a little different than you may be used to though; instead of just reaching out to your public CA to get one (where they generate your private/public keys) you would generate those public and private keys inside of your own HSM.
From there, you'll create what's called a Certificate Signing Request (CSR) which is basically your information (your name, organization, email address, etc.) added to the public key of your private/public key pair. This isn't a certificate itself; this CSR is then sent to your CA (note, the private key has never left your HSM!) to be signed and then become a certificate.
Once you have it back - depending on the HSM, you can even import the certificate for safe keeping. Note that since the certificate itself is based on the PUBLIC key, it doesn't matter if it "gets out" so to speak. It's meant to be passed around for usage.
Side note: In asymmetric cryptography, you can derive the public key FROM the private key, but not the other way around. This is why it's critical to keep that private key stored somewhere where it can't be compromised or stolen.
Now, you have your private key generated and stored inside a secure HSM, and a certificate. How do you sign code with it? The process is almost identical to however you were doing it previously - the big difference is you'll install a small crypto agent (a Cryptographic Service Provider, or CSP) that will allow your existing signing tools to talk to your HSM, where your private key exists.
The syntax will be slightly different for your tool, but now the signing tool will generate the hash and send that up to your HSM to be "signed" (encrypted) with the private key. That means the private key stays on the HSM, has a log associated with it for every time it's used as well as every time it's managed.
It also means you have full control over WHO has the capability to manage and/or utilize that key. Thankfully, hashes are tiny (less than 1kB easily) and since you're sending it up to an appliance that's designed to run cryptographic operations, there is almost no latency added to the process.
So Fortanix is an HSM then, right?
Right! At our core, that is. Fortanix is a full encryption PLATFORM that has far more functionality (related to cryptography) than a typical HSM. Logging, RBAC, quorum approvals (that prevent one person from having too much control) all enhance what our FIPS 140-2 Level 3 HSM can do, however we are also the Key Management Service (KMS) on top of that HSM that makes it so much easier and intuitive to manage the keys in our HSM.
No matter the encryption use case, Fortanix can help, including (of course) generating and securing your private keys used for code signing. This assures that your private keys are never in the hands of those who aren't authorized, and you have a log of all usage and management from the very beginning; when that key was generated.
On top of that, we generate attestation logs (these verify that the private key was generated inside a Level 3 HSM) for your private keys that can be sent to your CA to assure them that your keys are secure. Couple all of these advantages with an easy-to-deploy SaaS solution that is fully HA/DR across the globe with multiple options and you have a very resilient HSM solution to protect your code signing keys!