Skip to content

Commit 20d5865

Browse files
authored
Strictly verify messages when using stellar message verify (#2767)
1 parent 3805157 commit 20d5865

1 file changed

Lines changed: 34 additions & 2 deletions

File tree

  • cmd/soroban-cli/src/commands/message

‎cmd/soroban-cli/src/commands/message/verify.rs‎

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
};
88
use base64::{engine::general_purpose::STANDARD as BASE64, Engine};
99
use clap::Parser;
10-
use ed25519_dalek::{Signature, Verifier, VerifyingKey};
10+
use ed25519_dalek::{Signature, VerifyingKey};
1111
use sha2::{Digest, Sha256};
1212

1313
use super::SEP53_PREFIX;
@@ -100,7 +100,7 @@ impl Cmd {
100100
let verifying_key = VerifyingKey::from_bytes(&public_key.0)?;
101101

102102
// Verify the signature
103-
if verifying_key.verify(&hash, &signature).is_ok() {
103+
if verifying_key.verify_strict(&hash, &signature).is_ok() {
104104
print.checkln("Signature valid");
105105
Ok(())
106106
} else {
@@ -275,6 +275,38 @@ mod tests {
275275
assert!(successful.is_err());
276276
}
277277

278+
#[test]
279+
fn test_verify_rejects_small_order_public_keys() {
280+
// Small-order ed25519 public keys have no secret key. A signature (R, s = 0) with R a
281+
// small-order point passes non-strict verification without any key material.
282+
const IDENTITY_PUBLIC_KEY: &str =
283+
"GAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHV4";
284+
const IDENTITY_FORGED_SIGNATURE: &str =
285+
"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==";
286+
const ZERO_PUBLIC_KEY: &str = "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF";
287+
const ZERO_FORGED_SIGNATURE: &str =
288+
"7P///////////////////////////////////////38AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==";
289+
290+
for (public_key, signature) in [
291+
(IDENTITY_PUBLIC_KEY, IDENTITY_FORGED_SIGNATURE),
292+
(ZERO_PUBLIC_KEY, ZERO_FORGED_SIGNATURE),
293+
] {
294+
let cmd = super::Cmd {
295+
message: Some("Hello, World!".to_string()),
296+
base64: false,
297+
signature: signature.to_string(),
298+
public_key: public_key.to_string(),
299+
hd_path: None,
300+
locator: setup_locator(),
301+
};
302+
let err = cmd.run(&global_args()).unwrap_err();
303+
assert!(
304+
matches!(err, Error::VerificationFailed),
305+
"{public_key}: {err:?}"
306+
);
307+
}
308+
}
309+
278310
#[test]
279311
fn test_verify_rejects_raw_secret_key_as_public_key() {
280312
let secret_key = "SBF5HLRREHMS36XZNTUSKZ6FTXDZGNXOHF4EXKUL5UCWZLPBX3NGJ4BH";

0 commit comments

Comments
 (0)