-
Notifications
You must be signed in to change notification settings - Fork 252
NuGet Sign Command
Status: Review
Task for Specing and Task for execution
Currently there is no way for package authors to sign their packages. Signed packages help with authenticity and integrity of a package when it is being consumed by NuGet users. Further, in future, this command will also facilitate package sources to sign the package to prevent package tampering once it has been published.
All NuGet package authors.
Part of the larger package signing effort.
We will add a first level command to NuGet.exe which will allow package authors and package sources to sign NuGet packages.
usage: NuGet sign <package_path> -Timestamper <timestamp_server_url> [-CertificatePath <certificate_path> | [ -CertificateStoreName <certificate_store_name> -CertificateStoreLocation <certificate_store_location> [-CertificateSubjectName <certificate_subject_name> | -CertificateFingerprint <certificate_fingerprint>]]] [options]
Signs a NuGet package.
argument:
package - Path to the package that needs to be signed.
options:
-OutputDirectory - Directory where the signed package should be saved. By default the original package is overwritten by the signed package.
-CertificatePath - File path to the certificate to be used while signing the package.
-CertificateStoreName - Name of the X.509 certificate store to use to search for the certificate. Defaults to "My", the X.509 certificate store for personal certificates.
This option should be used when specifying the certificate via -CertificateSubjectName or -CertificateFingerprint options.
-CertificateStoreLocation - Name of the X.509 certificate store use to search for the certificate.. Defaults to "CurrentUser", the X.509 certificate store used by the current user.
This option should be used when specifying the certificate via -CertificateSubjectName or -CertificateFingerprint options.
-CertificateSubjectName - Subject name of the certificate used to search the default local certificate store for the certificate.
The search is a case-insensitive string comparison using the supplied value, which will find all certificates with the subject name containing that string, regardless of other subject values.
-CertificateFingerprint - SHA-1 fingerprint of the certificate used to search the default local certificate store for the certificate.
-CertificatePassword - Password for the certificate, if needed.
This option can be used to specify the password for the certificate. If no password is provided, the user may be prompted for a password at run time, unless the -NonInteractive option is passed.
-CryptographicServiceProvider - Name of the cryptographic service provider which contains the private key container.
This option, along with -KeyContainer, can be used to specify the private key if the certificate file does not contain one.
-KeyContainer - Name of the key container which has the private key.
This option, along with -CryptographicServiceProvider, can be used to specify the private key if the certificate file does not contain one.
-Timestamper - URL to an RFC 3161 timestamp server.
-TimestampHashAlgorithm - Hash algorithm to be used by the RFC 3161 timestamp server. Defaults to SHA256.
-HashAlgorithm - Hash algorithm to be used while generating the package manifest file. Defaults to SHA256.
-Overwrite - Switch to indicate if the current signature should be overwritten. By default the command will fail if the package already has a signature.
-NonInteractive - Do not prompt for user input or confirmations.
Sign Command returns one of the following exit codes when it terminates.
Exit code | Description |
---|---|
0 | Execution was successful. |
1 | Execution has failed. |
The errors and warnings will be displayed on the console.
- The users should use 1 of the 2 following ways to specify the certificate to be used to sign the package -
-
-CertificatePath
-
TheCertificatePath
option is used to uniquely identify a certificate. The parameter accepts a relative or absolute file path. -
-CertificateSubjectName | -CertificateFingerprint
-
CertificateSubjectName
andCertificateFingerprint
options can be used to search the local certificate store. While searching the local store, if more than one matching certificates are found then we should prompt the user with the options and ask them to provide a more specific filter. Users can also use the-CertificateStoreName
and-CertificateStoreLocation
options to specify the certificate store name and location to be used to search for the certificate.
-
- In all the cases we should display the certificate being used.
- The users should use 1 of the 2 following ways to specify the private key to be used to sign the package -
- Primarily they should provide a certificate which contains a private key, in such a case we will use that to sign the package.
- However, if the certificate does not contain a private key then the user can provide the
CryptographicServiceProvider
andKeyContainer
values to be used to find the private key. While providingCryptographicServiceProvider
andKeyContainer
values, the user must ensure that the resolved private key must match the certificate file passed. Else the sign command will fail.
-
Overwrite
option can be used to specify if an existing signature should be overwritten. If this switch is not used then we should fail if there is an existing signature.
The command will support for the following certificates sources -
- Certificate file - Path to the certificate file on the local file system or a network share.
- Certificate store-
CertificateSubjectName
andCertificateFingerprint
options can be used to search the local certificate store. Users can also use the-CertificateStoreName
and-CertificateStoreLocation
options to specify the certificate store name and location to be used to search for the certificate. - Hardware Security Module - Under Investigation.
- CSP - User can provide the Cryptographic Service Provider name and the key container name. Sample Code
The sign command should be atomic in nature i.e. If the command fails then the original package should not be modified. Possible options for this -
- Do not allow in-place signing and mandate the
-OutputDirectory
options. - Back up the original package and overwrite it back if signing fails midway. This can be costly for large packages.
- Create the manifest and signature files out of package and write into the package once all the files are ready.
The sign command should perform the following validations before attempting to sign the package -
- Validate that the package exists on disk and the process has Read/Write access to the package.
- If
-OutputDirectory
if passed, validate that the process has write access to the path. - Validate that the user has supplied a valid certificate through all of the options.
- If the certificate is password protected, validate that the user supplied a password using the
-CertificatePassword
option. Or prompt the user, when possible. - Validate that the resolved certificate is currently valid.
- Validate that the certificate contains a private key or the user has provided the
-CryptographicSignatureProvider
and-KeyContainer
options. - Validate that the user has passed a valid timestamper url using the
-Timestamper
option. - Logical validation on all the supplied options.
In future we would like to add support for the following platforms -
-
Dotnet CLI -
dotnet nuget sign <package_path> [Options]
-
MSBuild target -
msbuild /t:nugetsign <package_path> [Options]
The sign command will do the following -
- Check if the passed arguments are valid. If not then throw.
- Wrap them into a
SignArgs
object. - Invoke
var signResult = SignCommandRunner.Execute(SignArgs);
. - If
signResult.Status == Failure
, then show an error indicating the failure.
The SignCommandRunner will do the following -
- Convert the package path into an in memory Package Object/stream.
- Convert the certificate into an in memory Certificate object.
- Pass the SignArgs to NuGet.Sign API.
- return result to the caller.
1. Whats the best way to pass the certificate password to the sign command?
Currently the spec only accepts a commandline switch with clear text password. But we can also support having an
encrypted password stored in a nuget.config file.
We will allow users to pass a clear text via commandline or prompt them to input it in secure string format during runtime.
2. What kind of validation will we do before signing?
We should spec out all the validations that will be done before signing.
3. Do we need to add retry mechanism for the timestamper service?
Number of retries to get a timestamp for the signature.
Delay (in seconds) between the retries to get a timestamp for the signature.
Please use the tracking issue to provide feedback or any questions that you might have. Thanks!
Check out the proposals in the accepted
& proposed
folders on the repository, and active PRs for proposals being discussed today.