Skip to content

Commit

Permalink
use prefixed versions for public & private key string representations
Browse files Browse the repository at this point in the history
Public and Private keys are now using the following string format everywhere: `{algorithm}/{bytes}`

`--key-algorithm` is now used when reading binary input, or to assert an algorithm when reading a key from a string.
  • Loading branch information
divarvel committed Jan 27, 2025
1 parent d68e996 commit 3ff2eb3
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 47 deletions.
22 changes: 13 additions & 9 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ pub struct KeyPairCmd {
#[clap(long, parse(from_os_str))]
pub from_private_key_file: Option<PathBuf>,
/// Read the private key raw bytes directly, with no hex decoding
#[clap(long, requires("from-private-key-file"))]
#[clap(
long,
requires("from-private-key-file"),
conflicts_with("from-private-key")
)]
pub from_raw_private_key: bool,
/// Only output the public part of the key pair
#[clap(long, conflicts_with("only-private-key"))]
Expand All @@ -51,8 +55,8 @@ pub struct KeyPairCmd {
#[clap(long, requires("only-private-key"))]
pub raw_private_key_output: bool,
/// Key algorithm: ed25519 (default) or secp256r1
#[clap(long, default_value_t)]
pub key_algorithm: Algorithm,
#[clap(long)]
pub key_algorithm: Option<Algorithm>,
}

