Skip to content
This repository has been archived by the owner on Jul 26, 2020. It is now read-only.
/ NuSign Public archive

DEPRECATED - NuGet package signing prototype

License

Notifications You must be signed in to change notification settings

jariq/NuSign

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NuSign

WARNING: NuSign is just proof of the concept which SHOULD NOT be used in production!

Table of Contents

What is NuSign?

NuSign is a command line application that digitally signs NuGet packages. It can also verify the signature of any previously signed NuGet package.

All NuGet package signing related resources I've managed to find are rather old:

I've decided to create NuSign hoping its existence might help revive both upstream discussion and upstream implementation of NuGet package signing.

I've followed these simple design goals:

  • signature needs to be embedded in the package so it does not get lost and can be verified even on packages imported to local repositories
  • signed package needs to be backwards compatible so it can be consumed by the client tools without the support for package signatures
  • signing technology needs to be based on X.509 code-signing certificates just like like assembly signatures are

Why do NuGet packages need to be signed?

NuGet package repository hosted at nuget.org is currently vulnerable to several attacks such as typosquatting attack because:

  • anyone can submit package and it gets accepted automatically without any kind of human review
  • packages can indirectly execute arbitrary code
    • on developer machine via MSBuild props and targets present in a package
    • on end-user machine via .NET assemblies included in package

Does NuGet package signature make assembly signature obsolete?

No, it does not. Ideally all packages will use both signature types in the future.

Assembly signature created with SignTool protects integrity and origin/authenticity of .NET assembly (.dll file). It can be verified in the runtime (where NuGet package does not exist anymore) or manually by the end-user.

Package signature created with NuSign protects integrity and origin/authenticity of all files present in the NuGet package (assemblies, MSBuild props and targets and all the other files). Package level signature can be verified during the development when package is added as a reference.

How do I sign a package?

Let's assume you have a valid code signing certificate present in your CurrentUser\My certificate store and you want to sign MyLibrary.1.0.0.nupkg. You can initiate package signing with following command:

c:\> NuSign.exe -sign MyLibrary.1.0.0.nupkg
Signing package "MyLibrary.1.0.0.nupkg"...
Package "MyLibrary.1.0.0.nupkg" successfully signed.

Package was signed with the following certificate:
  Issuer:         CN=Certum Code Signing CA SHA2, OU=Certum Certification Authority, O=Unizeto Technologies S.A., C=PL
  Subject:        E=jaroslav.imrich@gmail.com, CN="Open Source Developer, Jaroslav IMRICH", O=Open Source Developer, C=SK
  Serial number:  78E0593A6F048F998C255F8BC2892D82
  Invalid before: Wed, 11 Jan 2017 07:52:59 GMT
  Invalid after:  Thu, 11 Jan 2018 07:52:59 GMT

NuSign will display GUI dialog which will let you select certificate you want to use for signing. If your signing certificate is stored in the smartcard then you might also be prompted to enter PIN code.

Alternatively you can perform signing operation in non-interactive/headless mode by specifying thumbprint of signing certificate with -cert parameter:

c:\> NuSign.exe -sign MyLibrary.1.0.0.nupkg -cert d5de31ea974f5ea8581d633eeffa8f3ea0d479bb

How do I verify package signature?

Validation of package signature can be performed with the following command:

c:\> NuSign.exe -verify MyLibrary.1.0.0.nupkg
Verifying the signature of package "NuSign.TestLibrary.Signed.1.0.0.nupkg"...
Signature of "MyLibrary.1.0.0.nupkg" package is VALID.

Package was signed with the following certificate:
  Issuer:         CN=Certum Code Signing CA SHA2, OU=Certum Certification Authority, O=Unizeto Technologies S.A., C=PL
  Subject:        E=jaroslav.imrich@gmail.com, CN="Open Source Developer, Jaroslav IMRICH", O=Open Source Developer, C=SK
  Serial number:  78E0593A6F048F998C255F8BC2892D82
  Invalid before: Wed, 11 Jan 2017 07:52:59 GMT
  Invalid after:  Thu, 11 Jan 2018 07:52:59 GMT

