Skip to content

47-Day Certificates Are Coming. Are You Ready?

Act Now →

All you need to know about NuGet Signing

All about Nugget Signing

What is NuGet?

NuGet is the official package manager for the .Net ecosystem. It provides platforms and tools that help developers to create, publish, and consume .Net Packages. You must be wondering now, what’s a package! Packages can generally be compiled libraries packed with descriptive metadata into a nice shareable unit. NuGet’s job is to make those libraries as accessible and easy to share as possible in the form of packages. NuGet helps developers leverage an entire ecosystem and build on the existing solutions instead of building everything from scratch.

Go through the article below to better understand what NuGet Signing is.

Signing a NuGet package, in short: run nuget sign <package.nupkg> -CertificatePath <cert.pfx> -Timestamper <timestamp_url> (or the newer dotnet nuget sign equivalent), then verify with nuget verify -Signatures <package.nupkg>. The signing certificate must be valid for the id-kp-codeSigning EKU, have an RSA key of 2048 bits or higher, and must not carry the lifetime-signing EKU.

Key Takeaways

  • A NuGet package may have exactly one primary signature (author or repository); co-signing is explicitly disallowed by the specification.
  • The certificate must NOT have the lifetime-signing EKU (1.3.6.1.4.1.311.10.3.13). This is a hard requirement, not a recommendation, and a certificate with this EKU will be rejected.

Environment Matrix

ComponentRequirement
Toolingnuget.exe CLI, or dotnet nuget sign/verify (available in .NET SDK)
Certificate EKUid-kp-codeSigning (RFC 5280 §4.2.1.12); must NOT have the lifetime-signing EKU
Certificate keyRSA, 2048 bits or higher
Supported hash algorithmsSHA-2-256, SHA-2-384, SHA-2-512
Timestamp certificateid-kp-timeStamping EKU, RSA 2048-bit minimum
Primary signatures per packageExactly one (author or repository); co-signing not supported

Let’s talk about the Package Flow

In its public role, NuGet is like a big library (nuget.org) with over 100,000 different packages. These packages are used by lots of .NET/.NET Core developers every day. NuGet also lets you have your private library in the cloud (like on Azure DevOps), on a private network, or just on your computer. This way, only certain developers with access to the library can use those packages, and you can share them with a specific group. You can learn more about these options by Hosting your own NuGet feeds. By setting things up a certain way, you can control which libraries a computer can get packages from, ensuring they come from specific sources and not just the big public library (nuget.org).

No matter what, a library is like a meeting place for package creators and package users. Creators make helpful NuGet packages and put them in a library. Users then look for useful packages in accessible libraries, download them, and add them to their projects. Once in a project, these packages’ tools are ready to be used in the rest of the project code.

Before we dive deep into NuGet signing, let’s understand what Code signing is.

Code signing is a cryptographic process that involves attaching a digital signature to software to verify its origin and ensure it hasn’t been tampered with. This digital signature is generated using a private key and can be verified using the corresponding public key, providing users with confidence in the authenticity and integrity of the code.

Key Benefits of Code Signing:

  1. Authenticity

    Code signing verifies the software publisher’s identity, ensuring that users can trust the source of the code.

  2. Integrity

    Attaching a digital signature to the code can detect unauthorized modifications, safeguarding against tampering.

  3. Tamper-proof Distribution

    Code signing allows developers to distribute their software securely, reducing the risk of malicious alterations during transit.

Understanding NuGet Signing

As discussed above, NuGet is a popular package manager for .NET development, allowing developers to share and consume code easily. NuGet signing is an extension of code signing tailored for NuGet packages. When a NuGet package is signed, it includes a digital signature that provides the same benefits as traditional code signing, ensuring the authenticity and integrity of the packaged code.

General requirements of NuGet Signing

  1. Ensure that a signed package remains compatible with package readers and writers lacking support for package signing

  2. Integrate the package signature intricately within the package file.

  3. Strictly adhere to the rule that each signed package should contain precisely one primary signature. (co-signing explicitly disallowed)

  4. Ideally, designate the primary signature as either an author or repository signature.

  5. When applying an author signature, ensure it serves as the primary signature. Remove the existing primary signature before adding an author signature to an already signed package.

Certificate minimum requirements

A NuGet signing certificate MUST meet the following minimum requirements:

  1. The certificate MUST be valid for the id-kp-codeSigning purpose [RFC 5280 section 4.2.1.12].

  2. The certificate MUST have an RSA public key length of 2048 bits or higher.

A timestamping certificate MUST meet the following minimum requirements:

  1. The certificate MUST be valid for the id-kp-timeStamping purpose [RFC 5280 section 4.2.1.12].

  2. The certificate MUST have an RSA public key length of 2048 bits or higher.

At signing time, a certificate MUST be within its validity period according to the package writer and MUST NOT be revoked. At validation time, the certificate’s revocation status SHOULD be rechecked; however, package readers MAY fail to open if revocation status is unavailable (e.g., a CRL is inaccessible).

Certificates MUST NOT have the lifetime signing EKU (1.3.6.1.4.1.311.10.3.13).

