Skip to content

Commit f979a1a

Browse files
committed
start implementing signature verification for add and revoke
1 parent bc21d9d commit f979a1a

File tree

2 files changed

+63
-17
lines changed

2 files changed

+63
-17
lines changed

crates/common/src/hashchain.rs

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use anyhow::{anyhow, bail, Result};
2+
use ed25519_dalek::{Signature, Verifier, VerifyingKey};
23
use jmt::KeyHash;
34
use serde::{Deserialize, Serialize};
45
use std::{
5-
collections::{HashMap, HashSet},
6+
collections::HashSet,
67
ops::{Deref, DerefMut},
78
};
89

@@ -165,24 +166,73 @@ impl Hashchain {
165166
}
166167

167168
// TODO: Obviously, this needs to be authenticated by an existing key.
168-
pub fn add(&mut self, value: PublicKey, signature: SignatureBundle) -> Result<Digest> {
169-
let operation = Operation::AddKey(KeyOperationArgs {
169+
pub fn add(&mut self, value: PublicKey, signature_bundle: SignatureBundle) -> Result<Digest> {
170+
self.perform_operation(Operation::AddKey, value, signature_bundle)
171+
}
172+
173+
pub fn revoke(
174+
&mut self,
175+
value: PublicKey,
176+
signature_bundle: SignatureBundle,
177+
) -> Result<Digest> {
178+
self.perform_operation(Operation::RevokeKey, value, signature_bundle)
179+
}
180+
181+
fn perform_operation(
182+
&mut self,
183+
operation_type: fn(KeyOperationArgs) -> Operation,
184+
value: PublicKey,
185+
signature_bundle: SignatureBundle,
186+
) -> Result<Digest> {
187+
let signing_key = self.get_key_at_index(signature_bundle.key_idx as usize)?;
188+
189+
if self.is_key_revoked(signing_key.clone()) {
190+
bail!("The signing key is revoked");
191+
}
192+
193+
let operation_to_sign = operation_type(KeyOperationArgs {
170194
id: self.id.clone(),
171-
value,
172-
signature,
195+
value: value.clone(),
196+
signature: SignatureBundle {
197+
key_idx: signature_bundle.key_idx,
198+
signature: Vec::new(),
199+
},
173200
});
174-
self.push(operation)
175-
}
176201

177-
pub fn revoke(&mut self, value: PublicKey, signature: SignatureBundle) -> Result<Digest> {
178-
let operation = Operation::RevokeKey(KeyOperationArgs {
202+
let message = bincode::serialize(&operation_to_sign)?;
203+
self.verify_signature(
204+
&signing_key,
205+
&message,
206+
signature_bundle.signature.as_slice(),
207+
)?;
208+
209+
let operation = operation_type(KeyOperationArgs {
179210
id: self.id.clone(),
180211
value,
181-
signature,
212+
signature: signature_bundle,
182213
});
183214
self.push(operation)
184215
}
185216

217+
fn verify_signature(
218+
&self,
219+
public_key: &PublicKey,
220+
message: &[u8],
221+
signature: &[u8],
222+
) -> Result<()> {
223+
match public_key {
224+
PublicKey::Ed25519(key_bytes) => {
225+
let verifying_key = VerifyingKey::from_bytes(key_bytes.as_slice().try_into()?)?;
226+
let signature = Signature::from_slice(signature)?;
227+
verifying_key
228+
.verify(message, &signature)
229+
.map_err(|e| anyhow::anyhow!("Signature verification failed: {}", e))
230+
}
231+
// pot. cases for other key types in the future here
232+
_ => bail!("Unsupported key type for verification"),
233+
}
234+
}
235+
186236
pub fn get_keyhash(&self) -> KeyHash {
187237
KeyHash::with::<Hasher>(self.id.clone())
188238
}

crates/common/src/test_utils.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
hashchain::{Hashchain, HashchainEntry},
33
operation::{KeyOperationArgs, Operation, PublicKey, SignatureBundle},
4-
tree::{hash, InsertProof, KeyDirectoryTree, SnarkableTree, UpdateProof},
4+
tree::{hash, Digest, InsertProof, KeyDirectoryTree, SnarkableTree, UpdateProof},
55
};
66
use anyhow::{anyhow, Result};
77
use ed25519_dalek::{Signer, SigningKey};
@@ -132,18 +132,14 @@ pub fn create_mock_hashchain(id: &str) -> Hashchain {
132132
hc
133133
}
134134

135-
pub fn create_mock_chain_entry(signing_key: &SigningKey) -> HashchainEntry {
135+
pub fn create_mock_chain_entry(signing_key: &SigningKey, previous_hash: Digest) -> HashchainEntry {
136136
let operation = Operation::AddKey(KeyOperationArgs {
137137
id: "test_id".to_string(),
138138
value: PublicKey::Ed25519(signing_key.verifying_key().to_bytes().to_vec()),
139139
signature: create_mock_signature(signing_key, b"test_id"),
140140
});
141141

142-
HashchainEntry {
143-
hash: hash(b"test_hash"),
144-
previous_hash: hash(b"test_previous_hash"),
145-
operation,
146-
}
142+
HashchainEntry::new(operation, previous_hash)
147143
}
148144

149145
pub fn create_add_key_operation_with_test_value(id: &str, signing_key: &SigningKey) -> Operation {

0 commit comments

Comments
 (0)