Signing a nupkg and Uploading to Nuget.org
Tags: nuget, nupkg, publickey
Published: 2018-08-18 08:47:34

---
title: Signing a nupkg and Uploading to Nuget.org
published: true
tags: nuget,nupkg,public-key
canonical_url: 
---

[A few days ago](./nupkg-containing-native-libraries-1576) I detailed how to create a nupkg containing a native library. Next we’ll sign and upload it to [nuget.org](https://www.nuget.org/).

Nuget.org also has [an excellect post](https://blog.nuget.org/20180522/Introducing-signed-package-submissions.html) on the topic.

Motivations:

- Make our own libraries more accessible to others. Previously we provided instructions on cloning the repo and bringing it into an existing project- using nuget would be easier.
- Simplify our codebase. Our main .sln has 55 projects; perhaps 10 of which are third party libs that we made minor changes to but otherwise rarely touch.

## Organization

We want all our packages to be owned by the [Subor organization](https://www.nuget.org/profiles/subor) so everything won’t be tied to a single person.

After creating an organization (profile **->Manage Organizations->Add new** ), you can click the pencil icon to access the organization’s settings page and configure various things:  
 ![](https://rendered-obsolete.github.io/assets/nuget_edit_icon.png)

## Certificate Creation and Registration

Assuming you have a _PKCS #12_ file (with a .pfx extension) for signing, you need to export a .cer to register with nuget.org. On Windows, double-clicking the pfx should launch the Certificate Import Wizard, or you can run `certmgr.exe` and click **Import…**.

Once imported, select the key and click **Export…** :  
 ![](https://rendered-obsolete.github.io/assets/certmgr_export.png)

When prompted select **No, do not export the private key** :  
 ![](https://rendered-obsolete.github.io/assets/certmgr_export_no_private.png)

And **DER encoded X.509** :  
 ![](https://rendered-obsolete.github.io/assets/certmgr_export_format.png)

Then click through to create the .cer. Now, go to the organization’s settings page on nuget.org and pick **Certificates->Register new**. Select the .cer you just created.

## Nuget.org API Key

While you’re visiting nuget.org it’s worth creating an API key **profile->API Keys->+Create** :  
 ![](https://rendered-obsolete.github.io/assets/nuget-org_apikey_create.png)

For **Package Owner** pick the organization. Uploaded packages will belong to the organization rather than your individual account.

For **Select Scopes** I’ve got **Push only new package versions** because I’m planning to use this on our build machine and it really has no reason to create new packages.

Click **Create** then **Copy** to save the API key to your clipboard. You cannot get this key again later; if you forget it you just have to **Regenerate** it (invalidating the old one):  
 ![](https://rendered-obsolete.github.io/assets/nuget-org_apikey_regenerate.png)

## Signing

I’ve got `Subor.NNanomsg.NETStandard.0.5.2.nupkg` from the [other day](./nupkg-containing-native-libraries-1576) and our private key (the pfx). To sign the package:

```
nuget.exe sign Subor.NNanomsg.NETStandard.0.5.2.nupkg -Timestamper http://sha256timestamp.ws.symantec.com/sha256/timestamp -CertificatePath path_to_private_key.pfx

```

Output should be similar to:

```
Please provide password for: path_to_private_key.pfx
Password: ********************************
 
 
Signing package(s) with certificate:
  Subject Name: CN=???????????????????, O=???????????????????, L=??, C=CN
  SHA1 hash: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  SHA256 hash: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
  Issued by: CN=DDDDDDDDDDDDDDD SHA256 Code Signing CA, OU=EEEEEEEEEEEEEEEEE, O=FFFFFFFFFFFFFFFFFF, C=US
  Valid from: 12/34/56 00:00:00 to 12/34/56 00:00:00
 
Timestamping package(s) with:
http://sha256timestamp.ws.symantec.com/sha256/timestamp
Package(s) signed successfully.

```

After signing the size of the nupkg file should increase slightly (in this case 10KB).

If you get output that ends with `Key does not exist.`, make sure the .pfx (the private key) follows `-CertificatePath` and not the .cer (public key).

You can verify the package with:

```
nuget.exe verify Subor.NNanomsg.NETStandard.0.5.2.nupkg -All

```

And there should be a bunch of similar output that ends with `Successfully verified package 'Subor.NNanomsg.NETStandard.0.5.2'.`.

## Uploading

The first time I uploaded the package I used nuget.org’s web interface: profile **->Manage Packages->+Add new**.

Thereafter I can use the “update package versions”-only API key I created to push updates:

```
nuget.exe push Subor.NNanomsg.NETStandard.0.5.2.nupkg -Source "https://www.nuget.org" -ApiKey abcdef01234567890abcdef01234567890

```

If everything is working:

```
Pushing Subor.NNanomsg.NETStandard.0.5.2.nupkg to the NuGet gallery (https://www.nuget.org)...
  PUT https://www.nuget.org/api/v2/package/
  Created https://www.nuget.org/api/v2/package/ 3158ms
Your package was pushed.

```

The package is validated before becoming available via nuget.org. This seems to take around 5 minutes for a small package like this, although I’d imagine it might take longer for large packages or during peak usage. You can keep an eye on its status via the package’s page: [https://www.nuget.org/packages/Subor.NNanomsg.NETStandard/0.5.2](https://www.nuget.org/packages/Subor.NNanomsg.NETStandard/0.5.2).

## The Circle is Now Complete

Back in Visual Studio, you can now:

1. Right-click a project **->Manage NuGet Packages…->Browse**.
2. Make sure **Package source** is `nuget.org` (in case you changed it during package development). And search for `Subor.NNanomsg.NETStandard`:  
 ![](https://rendered-obsolete.github.io/assets/vs_nuget_browse.png)

3. **Install** it and build the project (don’t forget to [set **Platform target**](./nupkg-containing-native-libraries-1576#consuming-nupkg)!).
4. Browse to the output folder and `nanomsg.dll` should be there.

Pretty slick.