Add commands for generating secret/public keys

This commit is contained in:
Eelco Dolstra 2021-01-06 17:41:16 +01:00
parent 555152ffe8
commit 9374c2baea
5 changed files with 160 additions and 11 deletions

View file

@ -132,11 +132,6 @@ struct CmdHash : NixMultiCommand
command->second->prepare();
command->second->run();
}
void printHelp(const string & programName, std::ostream & out) override
{
MultiCommand::printHelp(programName, out);
}
};
static auto rCmdHash = registerCommand<CmdHash>("hash");

View file

@ -0,0 +1,19 @@
R""(
# Examples
* Convert a secret key to a public key:
```console
# echo cache.example.org-0:E7lAO+MsPwTFfPXsdPtW8GKui/5ho4KQHVcAGnX+Tti1V4dUxoVoqLyWJ4YESuZJwQ67GVIksDt47og+tPVUZw== \
| nix key convert-secret-to-public
cache.example.org-0:tVeHVMaFaKi8lieGBErmScEOuxlSJLA7eO6IPrT1VGc=
```
# Description
This command reads a Ed25519 secret key from standard input, and
writes the corresponding public key to standard output. For more
details, see [nix key generate-secret](./nix3-key-generate-secret.md).
)""

View file

@ -0,0 +1,48 @@
R""(
# Examples
* Generate a new secret key:
```console
# nix key generate-secret --key-name cache.example.org-1 > ./secret-key
```
We can then use this key to sign the closure of the Hello package:
```console
# nix build nixpkgs#hello
# nix store sign-paths --key-file ./secret-key --recursive ./result
```
Finally, we can verify the store paths using the corresponding
public key:
```
# nix store verify --trusted-public-keys $(nix key convert-secret-to-public < ./secret-key) ./result
```
# Description
This command generates a new Ed25519 secret key for signing store
paths and prints it on standard output. Use `nix key
convert-secret-to-public` to get the corresponding public key for
verifying signed store paths.
The mandatory argument `--key-name` specifies a key name (such as
`cache.example.org-1). It is used to look up keys on the client when
it verifies signatures. It can be anything, but its suggested to use
the host name of your cache (e.g. `cache.example.org`) with a suffix
denoting the number of the key (to be incremented every time you need
to revoke a key).
# Format
Both secret and public keys are represented as the key name followed
by a base-64 encoding of the Ed25519 key data, e.g.
```
cache.example.org-0:E7lAO+MsPwTFfPXsdPtW8GKui/5ho4KQHVcAGnX+Tti1V4dUxoVoqLyWJ4YESuZJwQ67GVIksDt47og+tPVUZw==
```
)""

View file

@ -141,3 +141,90 @@ struct CmdSignPaths : StorePathsCommand
};
static auto rCmdSignPaths = registerCommand2<CmdSignPaths>({"store", "sign-paths"});
#if HAVE_SODIUM
struct CmdKeyGenerateSecret : Command
{
std::optional<std::string> keyName;
CmdKeyGenerateSecret()
{
addFlag({
.longName = "key-name",
.description = "identifier of the key (e.g. `cache.example.org-1`)",
.labels = {"name"},
.handler = {&keyName},
});
}
std::string description() override
{
return "generate a secret key for signing store paths";
}
std::string doc() override
{
return
#include "key-generate-secret.md"
;
}
void run() override
{
if (!keyName)
throw UsageError("required argument '--key-name' is missing");
std::cout << SecretKey::generate(*keyName).to_string();
}
};
struct CmdKeyConvertSecretToPublic : Command
{
std::string description() override
{
return "generate a public key for verifying store paths from a secret key read from standard input";
}
std::string doc() override
{
return
#include "key-convert-secret-to-public.md"
;
}
void run() override
{
SecretKey secretKey(drainFD(STDIN_FILENO));
std::cout << secretKey.toPublicKey().to_string();
}
};
struct CmdKey : NixMultiCommand
{
CmdKey()
: MultiCommand({
{"generate-secret", []() { return make_ref<CmdKeyGenerateSecret>(); }},
{"convert-secret-to-public", []() { return make_ref<CmdKeyConvertSecretToPublic>(); }},
})
{
}
std::string description() override
{
return "generate and convert Nix signing keys";
}
Category category() override { return catUtility; }
void run() override
{
if (!command)
throw UsageError("'nix flake' requires a sub-command.");
settings.requireExperimentalFeature("flakes");
command->second->prepare();
command->second->run();
}
};
static auto rCmdKey = registerCommand<CmdKey>("key");
#endif

View file

@ -131,14 +131,14 @@ if [ -n "$HAVE_SODIUM" ]; then
clearCache
clearCacheCache
declare -a res=($(nix-store --generate-binary-cache-key test.nixos.org-1 $TEST_ROOT/sk1 $TEST_ROOT/pk1 ))
publicKey="$(cat $TEST_ROOT/pk1)"
nix key generate-secret --key-name test.nixos.org-1 > $TEST_ROOT/sk1
publicKey=$(nix key convert-secret-to-public < $TEST_ROOT/sk1)
res=($(nix-store --generate-binary-cache-key test.nixos.org-1 $TEST_ROOT/sk2 $TEST_ROOT/pk2))
badKey="$(cat $TEST_ROOT/pk2)"
nix key generate-secret --key-name test.nixos.org-1 > $TEST_ROOT/sk2
badKey=$(nix key convert-secret-to-public < $TEST_ROOT/sk2)
res=($(nix-store --generate-binary-cache-key foo.nixos.org-1 $TEST_ROOT/sk3 $TEST_ROOT/pk3))
otherKey="$(cat $TEST_ROOT/pk3)"
nix key generate-secret --key-name foo.nixos.org-1 > $TEST_ROOT/sk3
otherKey=$(nix key convert-secret-to-public < $TEST_ROOT/sk3)
_NIX_FORCE_HTTP= nix copy --to file://$cacheDir?secret-key=$TEST_ROOT/sk1 $outPath