difftreelog
feat hex secret encoding
in: trunk
3 files changed
Cargo.lockdiffbeforeafterboth812 "clap",812 "clap",813 "ed25519-dalek",813 "ed25519-dalek",814 "fleet-shared",814 "fleet-shared",815 "hex",815 "rand",816 "rand",816 "x25519-dalek",817 "x25519-dalek",817]818]1048source = "registry+https://github.com/rust-lang/crates.io-index"1049source = "registry+https://github.com/rust-lang/crates.io-index"1049checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"1050checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"10511052[[package]]1053name = "hex"1054version = "0.4.3"1055source = "registry+https://github.com/rust-lang/crates.io-index"1056checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"105010571051[[package]]1058[[package]]1052name = "hkdf"1059name = "hkdf"cmds/generator-helper/Cargo.tomldiffbeforeafterboth10clap.workspace = true10clap.workspace = true11ed25519-dalek = { version = "2.1", features = ["rand_core"] }11ed25519-dalek = { version = "2.1", features = ["rand_core"] }12fleet-shared.workspace = true12fleet-shared.workspace = true13hex = "0.4.3"13rand = "0.8.5"14rand = "0.8.5"14x25519-dalek = "2.0.1"15x25519-dalek = "2.0.1"1516cmds/generator-helper/src/main.rsdiffbeforeafterboth1use std::{1use std::{2 env,2 env,3 fs::{File, OpenOptions},3 fs::{File, OpenOptions},4 io::{copy, Read, Write},4 io::{self, copy, stdin, stdout, Read, Write},5 str::FromStr,5 str::FromStr,6};6};77106 match encoding {106 match encoding {107 OutputEncoding::Raw => coerce(w),107 OutputEncoding::Raw => coerce(w),108 OutputEncoding::Base64 => {108 OutputEncoding::Base64 => {109 use base64::engine::general_purpose::STANDARD;109 use base64::{engine::general_purpose::STANDARD, write::EncoderWriter};110110 let writer = base64::write::EncoderWriter::new(w, &STANDARD);111 let writer = EncoderWriter::new(w, &STANDARD);111 coerce(writer)112 coerce(writer)112 }113 }114 OutputEncoding::Hex => {115 struct HexWriter<W>(W);116 impl<W> Write for HexWriter<W>117 where118 W: Write,119 {120 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {121 let encoded = hex::encode(buf);122 self.0.write_all(encoded.as_bytes())?;123 Ok(buf.len())124 }125126 fn flush(&mut self) -> io::Result<()> {127 self.0.flush()128 }129 }130 coerce(HexWriter(w))131 }113 }132 }114}133}115134120 Raw,139 Raw,121 /// Encode as base64 (with padding).140 /// Encode as base64 (with padding).122 Base64,141 Base64,142 /// Encode as hex (without leading 0x)143 Hex,123}144}124145125#[derive(Parser)]146#[derive(Parser)]175 #[arg(long, short = 'e', value_enum, default_value_t)]196 #[arg(long, short = 'e', value_enum, default_value_t)]176 encoding: OutputEncoding,197 encoding: OutputEncoding,177 },198 },199 /// Sometimes you also need to reencode secret, this command allows you to get raw data from200 /// secret encoded using `gh public`... I would like if I knew a better design for some sort of201 /// such thing. Ideally there should be no need to decode secrets back, but garage wants both202 /// raw pubkey and raw secret key, yet also requires node id which is hex-reencoded public key.203 Decode {204 #[arg(long, short = 'i')]205 input: String,206 },178 /// Generate keys in well-known schemas.207 /// Generate keys in well-known schemas.179 ///208 ///180 /// Note that this command is only intended to be used in fleet secret generator,209 /// Note that this command is only intended to be used in fleet secret generator,190219191 match opts {220 match opts {192 Opts::Public { output, encoding } => {221 Opts::Public { output, encoding } => {193 write_public(&output, std::io::stdin(), encoding)?;222 write_public(&output, stdin(), encoding)?;194 }223 }195 Opts::Private { output, encoding } => {224 Opts::Private { output, encoding } => {196 let recipients = load_identities()?;225 let recipients = load_identities()?;197 write_private(&recipients, &output, std::io::stdin(), encoding)?;226 write_private(&recipients, &output, stdin(), encoding)?;198 }227 }199 Opts::Generate(gen) => {228 Opts::Generate(gen) => {200 match gen {229 match gen {204 no_embed_public,233 no_embed_public,205 encoding,234 encoding,206 } => {235 } => {236 use ed25519_dalek::SigningKey;237207 let recipients = load_identities()?;238 let recipients = load_identities()?;208 let key = ed25519_dalek::SigningKey::generate(&mut rng).to_keypair_bytes();239 let key = SigningKey::generate(&mut rng).to_keypair_bytes();209 write_public(&public, &key[32..], encoding)?;240 write_public(&public, &key[32..], encoding)?;210 write_private(241 write_private(211 &recipients,242 &recipients,225 private,256 private,226 encoding,257 encoding,227 } => {258 } => {259 use x25519_dalek::{PublicKey, StaticSecret};260228 let recipients = load_identities()?;261 let recipients = load_identities()?;229 let key = x25519_dalek::StaticSecret::random_from_rng(rng);262 let key = StaticSecret::random_from_rng(rng);230 let public_key: x25519_dalek::PublicKey = (&key).into();263 let public_key: PublicKey = (&key).into();231 write_public(&public, public_key.as_bytes().as_slice(), encoding)?;264 write_public(&public, public_key.as_bytes().as_slice(), encoding)?;232 write_private(&recipients, &private, key.as_bytes().as_slice(), encoding)?;265 write_private(&recipients, &private, key.as_bytes().as_slice(), encoding)?;233 }266 }257 }290 }258 }291 }259 }292 }293 Opts::Decode { input } => {294 let mut data = Vec::new();295 File::open(input)?.read_to_end(&mut data)?;296 let data = String::from_utf8(data).context(297 "encoded data is always utf-8, you are trying to use decode the wrong way.",298 )?;299 let data =300 SecretData::from_str(&data).map_err(|e| anyhow!("failed to decode data: {e}"))?;301 ensure!(302 !data.encrypted,303 "you can not decrypt secret data, only decode public."304 );305 stdout().write_all(&data.data)?;306 }260 }307 }261 Ok(())308 Ok(())262}309}