Enterprise Code-Signing Solution

Get One solution for all your software code-signing cryptographic needs with our code-signing solution.

Supported Algorithms:

The following hash algorithms MUST be supported:

Hash AlgorithmHash-Algorithm-Oid
SHA-2-2562.16.840.1.101.3.4.2.1
SHA-2-3842.16.840.1.101.3.4.2.2
SHA-2-5122.16.840.1.101.3.4.2.3

NuGet Signing Workflow – Signing a package

The following steps are outlined for the author signing a package.

Step 1: Determine if the package is signed

  1. If the package is signed and the sign operation should not overwrite an existing signature – the sign operation fails with a message that “the package is already signed.”
  2. If the package is signed and the sign operation should overwrite an existing signature – remove the existing signature and follow step 2
  3. If the package is not signed, continue with step 2

Step 2: Verify the signing certificate satisfied the minimum requirements (as mentioned above)

Step 3: Verify that the supported hash, signature, and timestamp hash algorithms are used. (as mentioned above)

Step 4:  Generate Package signature File

  1. Create author signature
  2. Obtain a timestamp from the author signature

    Please verify that the timestamp signing certificate satisfies certificate minimum requirements (as mentioned above) and uses the supported hash algorithm.

  3. Extend the author signature to CAdES-T [RFC 5126]
  4. Encode the author signature CMS SignedData
  5. Write the encoded author signature to the file

Step 5: Add the package signature file as an uncompressed (stored) file to the package being signed

Step 6: Validate the signed package

  1. Determine if the package is signed ( if not signed, stop the validation immediately)
  2. Verify the package signature file is an uncompressed and regular file.
  3. Verify the package signature format is supported.
  4. Verify package integrity
  5. Verify primary signature validity and trust
  6. If no failures have been encountered, treat the package as a valid signed package.

The Actual Signing and Verification Commands

Using a certificate file directly:

nuget sign MyPackage.nupkg -CertificatePath cert.pfx -CertificatePassword <password> -Timestamper http://timestamp.digicert.com

Using a certificate already installed in the certificate store (typical when the KSP registers an HSM-backed key there):

nuget sign MyPackage.nupkg -CertificateStoreName My -CertificateStoreLocation CurrentUser -CertificateSubjectName "<certificate subject>" -Timestamper http://timestamp.digicert.com

The newer .NET SDK exposes the same functionality via dotnet nuget sign <package.nupkg> --certificate-path cert.pfx --timestamper http://timestamp.digicert.com. Verify a signed package with:

nuget verify -Signatures MyPackage.nupkg

A successful verification reports the signature is valid and names the signing certificate; a failure names the specific validation step that failed (signature format, package integrity, or trust) rather than a generic error, which is useful for diagnosing which requirement above wasn’t met.

Common Errors

ErrorLikely CauseFix
“The package is already signed”Attempting to sign a package that already has a primary signature without removing it firstRemove the existing signature before re-signing, since co-signing isn’t supported
Certificate rejected during signingCertificate has the lifetime-signing EKU, an RSA key under 2048 bits, or lacks the id-kp-codeSigning EKUConfirm the certificate meets all three minimum requirements before attempting to sign
Verification fails with a trust errorThe certificate chain doesn’t resolve to a trusted root, or the certificate was revoked after signingConfirm the certificate authority is trusted by the environment verifying the package, and check revocation status

CI/CD Use and Cleanup

For repeated signing in a pipeline, supply the certificate path and timestamp URL as pipeline variables rather than hardcoding them, and add nuget verify -Signatures as a required stage immediately after signing so the build fails rather than publishing an unverifiable package. If a .pfx certificate file was copied to a build agent for testing, remove it once the pipeline is confirmed working, and prefer certificate-store-based signing (which keeps the key HSM-backed) over file-based signing in production pipelines.

Frequently Asked Questions

Can I sign a NuGet package with more than one certificate?

No. Co-signing is explicitly disallowed by the NuGet signing specification; a package may have exactly one primary signature, either an author or repository signature.

Why does the specification prohibit the lifetime-signing EKU?

The lifetime-signing EKU is designed to make a signature remain valid indefinitely regardless of certificate expiration, which conflicts with NuGet’s model of validating certificates against their stated validity period and revocation status at signing time.

Conclusion

NuGet is an open-source and free package manager for the .NET ecosystem. In a world where software supply chain attacks are rising, implementing robust security measures like code signing and NuGet Signing is essential. These practices instill trust in the software supply chain, giving developers and end-users confidence in the authenticity and integrity of the code they consume.

CodeSign Secure helps sign NuGet Package without any hassle, With Encryption Consulting’s CodeSign Secure solution, we offer a highly effective and efficient approach to signing NuGet packages. Our solution not only ensures the security of your packages through robust cryptographic measures but also streamlines the signing process, enhancing the overall efficiency of your software development lifecycle.

References:

RFC 5126 – CMS Advanced Electronic Signatures (CAdES) (ietf.org)

RFC 5280 – Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile (ietf.org)

RFC 3161 – Internet X.509 Public Key Infrastructure Time-Stamp Protocol (TSP) (ietf.org)