Skip to content

Commit

Permalink
rename identity sig -> policy sig. update error strings for missing i…
Browse files Browse the repository at this point in the history
…dentities when verifying sigs to include FULL identity id, not the short one.
  • Loading branch information
orthecreedence committed Feb 20, 2024
1 parent b79f173 commit 7dd4284
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 27 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ hottest
<img style="display: inline-block; width: 0.75rem; height: 1rem; vertical-align: middle;" src="https://stamp-protocol.github.io/assets/images/fireanim.gif" alt="fireee">
Stamp CLI changes *allowed by law*.

## v0.1.4 // TBD

### Features

- Changing signature verification messages to be more clear.
- Rename "Identity signature" to "Policy signature." I believe it's less ambiguous.

## v0.1.3 // 2024-02-19

Fixing subkey signatures, adding identity signatures, and updating staged transaction interface.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/commands/dag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ pub fn post_save(transactions: &Transactions, transaction: &Transaction, stage:
}
TransactionBody::SignV1 { creator, body_hash } => {
if stage {
format!("Identity signature with hash {} created. {}", body_hash, view_staged())
format!("Policy signature with hash {} created. {}", body_hash, view_staged())
} else {
// weird, should never get here.
return Ok(None);
Expand Down
48 changes: 30 additions & 18 deletions src/commands/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,53 +80,53 @@ pub fn sign_subkey(id_sign: &str, key_search_sign: Option<&str>, input: &str, ou

pub fn verify(input_signature: &str, input_message: Option<&str>) -> Result<()> {
let sig_bytes = util::read_file(input_signature)?;
enum IdOrSub {
Id(Transaction),
Sub(Signature),
enum PolicyOrSub {
Policy(Transaction),
Subkey(Signature),
}
let signature = Transaction::deserialize_binary(sig_bytes.as_slice())
.or_else(|_| {
Transaction::deserialize_binary(&base64_decode(sig_bytes.as_slice())?)
})
.map(|x| IdOrSub::Id(x))
.map(|x| PolicyOrSub::Policy(x))
.or_else(|_| {
Signature::deserialize_binary(sig_bytes.as_slice())
.or_else(|_| {
Signature::deserialize_binary(&base64_decode(sig_bytes.as_slice())?)
})
.map(|x| IdOrSub::Sub(x))
.map(|x| PolicyOrSub::Subkey(x))
})
.map_err(|e| anyhow!("Error reading signature: {}", e))?;
let res = match &signature {
IdOrSub::Id(transaction) => {
PolicyOrSub::Policy(transaction) => {
let input_message = input_message
.ok_or(anyhow!("A MESSAGE argument must be give when verifying an identity signature."))?;
.ok_or(anyhow!("A MESSAGE argument must be give when verifying an policy signature."))?;
let message_bytes = util::read_file(&input_message)?;
match transaction.entry().body() {
TransactionBody::SignV1 { creator, body_hash } => {
let id_str = format!("{}", creator);
let creator_transactions = db::load_identity(&creator)?
.ok_or(anyhow!("Identity {} not found. Have you imported it?", IdentityID::short(&id_str)))?;
.ok_or(anyhow!("Identity {} not found. Have you imported it?", id_str))?;
let creator_identity = util::build_identity(&creator_transactions)?;
// TODO: verify against past version of creator_transactions if verification
// fails and we have a non-empty previous_transactions. see issue #41
transaction.verify(Some(&creator_identity))
.map_err(|e| anyhow!("Identity signature invalid: {}", e))?;
.map_err(|e| anyhow!("Policy signature invalid: {}", e))?;
match body_hash {
Hash::Blake3(..) => {
let compare = Hash::new_blake3(message_bytes.as_slice())?;
if &compare == body_hash {
Ok(())
} else {
Err(anyhow!("Identity signature hash ({}) does not match message hash ({})", body_hash, compare))
Err(anyhow!("Policy signature hash ({}) does not match message hash ({})", body_hash, compare))
}
}
}
}
_ => Err(anyhow!("Invalid identity signature"))?,
_ => Err(anyhow!("Invalid policy signature: invalid transaction type (expected `Sign` transaction)"))?,
}
}
IdOrSub::Sub(signature) => {
PolicyOrSub::Subkey(signature) => {
let sig = match signature {
Signature::Detached { sig } => sig,
Signature::Attached { sig, .. } => sig,
Expand All @@ -135,7 +135,7 @@ pub fn verify(input_signature: &str, input_message: Option<&str>) -> Result<()>
let key_id = sig.signed_by_key();
let id_str = id_str!(identity_id)?;
let transactions = db::load_identity(identity_id)?
.ok_or(anyhow!("Identity {} not found. Have you imported it?", IdentityID::short(&id_str)))?;
.ok_or(anyhow!("Identity {} not found. Have you imported it?", id_str))?;
let identity = util::build_identity(&transactions)?;
let subkey = identity.keychain().subkey_by_keyid(&key_id)
.ok_or(anyhow!("Signing key {} not found in identity {}", key_id.as_string(), IdentityID::short(&id_str)))?;
Expand All @@ -156,12 +156,24 @@ pub fn verify(input_signature: &str, input_message: Option<&str>) -> Result<()>
};
match res {
Ok(..) => {
let sigtype = match signature {
IdOrSub::Id(..) => "identity",
IdOrSub::Sub(..) => "subkey",
};
let green = dialoguer::console::Style::new().green();
println!("The {} signature is {}!", sigtype, green.apply_to("valid"));
match signature {
PolicyOrSub::Policy(trans) => {
let identity_id = match trans.entry().body() {
TransactionBody::SignV1 { creator, .. } => creator,
_ => Err(anyhow!("Problem pulling signature `creator` field from policy signature. Perhaps it is not a Sign transaction."))?,
};
let id_str_creator = id_str!(identity_id)?;
println!("This signature is {}! It is a policy signature made by the identity {}.", green.apply_to("valid"), id_str_creator);
}
PolicyOrSub::Subkey(sig) => {
let signed_obj = match sig {
Signature::Detached { sig } => sig,
Signature::Attached { sig, .. } => sig,
};
println!("This signature is {}! It is a subkey signature made by the identity {} with the key {}.", green.apply_to("valid"), signed_obj.signed_by_identity(), signed_obj.signed_by_key());
}
}
}
Err(e) => {
let red = dialoguer::console::Style::new().red();
Expand Down
16 changes: 9 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -891,9 +891,10 @@ fn run() -> Result<()> {
.subcommand_required(true)
.arg_required_else_help(true)
.subcommand(
Command::new("id")
.about("Create an identity signature. This type of signature is a transaction validated by the policy system, meaning the correct admin key signatures need to be present for it to be considered valid. Use this for creating official signatures.")
.alias("new")
Command::new("policy")
.about("Create a policy signature. This type of signature is a transaction validated by the policy system, meaning the correct admin key signatures need to be present for it to be considered valid. Use this for creating official signatures representative of your identity (for instance if signing a legal document).")
.alias("identity")
.alias("id")
.arg(id_arg("The ID of the identity we want to sign from. This overrides the configured default identity."))
.arg(stage_arg())
.arg(signwith_arg())
Expand All @@ -909,12 +910,13 @@ fn run() -> Result<()> {
.arg(Arg::new("MESSAGE")
.index(1)
.required(false)
.help("The input file to read the plaintext message from. You can leave blank or use the value '-' to signify STDIN."))
.help("The input file to read the data from. You can leave blank or use the value '-' to signify STDIN."))
)
.subcommand(
Command::new("subkey")
.about("Sign a message or document with one of your `sign` subkeys. This type of signature carries less weight than an `id` signature and only proves you have access to one of the identity's subkeys.")
.about("Sign a message or document with one of your `sign` subkeys. This type of signature carries less weight than a `policy` signature and only proves you have access to one of the identity's subkeys. Use this for less official signatures.")
.alias("sub")
.alias("key")
.arg(Arg::new("key-sign")
.short('k')
.long("key-sign")
Expand All @@ -937,11 +939,11 @@ fn run() -> Result<()> {
.arg(Arg::new("MESSAGE")
.index(1)
.required(false)
.help("The input file to read the plaintext message from. You can leave blank or use the value '-' to signify STDIN."))
.help("The input file to read the data from. You can leave blank or use the value '-' to signify STDIN."))
)
.subcommand(
Command::new("verify")
.about("Verify a signature. This can verify both identity and subkey signatures. This requires having the signing identity imported.")
.about("Verify a signature. This can verify both policy and subkey signatures. This requires having the signing identity imported.")
.arg(Arg::new("SIGNATURE")
.index(1)
.required(true)
Expand Down

0 comments on commit 7dd4284

Please sign in to comment.