Skip to content

Commit 0680429

Browse files
author
Hugh Cunningham
committed
removes signature from SigningCommitment
our SigningCommitment type includes a signature of the identity of the participant creating the commitment, the raw signing commitments, and the input checksum the signature allows other participants to verify that the commitment was created by the participant whose identity is included in the SigningCommitment. this verification takes place before creating a SigningPackage. without this verification an invalid SigningPackage can be created: the participant identity with the mismatched signing commitment will be unable to generate a signature share. the signature therefore allows the signing process to terminate one step earlier in case a participant generates an invalid commitment. the multisig Ledger app will not be able to generate this signature without additional features. these changes remove the signature from the SigningCommitment struct so that we will be able to create SigningCommitment instances from raw commitments generated on Ledger devices.
1 parent 4cec6d5 commit 0680429

File tree

1 file changed

+18
-168
lines changed

1 file changed

+18
-168
lines changed

src/signing_commitment.rs

Lines changed: 18 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use crate::io;
1414
use crate::nonces::deterministic_signing_nonces;
1515
use crate::participant::Identity;
1616
use crate::participant::Secret;
17-
use crate::participant::Signature;
1817
use crate::participant::IDENTITY_LEN;
1918
use core::borrow::Borrow;
2019
use core::hash::Hasher;
@@ -26,8 +25,7 @@ extern crate alloc;
2625
use alloc::vec::Vec;
2726

2827
const NONCE_COMMITMENT_LEN: usize = 32;
29-
pub const AUTHENTICATED_DATA_LEN: usize = IDENTITY_LEN + NONCE_COMMITMENT_LEN * 2 + CHECKSUM_LEN;
30-
pub const SIGNING_COMMITMENT_LEN: usize = AUTHENTICATED_DATA_LEN + Signature::BYTE_SIZE;
28+
pub const SIGNING_COMMITMENT_LEN: usize = IDENTITY_LEN + NONCE_COMMITMENT_LEN * 2 + CHECKSUM_LEN;
3129

3230
#[must_use]
3331
fn input_checksum<I>(transaction_hash: &[u8], signing_participants: &[I]) -> Checksum
@@ -51,55 +49,32 @@ where
5149
hasher.finish()
5250
}
5351

54-
fn authenticated_data(
55-
identity: &Identity,
56-
raw_commitments: &SigningCommitments,
57-
checksum: Checksum,
58-
) -> Result<[u8; AUTHENTICATED_DATA_LEN], IronfishFrostError> {
59-
let mut data = [0u8; AUTHENTICATED_DATA_LEN];
60-
let parts = [
61-
&identity.serialize()[..],
62-
&raw_commitments.hiding().serialize()?,
63-
&raw_commitments.binding().serialize()?,
64-
&checksum.to_le_bytes(),
65-
];
66-
let mut slice = &mut data[..];
67-
for part in parts {
68-
slice[..part.len()].copy_from_slice(part);
69-
slice = &mut slice[part.len()..];
70-
}
71-
debug_assert_eq!(slice.len(), 0);
72-
Ok(data)
73-
}
74-
7552
#[derive(Clone, PartialEq, Eq, Debug)]
7653
pub struct SigningCommitment {
7754
identity: Identity,
7855
raw_commitments: SigningCommitments,
7956
/// A checksum of the transaction hash and the signers for a signing operation. Used to quickly
8057
/// tell if a set of commitments were all generated from the same inputs.
8158
checksum: Checksum,
82-
/// Signature that ensures that `hiding`, `binding`, and `checksum` were generated by the owner
83-
/// of `identity`.
84-
signature: Signature,
8559
}
8660