If you want NuSign to skip validation of signing certificate (whether it's been issued by the trusted CA and whether it hasn't been revoked) you will need to add -skipCertValidation parameter:

c:\> NuSign.exe -verify MyLibrary.1.0.0.nupkg -skipCertValidation

How does the signing work?

NuGet package (.nupkg file) is just an ordinary ZIP archive (.zip file) with the following directory structure:

Structure of unsigned NuGet package

During the signing phase NuSign first creates file package/signatures/IntegrityList.xml which contains list of all other files present in the package along with their cryptographic hashes:

<?xml version="1.0" encoding="utf-8"?>
<IntegrityList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <IntegrityEntry>
    <FilePath>lib/netstandard1.0/MyLibrary.dll</FilePath>
    <HashAlgorithm>http://www.w3.org/2000/09/xmldsig#sha256</HashAlgorithm>
    <HashValue>xODa4SUb8nlwSCNVhQdbNcz7W69008nUtMPPsVkIr4U=</HashValue>
  </IntegrityEntry>
  <IntegrityEntry>
    <FilePath>MyLibrary.nuspec</FilePath>
    <HashAlgorithm>http://www.w3.org/2000/09/xmldsig#sha256</HashAlgorithm>
    <HashValue>qPH6r27f5UdmKOlQIG7NjSZ6y3/2GOG3E5CruBknuYc=</HashValue>
  </IntegrityEntry>
  <IntegrityEntry>
    <FilePath>package/services/metadata/core-properties/11faa6a592fc481090e9683c5b96d7bd.psmdcp</FilePath>
    <HashAlgorithm>http://www.w3.org/2000/09/xmldsig#sha256</HashAlgorithm>
    <HashValue>NvSHHsSrJxMw1eGMqA1mbtxj06CFUF6bCmJh6Z4hd1I=</HashValue>
  </IntegrityEntry>
  <IntegrityEntry>
    <FilePath>[Content_Types].xml</FilePath>
    <HashAlgorithm>http://www.w3.org/2000/09/xmldsig#sha256</HashAlgorithm>
    <HashValue>pZlrOm75NHkBx0F3V4ZX1tGJUxxhvGu+eKANLHevbzo=</HashValue>
  </IntegrityEntry>
  <IntegrityEntry>
    <FilePath>_rels/.rels</FilePath>
    <HashAlgorithm>http://www.w3.org/2000/09/xmldsig#sha256</HashAlgorithm>
    <HashValue>tvI1YA6lHdnIcQyXGPU7LCZTVNz8y1R6M1IaKnxd130=</HashValue>
  </IntegrityEntry>
</IntegrityList>

File package/signatures/IntegrityList.xml is then signed with selected signing certificate and resulting CMS signature is stored in DER encoded (binary) form in file package/signatures/IntegrityList.p7s.

That's it. Final signed package with following directory structure seems to be fully compatible with already existing NuGet tools and also with nuget.org repository:

Structure of signed NuGet package

How does signature verification work?

In the first phase of package signature verification NuSign validates CMS signature of IntegrityList.xml file. It uses Windows certificate store as a source of information about trusted certificate authorities.

In the second phase NuSign computes cryptographic hash for every file present in the package except those in signatures folder. Then it compares computed hashes with the hashes stored in IntegrityList.xml file.

Package signature is considered to be valid only if CMS signature is valid, all hashes match and there is no missing or additional file present in the package.

What is the fastest way to explore NuSign?

There is a precompiled NuSign.exe binary available in samples directory along with the following demonstration packages:

What is going to happen next?

NuSign can be improved in many ways:

  • support for other platforms than Windows can be added
  • support for external trust sources can be added
  • support for PKCS#11 compatible key stores can be added
  • support for signature time-stamps can be added
  • use of code-signing certificates could/should be enforced
  • ...

However I'd like to discuss high level design and technical details with NuGet upstream before I take on the burden of maintaining NuSign as a standalone tool. I hope that package signing will become an integral part of NuGet tool. Meanwhile please feel free to open new issue to report bugs, request new features or just discuss your thoughts.

About

NuSign has been written by Jaroslav Imrich and is available under the terms of MIT license.

About

DEPRECATED - NuGet package signing prototype

Resources

License

Stars

Watchers

Forks

Languages