1use std::{cmp::Ordering, convert::TryInto, io::Cursor};
3
4use anyhow::Result;
5use byteorder::{LittleEndian, ReadBytesExt};
6use curve25519_dalek::{
7 edwards::{CompressedEdwardsY, EdwardsPoint},
8 scalar::Scalar,
9};
10use ed25519_dalek::{Digest as _, Sha512, Signer as _};
11use rand::rngs::OsRng;
12use thiserror::Error;
13use zeroize::Zeroize;
14
15use crate::common::namespace::Namespace;
16
17use super::hash::Hash;
18
19const CHAIN_SIGNATURE_CONTEXT_SEPARATOR: &[u8] = b" for chain ";
21const RUNTIME_SIGNATURE_CONTEXT_SEPARATOR: &[u8] = b" for runtime ";
23
24impl_bytes!(
25 PublicKey,
26 ed25519_dalek::PUBLIC_KEY_LENGTH,
27 "An Ed25519 public key."
28);
29
30#[derive(Error, Debug)]
32enum SignatureError {
33 #[error("point decompression failed")]
34 PointDecompression,
35 #[error("small order A")]
36 SmallOrderA,
37 #[error("small order R")]
38 SmallOrderR,
39 #[error("signature malleability check failed")]
40 Malleability,
41 #[error("invalid signature")]
42 InvalidSignature,
43}
44
45static CURVE_ORDER: &[u64] = &[
46 0x1000000000000000,
47 0,
48 0x14def9dea2f79cd6,
49 0x5812631a5cf5d3ed,
50];
51
52pub struct PrivateKey(pub ed25519_dalek::SigningKey);
54
55impl PrivateKey {
56 pub fn generate() -> Self {
58 PrivateKey(ed25519_dalek::SigningKey::generate(&mut OsRng))
59 }
60
61 pub fn to_bytes(&self) -> Vec<u8> {
63 let mut bytes = self.0.to_bytes();
64 let bvec = bytes.to_vec();
65 bytes.zeroize();
66 bvec
67 }
68
69 pub fn from_bytes(bytes: Vec<u8>) -> PrivateKey {
75 let mut sk = bytes.try_into().unwrap();
76 let secret = ed25519_dalek::SigningKey::from_bytes(&sk);
77 sk.zeroize();
78
79 PrivateKey(secret)
80 }
81
82 pub fn from_test_seed(seed: String) -> Self {
84 let mut seed = Hash::digest_bytes(seed.as_bytes());
85 let sk = Self::from_bytes(seed.as_ref().to_vec());
86 seed.zeroize();
87
88 sk
89 }
90
91 pub fn public_key(&self) -> PublicKey {
93 PublicKey(self.0.verifying_key().to_bytes())
94 }
95}
96
97impl Signer for PrivateKey {
98 fn public(&self) -> PublicKey {
99 self.public_key()
100 }
101
102 fn sign(&self, context: &[u8], message: &[u8]) -> Result<Signature> {
103 let digest = Hash::digest_bytes_list(&[context, message]);
105
106 Ok(Signature(self.0.sign(digest.as_ref()).to_bytes()))
107 }
108}
109
110impl_bytes!(Signature, 64, "An Ed25519 signature.");
111
112impl Signature {
113 pub fn verify(&self, pk: &PublicKey, context: &[u8], message: &[u8]) -> Result<()> {
115 let digest = Hash::digest_bytes_list(&[context, message]);
119
120 self.verify_raw(pk, digest.as_ref())
121 }
122
123 #[allow(non_snake_case)] pub fn verify_raw(&self, pk: &PublicKey, msg: &[u8]) -> Result<()> {
126 let A = CompressedEdwardsY::from_slice(pk.as_ref())
136 .map_err(|_| SignatureError::PointDecompression)?;
137 let A = A.decompress().ok_or(SignatureError::PointDecompression)?;
138 if A.is_small_order() {
139 return Err(SignatureError::SmallOrderA.into());
140 }
141
142 let sig_slice = self.as_ref();
148 let R_bits = &sig_slice[..32];
149 let S_bits = &sig_slice[32..];
150
151 let R = CompressedEdwardsY::from_slice(R_bits)
152 .map_err(|_| SignatureError::PointDecompression)?;
153 let R = R.decompress().ok_or(SignatureError::PointDecompression)?;
154 if R.is_small_order() {
155 return Err(SignatureError::SmallOrderR.into());
156 }
157
158 if !sc_minimal(S_bits) {
159 return Err(SignatureError::Malleability.into());
160 }
161 let mut S: [u8; 32] = [0u8; 32];
162 S.copy_from_slice(S_bits);
163 #[allow(deprecated)] let S = Scalar::from_bits(S);
165
166 let mut k: Sha512 = Sha512::new();
168 k.update(R_bits);
169 k.update(pk.as_ref());
170 k.update(msg);
171 let k = Scalar::from_hash(k);
172
173 let neg_A = -A;
175 let should_be_small_order =
176 EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &neg_A, &S) - R;
177 match should_be_small_order.is_small_order() {
178 true => Ok(()),
179 false => Err(SignatureError::InvalidSignature.into()),
180 }
181 }
182}
183
184#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
186pub struct Signed {
187 #[cbor(rename = "untrusted_raw_value")]
189 pub blob: Vec<u8>,
190 pub signature: SignatureBundle,
192}
193
194#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
196pub struct MultiSigned {
197 #[cbor(rename = "untrusted_raw_value")]
199 pub blob: Vec<u8>,
200 pub signatures: Vec<SignatureBundle>,
202}
203
204#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
206pub struct SignatureBundle {
207 pub public_key: PublicKey,
209 pub signature: Signature,
211}
212
213impl SignatureBundle {
214 pub fn verify(&self, context: &[u8], message: &[u8]) -> bool {
217 self.signature
218 .verify(&self.public_key, context, message)
219 .is_ok()
220 }
221}
222
223pub trait Signer: Send + Sync {
225 fn public(&self) -> PublicKey;
227
228 fn sign(&self, context: &[u8], message: &[u8]) -> Result<Signature>;
230}
231
232fn sc_minimal(raw_s: &[u8]) -> bool {
235 let mut rd = Cursor::new(raw_s);
236 let mut s = [0u64; 4];
237
238 rd.read_u64_into::<LittleEndian>(&mut s[..]).unwrap();
241 s.reverse();
242
243 for i in 0..4 {
245 match s[i].cmp(&CURVE_ORDER[i]) {
246 Ordering::Greater => return false,
247 Ordering::Less => return true,
248 Ordering::Equal => {}
249 }
250 }
251
252 false
254}
255
256pub fn signature_context_with_runtime_separation(
258 mut context: Vec<u8>,
259 runtime_id: &Namespace,
260) -> Vec<u8> {
261 context.extend(RUNTIME_SIGNATURE_CONTEXT_SEPARATOR);
262 context.extend(runtime_id.0);
263 context
264}
265
266pub fn signature_context_with_chain_separation(
268 mut context: Vec<u8>,
269 chain_context: &String,
270) -> Vec<u8> {
271 context.extend(CHAIN_SIGNATURE_CONTEXT_SEPARATOR);
272 context.extend(chain_context.as_bytes());
273 context
274}
275
276#[cfg(test)]
277mod tests {
278 use super::*;
279 use rustc_hex::FromHex;
280
281 #[test]
282 fn test_sc_minimal() {
283 assert!(sc_minimal(&[
285 0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9,
286 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 0x00, 0x00, 0x00, 0x10
288 ]));
289
290 assert!(sc_minimal(&[
292 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd5, 0x9c, 0xf7, 0xa2, 0xde, 0xf9,
293 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x00, 0x00, 0x10
295 ]));
296
297 assert!(sc_minimal(&[
299 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd5, 0x9c, 0xf7, 0xa2, 0xde, 0xf9,
300 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
301 0xff, 0xff, 0xff, 0x0f,
302 ]));
303
304 assert!(!sc_minimal(&[
306 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9,
307 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
308 0x00, 0x00, 0x00, 0x10
309 ]));
310
311 assert!(!sc_minimal(&[
313 0xef, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9,
314 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x10
316 ]));
317
318 assert!(!sc_minimal(&[
320 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd7, 0x9c, 0xf7, 0xa2, 0xde, 0xf9,
321 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322 0x00, 0x00, 0x00, 0x10
323 ]));
324
325 assert!(!sc_minimal(&[
327 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9,
328 0xde, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329 0x00, 0x00, 0x00, 0x10
330 ]));
331
332 assert!(!sc_minimal(&[
334 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9,
335 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
336 0x00, 0x00, 0x00, 0x10
337 ]));
338
339 assert!(!sc_minimal(&[
341 0x67, 0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d, 0xaf, 0xc0,
342 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33, 0x36, 0xa5, 0xc5, 0x1e, 0xb6,
343 0xf9, 0x46, 0xb3, 0x1d,
344 ]))
345 }
346
347 #[test]
348 fn test_private_key_to_bytes() {
349 let secret = PrivateKey::generate();
350 let bytes = secret.to_bytes();
351 let from_bytes = PrivateKey::from_bytes(bytes);
352 assert_eq!(secret.public_key(), from_bytes.public_key());
353 }
354
355 #[test]
356 #[should_panic]
357 fn test_private_key_to_bytes_malformed_a() {
358 PrivateKey::from_bytes(vec![]);
359 }
360
361 #[test]
362 #[should_panic]
363 fn test_private_key_to_bytes_malformed_b() {
364 PrivateKey::from_bytes(vec![1, 2, 3]);
365 }
366
367 #[test]
368 fn verification_small_order_a() {
369 let pbk = "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa";
371 let msg = "9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79";
372 let sig = "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43a5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04";
373
374 let pbk: Vec<u8> = pbk.from_hex().unwrap();
375 let msg: Vec<u8> = msg.from_hex().unwrap();
376 let sig: Vec<u8> = sig.from_hex().unwrap();
377
378 let pbk = PublicKey::from(pbk);
379 let sig = Signature::from(sig);
380
381 assert!(
382 sig.verify_raw(&pbk, &msg).is_err(),
383 "small order A not rejected"
384 )
385 }
386
387 #[test]
388 fn verification_small_order_r() {
389 let pbk = "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43";
391 let msg = "aebf3f2601a0c8c5d39cc7d8911642f740b78168218da8471772b35f9d35b9ab";
392 let sig = "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa8c4bd45aecaca5b24fb97bc10ac27ac8751a7dfe1baff8b953ec9f5833ca260e";
393
394 let pbk: Vec<u8> = pbk.from_hex().unwrap();
395 let msg: Vec<u8> = msg.from_hex().unwrap();
396 let sig: Vec<u8> = sig.from_hex().unwrap();
397
398 let pbk = PublicKey::from(pbk);
399 let sig = Signature::from(sig);
400
401 assert!(
402 sig.verify_raw(&pbk, &msg).is_err(),
403 "small order R not rejected"
404 )
405 }
406
407 #[test]
408 fn verification_is_cofactored() {
409 let pbk = "cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d";
411 let msg = "e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c";
412 let sig = "160a1cb0dc9c0258cd0a7d23e94d8fa878bcb1925f2c64246b2dee1796bed5125ec6bc982a269b723e0668e540911a9a6a58921d6925e434ab10aa7940551a09";
413
414 let pbk: Vec<u8> = pbk.from_hex().unwrap();
415 let msg: Vec<u8> = msg.from_hex().unwrap();
416 let sig: Vec<u8> = sig.from_hex().unwrap();
417
418 let pbk = PublicKey::from(pbk);
419 let sig = Signature::from(sig);
420
421 assert!(
422 sig.verify_raw(&pbk, &msg).is_ok(),
423 "verification is not cofactored(?)"
424 )
425 }
426
427 }