Skip to content

Commit 8d85125

Browse files
authored
Add signature scheme versioning (#197)
1 parent 7301d8e commit 8d85125

File tree

10 files changed

+75
-38
lines changed

10 files changed

+75
-38
lines changed

src/bech32m.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ mod tests {
176176
case::<0, { Fingerprint::LEN }, Fingerprint>("package", "package fingerprint");
177177
case::<0, { PrivateKey::LEN }, PrivateKey>("private", "private key");
178178
case::<0, { PublicKey::LEN }, PublicKey>("public", "public key");
179-
case::<1, { Signature::LEN }, Signature>("signature", "signature");
179+
case::<2, { Signature::LEN }, Signature>("signature", "signature");
180180
}
181181

182182
#[test]

src/note.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ mod tests {
6767
);
6868
assert_eq!(
6969
serde_json::from_str::<Note>(&json).unwrap_err().to_string(),
70-
"invalid entry: found duplicate key at line 1 column 401",
70+
"invalid entry: found duplicate key at line 1 column 403",
7171
);
7272
}
7373

src/pgp.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ fn pgp_v4_signatures_can_be_verified() {
313313
}
314314

315315
// extract and verify public key
316-
{
316+
let private_key = {
317317
let packet::key::SecretKeyMaterial::Unencrypted(secret_key_material) =
318318
signing_key.key().optional_secret().unwrap()
319319
else {
@@ -327,7 +327,9 @@ fn pgp_v4_signatures_can_be_verified() {
327327
let private_key = PrivateKey::from_bytes(scalar.value().try_into().unwrap());
328328

329329
assert_eq!(private_key.public_key(), public_key);
330-
}
330+
331+
private_key
332+
};
331333

332334
// create filepack signature
333335
let signature = Signature::new(
@@ -339,4 +341,8 @@ fn pgp_v4_signatures_can_be_verified() {
339341

340342
// verify signature
341343
signature.verify(&message, public_key).unwrap();
344+
345+
eprintln!("PGP_PRIVATE_KEY: {}", private_key.display_secret());
346+
eprintln!("PGP_PUBLIC_KEY: {public_key}");
347+
eprintln!("PGP_SIGNATURE: {signature}");
342348
}

src/signature.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ impl Signature {
2424
}
2525
}
2626

27-
impl Bech32m<1, { Signature::LEN }> for Signature {
27+
impl Bech32m<2, { Signature::LEN }> for Signature {
2828
const HRP: Hrp = Hrp::parse_unchecked("signature");
2929
const TYPE: &'static str = "signature";
3030
type Suffix = Vec<u8>;
@@ -55,14 +55,14 @@ impl FromStr for Signature {
5555

5656
fn from_str(signature: &str) -> Result<Self, Self::Err> {
5757
let Bech32mPayload {
58-
prefix: [scheme],
58+
prefix: [scheme, version],
5959
data,
6060
suffix,
6161
} = Self::decode_bech32m(signature)?;
6262

6363
Ok(Self {
6464
inner: ed25519_dalek::Signature::from_bytes(&data),
65-
scheme: SignatureScheme::new(scheme, suffix)?,
65+
scheme: SignatureScheme::new(scheme, version, suffix)?,
6666
})
6767
}
6868
}
@@ -97,13 +97,14 @@ mod tests {
9797

9898
assert_eq!(
9999
bech32m.parse::<Signature>().unwrap_err().to_string(),
100-
"expected bech32m signature to have 1 prefix character but found 0",
100+
"expected bech32m signature to have 2 prefix characters but found 0",
101101
);
102102
}
103103

104104
#[test]
105105
fn unsupported_scheme() {
106106
let bech32m = iter::once(Fe32::Q)
107+
.chain(iter::once(Fe32::_0))
107108
.chain([0u8; Signature::LEN].iter().copied().bytes_to_fes())
108109
.with_checksum::<bech32::Bech32m>(&Signature::HRP)
109110
.with_witness_version(Fe32::A)
@@ -112,7 +113,7 @@ mod tests {
112113

113114
assert_eq!(
114115
bech32m.parse::<Signature>().unwrap_err().to_string(),
115-
"bech32m signature scheme `q` is not supported",
116+
"signature scheme `q` is not supported",
116117
);
117118
}
118119
}

src/signature_error.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ pub enum SignatureError {
1313
},
1414
#[snafu(display("found unexpected suffix for signature scheme `{scheme}`"))]
1515
UnexpectedSuffix { scheme: &'static str },
16-
#[snafu(display("bech32m signature scheme `{scheme}` is not supported"))]
16+
#[snafu(display("signature scheme `{scheme}` is not supported"))]
1717
UnsupportedScheme { scheme: Fe32 },
18+
#[snafu(display(
19+
"signature scheme `{scheme}` version `{actual}` is not supported, expected `{expected}`",
20+
))]
21+
UnsupportedVersion {
22+
actual: Fe32,
23+
expected: Fe32,
24+
scheme: &'static str,
25+
},
1826
}

src/signature_scheme.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,32 @@ pub(crate) enum SignatureScheme {
1111
}
1212

1313
impl SignatureScheme {
14-
pub(crate) fn new(scheme: Fe32, suffix: Vec<u8>) -> Result<Self, SignatureError> {
14+
pub(crate) fn new(scheme: Fe32, version: Fe32, suffix: Vec<u8>) -> Result<Self, SignatureError> {
1515
match scheme {
1616
Fe32::F => {
17+
ensure!(
18+
version == Fe32::_0,
19+
signature_error::UnsupportedVersion {
20+
scheme: "filepack",
21+
actual: version,
22+
expected: Fe32::_0,
23+
},
24+
);
1725
ensure!(
1826
suffix.is_empty(),
1927
signature_error::UnexpectedSuffix { scheme: "filepack" },
2028
);
2129
Ok(SignatureScheme::Filepack)
2230
}
2331
Fe32::P => {
32+
ensure!(
33+
version == Fe32::_4,
34+
signature_error::UnsupportedVersion {
35+
scheme: "pgp",
36+
actual: version,
37+
expected: Fe32::_4,
38+
},
39+
);
2440
u16::try_from(suffix.len())
2541
.ok()
2642
.context(signature_error::SuffixLength {
@@ -33,6 +49,14 @@ impl SignatureScheme {
3349
})
3450
}
3551
Fe32::S => {
52+
ensure!(
53+
version == Fe32::_0,
54+
signature_error::UnsupportedVersion {
55+
scheme: "ssh",
56+
actual: version,
57+
expected: Fe32::_0,
58+
},
59+
);
3660
ensure!(
3761
suffix.is_empty(),
3862
signature_error::UnexpectedSuffix { scheme: "ssh" },
@@ -43,11 +67,11 @@ impl SignatureScheme {
4367
}
4468
}
4569

46-
pub(crate) fn prefix_and_suffix(&self) -> ([Fe32; 1], &[u8]) {
70+
pub(crate) fn prefix_and_suffix(&self) -> ([Fe32; 2], &[u8]) {
4771
match self {
48-
SignatureScheme::Filepack => ([Fe32::F], &[]),
49-
SignatureScheme::Pgp { hashed_area } => ([Fe32::P], hashed_area),
50-
SignatureScheme::Ssh => ([Fe32::S], &[]),
72+
SignatureScheme::Filepack => ([Fe32::F, Fe32::_0], &[]),
73+
SignatureScheme::Pgp { hashed_area } => ([Fe32::P, Fe32::_4], hashed_area),
74+
SignatureScheme::Ssh => ([Fe32::S, Fe32::_0], &[]),
5175
}
5276
}
5377

src/ssh.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ fn ssh_signatures_can_be_verified() {
6868
};
6969

7070
// extract and verify private key
71-
{
71+
let private_key = {
7272
let pem = filesystem::read_to_string(&key_path).unwrap();
7373
let private_key = ssh_key::PrivateKey::from_openssh(&pem).unwrap();
7474

@@ -80,7 +80,9 @@ fn ssh_signatures_can_be_verified() {
8080

8181
let private_key = PrivateKey::from_bytes(keypair.private.to_bytes());
8282

83-
assert_eq!(private_key.public_key(), public_key,);
83+
assert_eq!(private_key.public_key(), public_key);
84+
85+
private_key
8486
};
8587

8688
// extract signature
@@ -97,4 +99,8 @@ fn ssh_signatures_can_be_verified() {
9799

98100
// verify signature
99101
signature.verify(&message, public_key).unwrap();
102+
103+
eprintln!("SSH_PRIVATE_KEY: {}", private_key.display_secret());
104+
eprintln!("SSH_PUBLIC_KEY: {public_key}");
105+
eprintln!("SSH_SIGNATURE: {signature}");
100106
}

src/test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ pub(crate) const PUBLIC_KEY: &str =
1212
"public1a67dndhhmae7p6fsfnj0z37zf78cde6mwqgtms0y87h8ldlvvflyqcxnd63";
1313

1414
pub(crate) const SIGNATURE: &str = concat!(
15-
"signature1afppampjlm7qs0g4amn9fnq87crhn70k5lv5wf48ajy6k774tqw",
16-
"6yc9s5n0kpq5420jrz644sgu7geahpffl8l7nuv9azsqv8jpgtrcqsdxjghp",
15+
"signature1af0ppampjlm7qs0g4amn9fnq87crhn70k5lv5wf48ajy6k774tq",
16+
"w6yc9s5n0kpq5420jrz644sgu7geahpffl8l7nuv9azsqv8jpgtrcqsarjptp",
1717
);
1818

1919
pub(crate) const WEAK_PUBLIC_KEY: &str =

tests/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,6 @@ const PRIVATE_KEY: &str = "private1a24p4zsr2nh04f4pkgtxfzv5yle473x4jue7s6lkwg9td
4646
const PUBLIC_KEY: &str = "public1a67dndhhmae7p6fsfnj0z37zf78cde6mwqgtms0y87h8ldlvvflyqcxnd63";
4747

4848
const SIGNATURE: &str = concat!(
49-
"signature1afppampjlm7qs0g4amn9fnq87crhn70k5lv5wf48ajy6k774tqw",
50-
"6yc9s5n0kpq5420jrz644sgu7geahpffl8l7nuv9azsqv8jpgtrcqsdxjghp",
49+
"signature1af0ppampjlm7qs0g4amn9fnq87crhn70k5lv5wf48ajy6k774tq",
50+
"w6yc9s5n0kpq5420jrz644sgu7geahpffl8l7nuv9azsqv8jpgtrcqsarjptp",
5151
);

tests/verify.rs

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -461,18 +461,14 @@ fn non_unicode_path_error() {
461461

462462
#[test]
463463
fn pgp_signature() {
464-
#[allow(unused)]
465-
const PGP_PRIVATE_KEY: &str =
466-
"private1at6hy62ykv46jmlqks3jpnx3lmgv2avtrrtnt2uljwhzdrfx54n6sx4cj9e";
467-
468-
const PGP_PUBLIC_KEY: &str = "public1afzgrryd0m6n96syhjl4fadx3hjse8pjr23uztxpwv4685lkjm37qmgwsd3";
464+
const PGP_PUBLIC_KEY: &str = "public1axadguya9tqnfavpjq08st0sfzgvmxwjsqcfudgg55sh4ztjnsugsxmnnj0";
469465

470466
const PGP_SIGNATURE: &str = concat!(
471-
"signature1apnckuwdwggchcm3wp5tyqef2ea03kucmc8j7p3ewcqh8falwrd0",
472-
"axhp3n59c644jxnyk66tcwhs33ut0v7puw58024g4xd756m7y7szs9sf5hzw",
473-
"qrpyg93acd9h5ckdxygu2qqqqqqqqpuqpqwdskcazqdehhgct5d9hkuuewwd",
474-
"jhzat0d9sj6ur8wqhx7un8fp3vcyaew0zvdd79t5tmsy3hy4mun4gql69d8n",
475-
"4t05sykyn9fm53vggy47uff5p0uvufjpvme2d43acd9h5ckdxy2u26nt",
467+
"signature1ap4f9anzsjk4gq0hh0a7uk5v7vvjpfz20hwp2y548twpn2ecxn5",
468+
"ahdjd2gusuztpwxs63ajcqzl26k7s95tcatvpsz8r2pgtj0yxjav2rc9sf5hz",
469+
"c22pygwudfszugaanvcgu2qqqqqqqqpuqpqwdskcazqdehhgct5d9hkuuewwd",
470+
"jhzat0d9sj6ur8wqhx7un8rl2l6gcc3ccvenxhfpyacp57t5xfyp3dktmz068",
471+
"w8uspdfdwy89pvggyppyz88rs9es8fq65rx77udfszugaanvcclxt00",
476472
);
477473

478474
Test::new()
@@ -635,15 +631,11 @@ error: 1 mismatched file
635631

636632
#[test]
637633
fn ssh_signature() {
638-
#[allow(unused)]
639-
const SSH_PRIVATE_KEY: &str =
640-
"private1a4u5t9g3hlfk56d5kaw8drqgc478ljeqzae7lqc4y742pa6u6ur7srw5lct";
641-
642-
const SSH_PUBLIC_KEY: &str = "public1a5yf9ackwkywzmygc3q4mglp7qd32ruyj5fr0w3szp70jt4cl34cqwtjjhh";
634+
const SSH_PUBLIC_KEY: &str = "public1avp5pgjsqf6uzcrd34x4hgdndfaf5w5h786wh3tjs9vyup3n74h2shpdku2";
643635

644636
const SSH_SIGNATURE: &str = concat!(
645-
"signature1as2wzp8g6f9d6gt53dpt37zlz4qw2hwhn4q7yg99uz6lrua63mh",
646-
"h7mnmka5cap6z37rglrst2thst909zlmerltgna7yhgf240dsqd6pgrvzhv0",
637+
"signature1as0qpsm76yvvg4wjn4l7vqemk5vpc5khpp5ceqrp693x2ndrvrn",
638+
"vsga58suzl239sjh4t5uhprwpyfmypy4cmp0upe055cvzxg226e7gzq3e7nwt",
647639
);
648640

649641
Test::new()

0 commit comments

Comments
 (0)