1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use std::borrow::Borrow;
use curve25519_dalek::{constants, ristretto, scalar};
use subtle::ConstantTimeEq;
use super::*;
pub struct EphemeralKeyDerivationBuilder {
r: PrivateKey,
}
#[derive(Clone)]
pub struct Recogniser {
inner: ristretto::RistrettoPoint,
}
impl Recogniser {
pub fn bytes(&self) -> [u8; 32] {
self.inner.compress().to_bytes()
}
pub fn from_bytes(bytes: [u8; 32]) -> Recogniser {
Recogniser {
inner: ristretto::CompressedRistretto(bytes).decompress().unwrap(),
}
}
}
impl EphemeralKeyDerivationBuilder {
pub fn new(sk: PrivateKey) -> Self {
EphemeralKeyDerivationBuilder { r: sk }
}
pub fn default<R: rand::SecureRandom>(rng: &R) -> crate::crypto::Result<Self> {
Ok(Self::new(PrivateKey::generate(rng)?))
}
pub fn derive(&self, public_base: &PublicKey) -> crate::crypto::Result<PublicKey> {
let hash = agree_to_scalar(public_base, &self.r)?;
Ok(PublicKey {
inner: public_base.inner + &hash * &constants::RISTRETTO_BASEPOINT_TABLE,
})
}
pub fn finish(self) -> crate::crypto::Result<Recogniser> {
self.r
.compute_public_key()
.map(|k| Recogniser { inner: k.inner })
}
}
pub struct EphemeralKeyRecovery<'sk> {
master_key: &'sk PrivateKey,
scalar: scalar::Scalar,
target: PublicKey,
}
impl<'sk> EphemeralKeyRecovery<'sk> {
pub fn new(
recogniser: &Recogniser,
master_key: &'sk PrivateKey,
) -> crate::crypto::Result<Self> {
let recogniser = PublicKey {
inner: recogniser.inner,
};
let master_public_key = master_key.compute_public_key()?;
let agreed = agree_to_scalar(&recogniser, master_key)?;
Ok(EphemeralKeyRecovery {
target: PublicKey {
inner: master_public_key.inner + &agreed * &constants::RISTRETTO_BASEPOINT_TABLE,
},
master_key,
scalar: agreed,
})
}
pub fn recognise(&self, public_key: &PublicKey) -> crate::crypto::Result<Option<PrivateKey>> {
if public_key.inner.ct_eq(&self.target.inner).unwrap_u8() == 0 {
return Ok(None);
}
Ok(Some(PrivateKey {
inner: self.master_key.inner + self.scalar,
}))
}
pub fn recognise_one<Key, I>(&self, i: I) -> crate::crypto::Result<Option<PrivateKey>>
where
Key: Borrow<PublicKey>,
I: Iterator<Item = Key>,
{
for key in i {
if let Some(sk) = self.recognise(key.borrow())? {
return Ok(Some(sk));
}
}
Ok(None)
}
}