/// Generate a biscuit from a private key and an authority block
Expand Down Expand Up @@ -84,8 +88,8 @@ pub struct Generate {
#[clap(long, conflicts_with = "private-key", requires = "private-key-file")]
pub raw_private_key: bool,
/// Key algorithm: ed25519 (default) or secp256r1
#[clap(long, default_value_t)]
pub key_algorithm: Algorithm,
#[clap(long)]
pub key_algorithm: Option<Algorithm>,
/// The optional context string attached to the authority block
#[clap(long)]
pub context: Option<String>,
Expand Down Expand Up @@ -150,8 +154,8 @@ pub struct Inspect {
#[clap(long, requires("public-key-file"), conflicts_with("public-key"))]
pub raw_public_key: bool,
/// Key algorithm: ed25519 (default) or secp256r1
#[clap(long, default_value_t)]
pub key_algorithm: Algorithm,
#[clap(long)]
pub key_algorithm: Option<Algorithm>,
#[clap(flatten)]
pub run_limits_args: common_args::RunLimitArgs,
#[clap(flatten)]
Expand Down Expand Up @@ -228,8 +232,8 @@ pub struct GenerateThirdPartyBlock {
#[clap(long, conflicts_with = "private-key", requires = "private-key-file")]
pub raw_private_key: bool,
/// Key algorithm: ed25519 (default) or secp256r1
#[clap(long, default_value_t)]
pub key_algorithm: Algorithm,
#[clap(long)]
pub key_algorithm: Option<Algorithm>,
/// Output the block raw bytes directly, with no base64 encoding
#[clap(long)]
pub raw_output: bool,
Expand Down
92 changes: 66 additions & 26 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,44 +270,84 @@ fn read_authorizer_from_snapshot(
Ok(builder)
}

pub fn read_private_key_from(from: &KeyBytes, alg: Algorithm) -> Result<PrivateKey> {
let bytes = match from {
KeyBytes::FromStdin(KeyFormat::RawBytes) => read_stdin_bytes()?,
pub fn read_private_key_from(from: &KeyBytes, alg: &Option<Algorithm>) -> Result<PrivateKey> {
let key = match from {
KeyBytes::FromStdin(KeyFormat::RawBytes) => {
let bytes = read_stdin_bytes()?;
PrivateKey::from_bytes(&bytes, alg.unwrap_or_default())
.map_err(|e| ParseError("private key".to_string(), format!("{}", &e)))?
}
KeyBytes::FromStdin(KeyFormat::HexKey) => {
hex::decode(read_stdin_string("hex-encoded private key")?)?
let str = read_stdin_string("hex-encoded private key")?;
str.parse()
.map_err(|e| ParseError("private key".to_string(), format!("{}", &e)))?
}
KeyBytes::FromFile(KeyFormat::RawBytes, path) => {
fs::read(path).map_err(|_| FileNotFound(path.clone()))?
let bytes = fs::read(path).map_err(|_| FileNotFound(path.clone()))?;
PrivateKey::from_bytes(&bytes, alg.unwrap_or_default())
.map_err(|e| ParseError("private key".to_string(), format!("{}", &e)))?
}
KeyBytes::FromFile(KeyFormat::HexKey, path) => hex::decode(
fs::read_to_string(path)
.map_err(|_| FileNotFound(path.clone()))?
.trim(),
)?,
KeyBytes::HexString(str) => hex::decode(str)?,
KeyBytes::FromFile(KeyFormat::HexKey, path) => {
let str = fs::read_to_string(path).map_err(|_| FileNotFound(path.clone()))?;
str.parse()
.map_err(|e| ParseError("private key".to_string(), format!("{}", &e)))?
}
KeyBytes::HexString(str) => str
.parse()
.map_err(|e| ParseError("private key".to_string(), format!("{}", &e)))?,
};
PrivateKey::from_bytes(&bytes, alg)
.map_err(|e| ParseError("private key".to_string(), format!("{}", &e)).into())
let key_alg = key.algorithm().into();

if let Some(a) = alg {
if *a != key_alg {
Err(std::io::Error::other(format!(
"Inconsistent algorithm: key algorithm is {}, expected algorithm is {}",
key_alg, a
)))?
}
}

Ok(key)
}

pub fn read_public_key_from(from: &KeyBytes, alg: Algorithm) -> Result<PublicKey> {
let bytes = match from {
KeyBytes::FromStdin(KeyFormat::RawBytes) => read_stdin_bytes()?,
pub fn read_public_key_from(from: &KeyBytes, alg: &Option<Algorithm>) -> Result<PublicKey> {
let key = match from {
KeyBytes::FromStdin(KeyFormat::RawBytes) => {
let bytes = read_stdin_bytes()?;
PublicKey::from_bytes(&bytes, alg.unwrap_or_default())
.map_err(|e| ParseError("public key".to_string(), format!("{}", &e)))?
}
KeyBytes::FromStdin(KeyFormat::HexKey) => {
hex::decode(read_stdin_string("hex-encoded public key")?)?
let str = read_stdin_string("hex-encoded public key")?;
str.parse()
.map_err(|e| ParseError("public key".to_string(), format!("{}", &e)))?
}
KeyBytes::FromFile(KeyFormat::RawBytes, path) => {
fs::read(path).map_err(|_| FileNotFound(path.clone()))?
let bytes = fs::read(path).map_err(|_| FileNotFound(path.clone()))?;
PublicKey::from_bytes(&bytes, alg.unwrap_or_default())
.map_err(|e| ParseError("public key".to_string(), format!("{}", &e)))?
}
KeyBytes::FromFile(KeyFormat::HexKey, path) => hex::decode(
fs::read_to_string(path)
.map_err(|_| FileNotFound(path.clone()))?
.trim(),
)?,
KeyBytes::HexString(str) => hex::decode(str)?,
KeyBytes::FromFile(KeyFormat::HexKey, path) => {
let str = fs::read_to_string(path).map_err(|_| FileNotFound(path.clone()))?;
str.parse()
.map_err(|e| ParseError("public key".to_string(), format!("{}", &e)))?
}
KeyBytes::HexString(str) => str
.parse()
.map_err(|e| ParseError("public key".to_string(), format!("{}", &e)))?,
};
PublicKey::from_bytes(&bytes, alg)
.map_err(|e| ParseError("public key".to_string(), format!("{}", &e)).into())
let key_alg = key.algorithm().into();

if let Some(a) = alg {
if *a != key_alg {
Err(std::io::Error::other(format!(
"Inconsistent algorithm: key algorithm is {}, expected algorithm is {}",
key_alg, a
)))?
}
}

Ok(key)
}

pub fn read_biscuit_from(from: &BiscuitBytes) -> Result<UnverifiedBiscuit> {
Expand Down
2 changes: 1 addition & 1 deletion src/inspect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ pub fn handle_inspect_inner(inspect: &Inspect) -> Result<InspectionResults> {
let query_result;

if let Some(key_from) = public_key_from {
let key = read_public_key_from(&key_from, inspect.key_algorithm)?;
let key = read_public_key_from(&key_from, &inspect.key_algorithm)?;
let sig_result = biscuit.verify(key);
signatures_check = Some(sig_result.is_ok());

Expand Down
19 changes: 8 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ fn handle_keypair(key_pair_cmd: &KeyPairCmd) -> Result<()> {
};

let private_key: Option<PrivateKey> = if let Some(f) = private_key_from {
Some(read_private_key_from(f, key_pair_cmd.key_algorithm)?)
Some(read_private_key_from(f, &key_pair_cmd.key_algorithm)?)
} else {
None
};

let key_pair = if let Some(private) = private_key {
KeyPair::from(&private)
} else {
KeyPair::new_with_algorithm(key_pair_cmd.key_algorithm)
KeyPair::new_with_algorithm(key_pair_cmd.key_algorithm.unwrap_or_default())
};

match (
Expand All @@ -85,23 +85,20 @@ fn handle_keypair(key_pair_cmd: &KeyPairCmd) -> Result<()> {
} else {
println!("Generating a new random keypair");
}
println!(
"Private key: {}",
hex::encode(key_pair.private().to_bytes())
);
println!("Public key: {}", hex::encode(key_pair.public().to_bytes()));
println!("Private key: {}", key_pair.private().to_prefixed_string());
println!("Public key: {}", key_pair.public());
}
(true, true, false, false) => {
let _ = io::stdout().write_all(&key_pair.private().to_bytes());
}
(true, false, false, false) => {
println!("{}", hex::encode(key_pair.private().to_bytes()));
println!("{}", key_pair.private().to_prefixed_string());
}
(false, false, true, true) => {
let _ = io::stdout().write_all(&key_pair.public().to_bytes());
}
(false, false, true, false) => {
println!("{}", hex::encode(key_pair.public().to_bytes()));
println!("{}", key_pair.public());
}
// the other combinations are prevented by clap
_ => unreachable!(),
Expand All @@ -128,7 +125,7 @@ fn handle_generate(generate: &Generate) -> Result<()> {
// the other combinations are prevented by clap
_ => unreachable!(),
},
generate.key_algorithm,
&generate.key_algorithm,
);

let root = KeyPair::from(&private_key?);
Expand Down Expand Up @@ -284,7 +281,7 @@ fn handle_generate_third_party_block(
// the other combinations are prevented by clap
_ => unreachable!(),
},
generate_third_party_block.key_algorithm,
&generate_third_party_block.key_algorithm,
);

let request = read_request_from(&request_from)?;
Expand Down

0 comments on commit 3ff2eb3

Please sign in to comment.