///|
/// `linuxpkg key apk-pub KEY` writes the Alpine public key of an RSA signing
/// key; `linuxpkg key info KEY` shows which key a file holds. Neither prints or
/// copies any secret part of the key.
fn cmd_key(args : Array[String]) -> Int32 raise CliError {
let options = parse_options(
args,
{ "--name": "name", "-n": "name", "--out": "out", "-o": "out" },
Map([]),
)
match options.positional {
["info", path] => {
let key = load_signing_key(path)
println("fingerprint: \{key.fingerprint()}")
println("key id: \{key.key_id()}")
if key.is_rsa() {
println("algorithm: RSA \{key.rsa_bits()}")
} else {
println("algorithm: Ed25519")
}
println("created: \{@repo.rfc2822(key.created())}")
0
}
["apk-pub", path] => {
let key = load_signing_key(path)
let pem = key.rsa_public_pem() catch {
err => raise Failed("\{path}: \{err}")
}
let name = match options.value("name") {
Some(name) =>
if name.has_suffix(".rsa.pub") {
name
} else {
name + ".rsa.pub"
}
None => apk_key_name(key, None)
}
let out_dir = match options.value("out") {
Some(dir) => dir
None => ""
}
ensure_dir(out_dir)
let target = join_path(out_dir, name)
write_bytes(target, @utf8.encode(pem))
println("wrote \{target}; copy it to /etc/apk/keys/ on Alpine Linux")
0
}
["info"] | ["apk-pub"] =>
raise Usage(
"key \{options.positional[0]} needs the path of a private key",
)
[] => raise Usage("key needs a subcommand: apk-pub KEY or info KEY")
[other, ..] =>
raise Usage(
"unknown key subcommand \"\{other}\", expected apk-pub or info",
)
}
}