-
Notifications
You must be signed in to change notification settings - Fork 98
/
Copy pathaead.rs
198 lines (176 loc) · 6.25 KB
/
aead.rs
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// -*- mode: rust; -*-
//
// This file is part of schnorrkel.
// Copyright (c) 2019 Web 3 Foundation
// See LICENSE for licensing information.
//
// Authors:
// - Jeff Burdges <jeff@web3.foundation>
//! Encryption using schnorrkel keys
/*
Riad Wahby writes:
As luck would have it, Degabriele, Lehmann, Paterson, Smart, and
Strefler (CT-RSA '12, https://eprint.iacr.org/2011/615) show that
ECIES and EC-Schnorr signatures are secure when instantiated with
the same secret key, in the random oracle model and assuming that
gap-DH and gap-DLP are hard (see Theorem 2).
It seems like this proof could be extended to EdDSA and HPKE with
DHKEM---but I haven't done more than glance! so this should be
regarded as a pointer, not a recommendation.
*/
// use rand_core::{RngCore,CryptoRng};
use aead::{
KeyInit, KeySizeUser,
generic_array::{GenericArray},
};
use curve25519_dalek::digest::generic_array::typenum::{U32};
use curve25519_dalek::{
ristretto::{CompressedRistretto}, // RistrettoPoint
};
use super::{SecretKey, PublicKey, Keypair, SignatureResult};
use crate::context::SigningTranscript;
use crate::cert::AdaptorCertPublic;
fn make_aead<T, AEAD>(mut t: T) -> AEAD
where
T: SigningTranscript,
AEAD: KeyInit,
{
let mut key: GenericArray<u8, <AEAD as KeySizeUser>::KeySize> = Default::default();
t.challenge_bytes(b"", key.as_mut_slice());
AEAD::new(&key)
}
impl SecretKey {
/// Commit the results of a key exchange into a transcript
#[inline(always)]
pub(crate) fn raw_key_exchange(&self, public: &PublicKey) -> CompressedRistretto {
(self.key * public.as_point()).compress()
}
/// Commit the results of a raw key exchange into a transcript
pub fn commit_raw_key_exchange<T>(&self, t: &mut T, ctx: &'static [u8], public: &PublicKey)
where
T: SigningTranscript,
{
let p = self.raw_key_exchange(public);
t.commit_point(ctx, &p);
}
/// An AEAD from a key exchange with the specified public key.
///
/// Requires the AEAD have a 32 byte public key and does not support a context.
pub fn aead32_unauthenticated<AEAD>(&self, public: &PublicKey) -> AEAD
where
AEAD: KeyInit<KeySize = U32>,
{
let mut key: GenericArray<u8, <AEAD as KeySizeUser>::KeySize> = Default::default();
key.clone_from_slice(self.raw_key_exchange(public).as_bytes());
AEAD::new(&key)
}
}
impl PublicKey {
/// Initialize an AEAD to the public key `self` using an ephemeral key exchange.
///
/// Returns the ephemeral public key and AEAD.
pub fn init_aead_unauthenticated<AEAD: KeyInit>(
&self,
ctx: &[u8],
) -> (CompressedRistretto, AEAD) {
let ephemeral = Keypair::generate();
let aead = ephemeral.aead_unauthenticated(ctx, self);
(ephemeral.public.into_compressed(), aead)
}
/// Initialize an AEAD to the public key `self` using an ephemeral key exchange.
///
/// Returns the ephemeral public key and AEAD.
/// Requires the AEAD have a 32 byte public key and does not support a context.
pub fn init_aead32_unauthenticated<AEAD>(&self) -> (CompressedRistretto, AEAD)
where
AEAD: KeyInit<KeySize = U32>,
{
let secret = SecretKey::generate();
let aead = secret.aead32_unauthenticated(self);
(secret.to_public().into_compressed(), aead)
}
}
impl Keypair {
/// Commit the results of a key exchange into a transcript
/// including the public keys in sorted order.
pub fn commit_key_exchange<T>(&self, t: &mut T, ctx: &'static [u8], public: &PublicKey)
where
T: SigningTranscript,
{
let mut pks = [self.public.as_compressed(), public.as_compressed()];
pks.sort_unstable_by_key(|pk| pk.as_bytes());
for pk in &pks {
t.commit_point(b"pk", pk);
}
self.secret.commit_raw_key_exchange(t, ctx, public);
}
/// An AEAD from a key exchange with the specified public key.
pub fn aead_unauthenticated<AEAD: KeyInit>(&self, ctx: &[u8], public: &PublicKey) -> AEAD {
let mut t = merlin::Transcript::new(b"KEX");
t.append_message(b"ctx", ctx);
self.commit_key_exchange(&mut t, b"kex", public);
make_aead(t)
}
/// Reciever's 2DH AEAD
pub fn reciever_aead<T, AEAD>(
&self,
mut t: T,
ephemeral_pk: &PublicKey,
static_pk: &PublicKey,
) -> AEAD
where
T: SigningTranscript,
AEAD: KeyInit,
{
self.commit_key_exchange(&mut t, b"epk", ephemeral_pk);
self.commit_key_exchange(&mut t, b"epk", static_pk);
make_aead(t)
}
/// Sender's 2DH AEAD
pub fn sender_aead<T, AEAD>(&self, mut t: T, public: &PublicKey) -> (CompressedRistretto, AEAD)
where
T: SigningTranscript,
AEAD: KeyInit,
{
let key = t.witness_scalar(b"make_esk", &[&self.secret.nonce]);
let ekey = SecretKey { key, nonce: self.secret.nonce }.to_keypair();
ekey.commit_key_exchange(&mut t, b"epk", public);
self.commit_key_exchange(&mut t, b"epk", public);
(ekey.public.into_compressed(), make_aead(t))
}
/// Reciever's AEAD with Adaptor certificate.
///
/// Returns the AEAD constructed from an ephemeral key exchange
/// with the public key computed form the sender's public key
/// and their implicit Adaptor certificate.
pub fn reciever_aead_with_adaptor_cert<T, AEAD>(
&self,
t: T,
cert_public: &AdaptorCertPublic,
public: &PublicKey,
) -> SignatureResult<AEAD>
where
T: SigningTranscript,
AEAD: KeyInit,
{
let epk = public.open_adaptor_cert(t, cert_public)?;
Ok(self.aead_unauthenticated(b"", &epk))
}
/// Sender's AEAD with Adaptor certificate.
///
/// Along with the AEAD, we return the implicit Adaptor certificate
/// from which the receiver recreates the ephemeral public key.
pub fn sender_aead_with_adaptor_cert<T, AEAD>(
&self,
t: T,
public: &PublicKey,
) -> (AdaptorCertPublic, AEAD)
where
T: SigningTranscript + Clone,
AEAD: KeyInit,
{
let (cert, secret) = self.issue_self_adaptor_cert(t);
let aead = secret.to_keypair().aead_unauthenticated(b"", public);
(cert, aead)
}
}