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
use generic_array::{GenericArray, ArrayLength};
use keystream::SeekableKeyStream;
use rac::{LineValid, Curve};
use crypto_mac::{Mac, NewMac};
use digest::{Update, FixedOutput};
pub trait PseudoRandomStream<T>
where
T: ArrayLength<u8>,
{
fn seed(v: GenericArray<u8, T>) -> Self;
}
pub type SharedSecret<A> = GenericArray<u8, <<A as Curve>::Scalar as LineValid>::Length>;
pub trait Sphinx {
type MacLength: ArrayLength<u8>;
type AsymmetricKey: Curve;
type Stream: SeekableKeyStream;
fn mu<'a, I>(
shared: &SharedSecret<Self::AsymmetricKey>,
data: I,
) -> GenericArray<u8, Self::MacLength>
where
I: Iterator<Item = &'a [u8]>;
fn rho(shared: &SharedSecret<Self::AsymmetricKey>) -> Self::Stream;
fn pi(shared: &SharedSecret<Self::AsymmetricKey>) -> Self::Stream;
fn tau(public_key: Self::AsymmetricKey) -> SharedSecret<Self::AsymmetricKey>;
fn blinding(
public_key: &Self::AsymmetricKey,
shared: &SharedSecret<Self::AsymmetricKey>,
) -> <Self::AsymmetricKey as Curve>::Scalar;
}
impl<A, C, D, S> Sphinx for (A, C, D, S)
where
A: Curve,
C: Mac + NewMac,
D: Default + Update + FixedOutput<OutputSize = <<A as Curve>::Scalar as LineValid>::Length>,
S: PseudoRandomStream<C::OutputSize> + SeekableKeyStream,
{
type MacLength = C::OutputSize;
type AsymmetricKey = A;
type Stream = S;
fn mu<'a, I>(
shared: &SharedSecret<Self::AsymmetricKey>,
data: I,
) -> GenericArray<u8, Self::MacLength>
where
I: Iterator<Item = &'a [u8]>,
{
let mut collector = C::new_varkey(b"mu").unwrap();
collector.update(shared);
let key = collector.finalize().into_bytes();
let mut collector = C::new_varkey(&key).unwrap();
data.for_each(|s| collector.update(s));
collector.finalize().into_bytes()
}
fn rho(shared: &SharedSecret<Self::AsymmetricKey>) -> Self::Stream {
let mut collector = C::new_varkey(b"rho").unwrap();
collector.update(shared);
let key = collector.finalize().into_bytes();
S::seed(key)
}
fn pi(shared: &SharedSecret<Self::AsymmetricKey>) -> Self::Stream {
let mut collector = C::new_varkey(b"um").unwrap();
collector.update(shared);
let key = collector.finalize().into_bytes();
S::seed(key)
}
fn tau(public_key: Self::AsymmetricKey) -> SharedSecret<Self::AsymmetricKey> {
D::default()
.chain(public_key.compress().clone_line().as_ref())
.finalize_fixed()
}
fn blinding(
public_key: &Self::AsymmetricKey,
shared: &SharedSecret<Self::AsymmetricKey>,
) -> <Self::AsymmetricKey as Curve>::Scalar {
let r = D::default()
.chain(public_key.compress().clone_line().as_ref())
.chain(shared)
.finalize_fixed();
LineValid::try_clone_array(&r).unwrap()
}
}