common commands - add prefix and account id to the signature verification helper (#1659)
This commit is contained in:
@@ -5,6 +5,9 @@ use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Errors {
|
||||
#[error("account id does not match")]
|
||||
AccountIdError,
|
||||
|
||||
#[error("signature error - {0}")]
|
||||
SignatureError(#[from] k256::ecdsa::signature::Error),
|
||||
|
||||
|
||||
@@ -21,12 +21,22 @@ pub fn secp256k1_verify_with_public_key_json(
|
||||
public_key_as_json: String,
|
||||
signature_as_hex: String,
|
||||
message: String,
|
||||
account_id: String,
|
||||
account_prefix: &str,
|
||||
) -> Result<(), Errors> {
|
||||
let public_key = PublicKey::from_json(&public_key_as_json)?;
|
||||
let verifying_key = VerifyingKey::from_sec1_bytes(&public_key.to_bytes())?;
|
||||
let signature = Signature::from_str(&signature_as_hex)?;
|
||||
let message_as_bytes = message.into_bytes();
|
||||
Ok(verifying_key.verify(&message_as_bytes, &signature)?)
|
||||
match public_key.account_id(account_prefix) {
|
||||
Ok(derived_account_id) => {
|
||||
if derived_account_id.to_string() != account_id {
|
||||
return Err(Errors::AccountIdError);
|
||||
}
|
||||
let verifying_key = VerifyingKey::from_sec1_bytes(&public_key.to_bytes())?;
|
||||
let signature = Signature::from_str(&signature_as_hex)?;
|
||||
let message_as_bytes = message.into_bytes();
|
||||
Ok(verifying_key.verify(&message_as_bytes, &signature)?)
|
||||
}
|
||||
Err(e) => Err(Errors::CosmrsError(e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -69,9 +79,16 @@ mod test_secp256k1 {
|
||||
let json_public_key = r#"{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A4FdhUMasPmNhRZjtpKlmjNbq7EEUgPxfdI+E3vSajvc"}"#.to_string();
|
||||
let signature_as_hex = "E3AA5AC0DA1B7DEBB7808000F719D8ACB9A0BE10AFA2756A788516268EB246A1257EC1097C5E364EF916145B01641DEDFE955994CB340BDAFA99A65BCA3F6F28".to_string();
|
||||
let message = "test 1234".to_string();
|
||||
let account_id = "n1lntkptzz8grf2w4yht4szxktzwsucgv4s7vv9g".to_string();
|
||||
let account_prefix = "n";
|
||||
|
||||
let result =
|
||||
secp256k1_verify_with_public_key_json(json_public_key, signature_as_hex, message);
|
||||
let result = secp256k1_verify_with_public_key_json(
|
||||
json_public_key,
|
||||
signature_as_hex,
|
||||
message,
|
||||
account_id,
|
||||
account_prefix,
|
||||
);
|
||||
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
@@ -81,9 +98,16 @@ mod test_secp256k1 {
|
||||
let bad_json_public_key = r#"This is not JSON ☠️"#.to_string();
|
||||
let signature_as_hex = "E3AA5AC0DA1B7DEBB7808000F719D8ACB9A0BE10AFA2756A788516268EB246A1257EC1097C5E364EF916145B01641DEDFE955994CB340BDAFA99A65BCA3F6F28".to_string();
|
||||
let message = "abcdef".to_string();
|
||||
let account_id = "".to_string();
|
||||
let account_prefix = "n";
|
||||
|
||||
let result =
|
||||
secp256k1_verify_with_public_key_json(bad_json_public_key, signature_as_hex, message);
|
||||
let result = secp256k1_verify_with_public_key_json(
|
||||
bad_json_public_key,
|
||||
signature_as_hex,
|
||||
message,
|
||||
account_id,
|
||||
account_prefix,
|
||||
);
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
@@ -23,16 +23,21 @@ Nym signature verification example
|
||||
|
||||
|
||||
public key: {"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A4FdhUMasPmNhRZjtpKlmjNbq7EEUgPxfdI+E3vSajvc"}
|
||||
account id: n1lntkptzz8grf2w4yht4szxktzwsucgv4s7vv9g
|
||||
signature: E3AA5AC0DA1B7DEBB7808000F719D8ACB9A0BE10AFA2756A788516268EB246A1257EC1097C5E364EF916145B01641DEDFE955994CB340BDAFA99A65BCA3F6F28
|
||||
message: test 1234
|
||||
|
||||
|
||||
Verify the correct message:
|
||||
|
||||
SUCCESS ✅ signature is valid
|
||||
|
||||
|
||||
Verify another message:
|
||||
Verify the correct message with the wrong address:
|
||||
FAILURE ❌ signature is not valid: account id does not match
|
||||
|
||||
FAILURE ❌ signature is not valid: signature error
|
||||
Verify the correct message with the wrong account and public key:
|
||||
FAILURE ❌ signature is not valid: account id does not match
|
||||
|
||||
Verify another message:
|
||||
FAILURE ❌ signature is not valid: signature error - signature error
|
||||
```
|
||||
@@ -6,6 +6,12 @@ fn main() {
|
||||
// the public key in JSON format (because Cosmos supports secp256k1 and ed25519 - NB: the helper only supports secp256k1)
|
||||
let public_key_as_json = r#"{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A4FdhUMasPmNhRZjtpKlmjNbq7EEUgPxfdI+E3vSajvc"}"#;
|
||||
|
||||
// the Cosmos address prefix for Nyx is just 'n'
|
||||
let account_prefix = "n";
|
||||
|
||||
// the account id is a hash of the public key combined with the prefix
|
||||
let account_id = "n1lntkptzz8grf2w4yht4szxktzwsucgv4s7vv9g".to_string();
|
||||
|
||||
// the signature as a string of hex characters to represent the bytes in the signature
|
||||
let signature_as_hex = "E3AA5AC0DA1B7DEBB7808000F719D8ACB9A0BE10AFA2756A788516268EB246A1257EC1097C5E364EF916145B01641DEDFE955994CB340BDAFA99A65BCA3F6F28";
|
||||
|
||||
@@ -13,30 +19,69 @@ fn main() {
|
||||
let message = "test 1234".to_string();
|
||||
|
||||
println!("public key: {}", &public_key_as_json);
|
||||
println!("account id: {}", &account_id);
|
||||
println!("signature: {}", &signature_as_hex);
|
||||
println!("message: {}", &message);
|
||||
|
||||
println!();
|
||||
|
||||
// this will pass, because the signature was signed for this message
|
||||
println!("\nVerify the correct message:\n");
|
||||
println!("\nVerify the correct message:");
|
||||
do_verify(
|
||||
account_id.clone(),
|
||||
account_prefix,
|
||||
public_key_as_json.to_string(),
|
||||
signature_as_hex.to_string(),
|
||||
message.clone(),
|
||||
);
|
||||
|
||||
println!();
|
||||
|
||||
// this will fail, because the account id doesn't match the public key
|
||||
println!("\nVerify the correct message with the wrong address:");
|
||||
do_verify(
|
||||
"n19s8wj0lhkvhr73vy746q3c2hfdzew80rxs6qmy".to_string(),
|
||||
account_prefix,
|
||||
public_key_as_json.to_string(),
|
||||
signature_as_hex.to_string(),
|
||||
message.clone(),
|
||||
);
|
||||
|
||||
// this will fail, because the message was signed with another account private key
|
||||
println!("\nVerify the correct message with the wrong account and public key:");
|
||||
do_verify(
|
||||
"n19s8wj0lhkvhr73vy746q3c2hfdzew80rxs6qmy".to_string(),
|
||||
account_prefix,
|
||||
r#"{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A8l8JuPJjXPUWlBN0XaqRClrq9NMf2qaFQ5CJzidvAvK"}"#.to_string(),
|
||||
signature_as_hex.to_string(),
|
||||
message,
|
||||
);
|
||||
|
||||
// this will fail, because the signature is for another message
|
||||
println!("\n\nVerify another message:\n");
|
||||
println!("\nVerify another message:");
|
||||
do_verify(
|
||||
account_id,
|
||||
account_prefix,
|
||||
public_key_as_json.to_string(),
|
||||
signature_as_hex.to_string(),
|
||||
"another message that will fail".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
fn do_verify(public_key_as_json: String, signature_as_hex: String, message: String) {
|
||||
match secp256k1_verify_with_public_key_json(public_key_as_json, signature_as_hex, message) {
|
||||
fn do_verify(
|
||||
account_id: String,
|
||||
prefix: &str,
|
||||
public_key_as_json: String,
|
||||
signature_as_hex: String,
|
||||
message: String,
|
||||
) {
|
||||
match secp256k1_verify_with_public_key_json(
|
||||
public_key_as_json,
|
||||
signature_as_hex,
|
||||
message,
|
||||
account_id,
|
||||
prefix,
|
||||
) {
|
||||
Ok(()) => println!("SUCCESS ✅ signature is valid"),
|
||||
Err(e) => println!("FAILURE ❌ signature is not valid: {}", e),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user