8761
impl SigningCommitment {
88-
fn from_raw_parts(
89-
identity: Identity,
62+
pub fn from_raw<I>(
9063
raw_commitments: SigningCommitments,
91-
checksum: Checksum,
92-
signature: Signature,
93-
) -> Result<Self, IronfishFrostError> {
94-
let signing_commitment = Self {
64+
identity: Identity,
65+
transaction_hash: &[u8],
66+
signing_participants: &[I],
67+
) -> Result<SigningCommitment, IronfishFrostError>
68+
where
69+
I: Borrow<Identity>,
70+
{
71+
let checksum = input_checksum(transaction_hash, signing_participants);
72+
73+
Ok(SigningCommitment {
9574
identity,
9675
raw_commitments,
9776
checksum,
98-
signature,
99-
};
100-
signing_commitment
101-
.verify_authenticity()
102-
.map(|_| signing_commitment)
77+
})
10378
}
10479

10580
pub fn from_secrets<I>(
@@ -116,24 +91,13 @@ impl SigningCommitment {
11691
deterministic_signing_nonces(secret_share, transaction_hash, signing_participants);
11792
let raw_commitments = *nonces.commitments();
11893
let checksum = input_checksum(transaction_hash, signing_participants);
119-
let authenticated_data = authenticated_data(&identity, &raw_commitments, checksum)?;
120-
let signature = participant_secret.sign(&authenticated_data);
12194
Ok(SigningCommitment {
12295
identity,
12396
raw_commitments,
12497
checksum,
125-
signature,
12698
})
12799
}
128100

129-
pub fn verify_authenticity(&self) -> Result<(), IronfishFrostError> {
130-
let authenticated_data =
131-
authenticated_data(&self.identity, &self.raw_commitments, self.checksum)?;
132-
Ok(self
133-
.identity
134-
.verify_data(&authenticated_data, &self.signature)?)
135-
}
136-
137101
pub fn verify_checksum<I>(
138102
&self,
139103
transaction_hash: &[u8],
@@ -178,7 +142,6 @@ impl SigningCommitment {
178142
}
179143

180144
pub fn serialize_into<W: io::Write>(&self, mut writer: W) -> Result<(), IronfishFrostError> {
181-
writer.write_all(&self.signature.to_bytes())?;
182145
writer.write_all(&self.identity.serialize())?;
183146
writer.write_all(&self.hiding().serialize()?)?;
184147
writer.write_all(&self.binding().serialize()?)?;
@@ -187,10 +150,6 @@ impl SigningCommitment {
187150
}
188151

189152
pub fn deserialize_from<R: io::Read>(mut reader: R) -> Result<Self, IronfishFrostError> {
190-
let mut signature_bytes = [0u8; Signature::BYTE_SIZE];
191-
reader.read_exact(&mut signature_bytes)?;
192-
let signature = Signature::from_bytes(&signature_bytes);
193-
194153
let identity = Identity::deserialize_from(&mut reader)?;
195154

196155
let mut hiding = [0u8; 32];
@@ -207,17 +166,19 @@ impl SigningCommitment {
207166
reader.read_exact(&mut checksum)?;
208167
let checksum = Checksum::from_le_bytes(checksum);
209168

210-
Self::from_raw_parts(identity, raw_commitments, checksum, signature)
169+
Ok(SigningCommitment {
170+
identity,
171+
raw_commitments,
172+
checksum,
173+
})
211174
}
212175
}
213176

214177
#[cfg(test)]
215178
mod tests {
216-
use super::authenticated_data;
217179
use super::SigningCommitment;
218180
use crate::frost::keys::SigningShare;
219181
use crate::participant::Secret;
220-
use hex_literal::hex;
221182
use rand::thread_rng;
222183

223184
#[test]
@@ -248,117 +209,6 @@ mod tests {
248209
assert_eq!(deserialized, commitment);
249210
}
250211

251-
#[test]
252-
fn deserialization_regression() {
253-
let serialization = hex!(
254-
"
255-
307be5a2c20495d05966fc12b2cee3ea4d44cb3623f92b0f6a391c626fa7708e835
256-
26e886448d5ef376c5d09675aed3e711cd3e0df9f6c607604e6a7371a210e725c3a
257-
20a22aebc59d856bfbaa48fde8f8ea6fe48ddd978555932c283e760397f78b4b468
258-
2f9b70f8baad6d7752f5e25bcbc6b3453d16d92589da722ad13a7390d0057c6aae8
259-
363a50e835b89b44bccdd5889ef5a362fa89d841c96e65b34dbe3adf8f71faa041f
260-
394ef6b127c4b6b1e43714f32c450e8d3d089b376915acd6500639cad9b202c479e
261-
4216e2d4d16cad09b634e01270f4a52707d924fd9834e6206f48f04388ae90bcd63
262-
f901369c6034760245574a2d3068f52b617d33ca1a417ea391d3785b542f5
263-
"
264-
);
265-
let deserialized = SigningCommitment::deserialize_from(&serialization[..])
266-
.expect("deserialization failed");
267-
assert_eq!(serialization, deserialized.serialize());
268-
}
269-
270-
#[test]
271-
fn test_invalid_deserialization() {
272-
let mut rng = thread_rng();
273-
274-
let secret = Secret::random(&mut rng);
275-
let signing_share = SigningShare::default();
276-
let signing_participants = [
277-
Secret::random(&mut rng).to_identity(),
278-
Secret::random(&mut rng).to_identity(),
279-
Secret::random(&mut rng).to_identity(),
280-
];
281-
282-
let commitment = SigningCommitment::from_secrets(
283-
&secret,
284-
&signing_share,
285-
b"transaction hash",
286-
&signing_participants,
287-
)
288-
.expect("commitment creation failed");
289-
290-
let serialized = commitment.serialize();
291-
292-
for index in 0..serialized.len() {
293-
let mut invalid_serialization = serialized;
294-
invalid_serialization[index] ^= 0xff;
295-
assert!(SigningCommitment::deserialize_from(&invalid_serialization[..]).is_err());
296-
}
297-
}
298-
299-
#[test]
300-
fn test_valid_signature() {
301-
let mut rng = thread_rng();
302-
303-
let secret = Secret::random(&mut rng);
304-
let signing_share = SigningShare::default();
305-
let signing_participants = [
306-
Secret::random(&mut rng).to_identity(),
307-
Secret::random(&mut rng).to_identity(),
308-
Secret::random(&mut rng).to_identity(),
309-
];
310-
311-
let commitment = SigningCommitment::from_secrets(
312-
&secret,
313-
&signing_share,
314-
b"transaction hash",
315-
&signing_participants,
316-
)
317-
.expect("commitment creation failed");
318-
319-
assert!(commitment.verify_authenticity().is_ok());
320-
}
321-
322-
#[test]
323-
fn test_invalid_signature() {
324-
let mut rng = thread_rng();
325-
326-
let secret = Secret::random(&mut rng);
327-
let signing_share = SigningShare::default();
328-
let signing_participants = [
329-
Secret::random(&mut rng).to_identity(),
330-
Secret::random(&mut rng).to_identity(),
331-
Secret::random(&mut rng).to_identity(),
332-
];
333-
334-
let commitment = SigningCommitment::from_secrets(
335-
&secret,
336-
&signing_share,
337-
b"transaction hash",
338-
&signing_participants,
339-
)
340-
.expect("commitment creation failed");
341-
342-
let unrelated_secret = Secret::random(&mut rng);
343-
let invalid_signature = unrelated_secret.sign(
344-
&authenticated_data(
345-
commitment.identity(),
346-
commitment.raw_commitments(),
347-
commitment.checksum(),
348-
)
349-
.expect("authenticated data failed to return"),
350-
);
351-
352-
let invalid_commitment = SigningCommitment {
353-
identity: commitment.identity().clone(),
354-
raw_commitments: *commitment.raw_commitments(),
355-
checksum: commitment.checksum(),
356-
signature: invalid_signature,
357-
};
358-
359-
assert!(invalid_commitment.verify_authenticity().is_err());
360-
}
361-
362212
#[test]
363213
fn test_checksum_stability() {
364214
let mut rng = thread_rng();

0 commit comments

Comments
 (0)