@@ -8,7 +8,7 @@ from collections import namedtuple
8
8
9
9
try :
10
10
from sagelib .opaque_common import derive_secret , hkdf_expand_label , hkdf_extract , I2OSP , OS2IP , OS2IP_le , encode_vector , encode_vector_len , to_hex , OPAQUE_NONCE_LENGTH
11
- from sagelib .opaque_core import OPAQUECore
11
+ from sagelib .opaque_core import OPAQUECore , OPAQUE_SEED_LENGTH
12
12
from sagelib .opaque_messages import deserialize_credential_request , deserialize_credential_response
13
13
except ImportError as e :
14
14
sys .exit ("Error loading preprocessed sage files. Try running `make setup && make clean pyfiles`. Full error: " + e )
@@ -76,9 +76,9 @@ class OPAQUE3DH(KeyExchange):
76
76
}
77
77
78
78
def derive_3dh_keys (self , dh_components , info ):
79
- dh1 = dh_components .sk1 * dh_components .pk1
80
- dh2 = dh_components .sk2 * dh_components .pk2
81
- dh3 = dh_components .sk3 * dh_components .pk3
79
+ dh1 = self . config . group . scalar_mult ( dh_components .sk1 , self . config . group . deserialize ( dh_components .pk1 ))
80
+ dh2 = self . config . group . scalar_mult ( dh_components .sk2 , self . config . group . deserialize ( dh_components .pk2 ))
81
+ dh3 = self . config . group . scalar_mult ( dh_components .sk3 , self . config . group . deserialize ( dh_components .pk3 ))
82
82
83
83
dh1_encoded = self .config .group .serialize (dh1 )
84
84
dh2_encoded = self .config .group .serialize (dh2 )
@@ -101,10 +101,9 @@ class OPAQUE3DH(KeyExchange):
101
101
102
102
def auth_client_start (self ):
103
103
self .client_nonce = self .rng .random_bytes (OPAQUE_NONCE_LENGTH )
104
- self .client_private_keyshare = ZZ (self .config .group .random_scalar (self .rng ))
105
- self .client_public_keyshare_bytes = self .config .group .serialize (self .client_private_keyshare * self .config .group .generator ())
106
-
107
- return TripleDHMessageInit (self .client_nonce , self .client_public_keyshare_bytes )
104
+ self .client_keyshare_seed = self .rng .random_bytes (OPAQUE_SEED_LENGTH )
105
+ self .client_private_keyshare , self .client_public_keyshare = self .core .derive_diffie_hellman_key_pair (self .client_keyshare_seed )
106
+ return TripleDHMessageInit (self .client_nonce , self .client_public_keyshare )
108
107
109
108
def generate_ke1 (self , password ):
110
109
cred_request , cred_metadata = self .core .create_credential_request (password )
@@ -116,14 +115,14 @@ class OPAQUE3DH(KeyExchange):
116
115
117
116
return self .serialized_request + ke1 .serialize ()
118
117
119
- def transcript_hasher (self , serialized_request , serialized_response , cleartext_credentials , client_nonce , client_public_keyshare_bytes , server_nonce , server_public_keyshare_bytes ):
118
+ def transcript_hasher (self , serialized_request , serialized_response , cleartext_credentials , client_nonce , client_public_keyshare , server_nonce , server_public_keyshare_bytes ):
120
119
hasher = self .config .hash ()
121
120
hasher .update (_as_bytes ("RFCXXXX" )) # RFCXXXX
122
121
hasher .update (encode_vector (self .config .context )) # context
123
122
hasher .update (encode_vector_len (cleartext_credentials .client_identity , 2 )) # client_identity
124
123
hasher .update (serialized_request ) # ke1: cred request
125
124
hasher .update (client_nonce ) # ke1: client nonce
126
- hasher .update (client_public_keyshare_bytes ) # ke1: client keyshare
125
+ hasher .update (client_public_keyshare ) # ke1: client keyshare
127
126
hasher .update (encode_vector_len (cleartext_credentials .server_identity , 2 )) # server identity
128
127
hasher .update (serialized_response ) # ke2: cred response
129
128
hasher .update (server_nonce ) # ke2: server nonce
@@ -133,21 +132,19 @@ class OPAQUE3DH(KeyExchange):
133
132
134
133
return hasher .digest ()
135
134
136
- def auth_server_respond (self , cred_request , cred_response , ke1 , cleartext_credentials , server_private_key , client_public_key ):
135
+ def auth_server_respond (self , cred_request , cred_response , ke1 , cleartext_credentials , server_private_key , client_public_keyshare ):
137
136
self .server_nonce = self .rng .random_bytes (OPAQUE_NONCE_LENGTH )
138
- self .server_private_keyshare = ZZ (self .config .group .random_scalar (self .rng ))
139
- self .server_public_keyshare = self .server_private_keyshare * self .config .group .generator ()
140
- server_public_keyshare_bytes = self .config .group .serialize (self .server_public_keyshare )
141
- client_public_keyshare = self .config .group .deserialize (ke1 .client_public_keyshare )
137
+ self .server_keyshare_seed = self .rng .random_bytes (OPAQUE_SEED_LENGTH )
138
+ self .server_private_keyshare , self .server_public_keyshare_bytes = self .core .derive_diffie_hellman_key_pair (self .server_keyshare_seed )
142
139
143
- transcript_hash = self .transcript_hasher (cred_request .serialize (), cred_response .serialize (), cleartext_credentials , ke1 .client_nonce , ke1 .client_public_keyshare , self .server_nonce , server_public_keyshare_bytes )
140
+ transcript_hash = self .transcript_hasher (cred_request .serialize (), cred_response .serialize (), cleartext_credentials , ke1 .client_nonce , ke1 .client_public_keyshare , self .server_nonce , self . server_public_keyshare_bytes )
144
141
145
142
# K3dh = epkU^eskS || epkU^skS || pkU^eskS
146
- dh_components = TripleDHComponents (client_public_keyshare , self .server_private_keyshare , client_public_keyshare , server_private_key , client_public_key , self .server_private_keyshare )
143
+ dh_components = TripleDHComponents (ke1 . client_public_keyshare , self .server_private_keyshare , ke1 . client_public_keyshare , server_private_key , client_public_keyshare , self .server_private_keyshare )
147
144
148
145
server_mac_key , client_mac_key , session_key , handshake_secret = self .derive_3dh_keys (dh_components , self .hasher .digest ())
149
146
mac = hmac .digest (server_mac_key , transcript_hash , self .config .hash )
150
- ake2 = TripleDHMessageRespond (self .server_nonce , server_public_keyshare_bytes , mac )
147
+ ake2 = TripleDHMessageRespond (self .server_nonce , self . server_public_keyshare_bytes , mac )
151
148
152
149
self .server_mac_key = server_mac_key
153
150
self .ake2 = ake2
@@ -158,27 +155,24 @@ class OPAQUE3DH(KeyExchange):
158
155
159
156
return ake2
160
157
161
- def generate_ke2 (self , msg , oprf_seed , credential_identifier , envU , masking_key , server_identity , server_private_key , server_public_key , client_identity , client_public_key ):
158
+ def generate_ke2 (self , msg , oprf_seed , credential_identifier , envU , masking_key , server_identity , server_private_key , server_public_keyshare , client_identity , client_public_keyshare ):
162
159
cred_request , offset = deserialize_credential_request (self .config , msg )
163
160
ke1 = deserialize_tripleDH_init (self .config , msg [offset :])
164
161
165
- server_public_key_bytes = self .config .group .serialize (server_public_key )
166
- cred_response = self .core .create_credential_response (cred_request , server_public_key_bytes , oprf_seed , envU , credential_identifier , masking_key )
162
+ cred_response = self .core .create_credential_response (cred_request , server_public_keyshare , oprf_seed , envU , credential_identifier , masking_key )
167
163
serialized_response = cred_response .serialize ()
168
164
self .masking_nonce = cred_response .masking_nonce
169
165
170
- cleartext_credentials = self .core .create_cleartext_credentials (server_public_key_bytes , self . config . group . serialize ( client_public_key ) , server_identity , client_identity )
171
- ake2 = self .auth_server_respond (cred_request , cred_response , ke1 , cleartext_credentials , server_private_key , client_public_key )
166
+ cleartext_credentials = self .core .create_cleartext_credentials (server_public_keyshare , client_public_keyshare , server_identity , client_identity )
167
+ ake2 = self .auth_server_respond (cred_request , cred_response , ke1 , cleartext_credentials , server_private_key , client_public_keyshare )
172
168
173
169
return serialized_response + ake2 .serialize ()
174
170
175
- def auth_client_finalize (self , cred_response , ake2 , cleartext_credentials , client_private_key , client_public_key ):
176
- transcript_hash = self .transcript_hasher (self .serialized_request , cred_response .serialize (), cleartext_credentials , self .client_nonce , self .client_public_keyshare_bytes , ake2 .server_nonce , ake2 .server_public_keyshare_bytes )
177
- server_public_key = self .config .group .deserialize (cleartext_credentials .server_public_key_bytes )
178
- server_public_keyshare = self .config .group .deserialize (ake2 .server_public_keyshare_bytes )
171
+ def auth_client_finalize (self , cred_response , ake2 , cleartext_credentials , client_private_key ):
172
+ transcript_hash = self .transcript_hasher (self .serialized_request , cred_response .serialize (), cleartext_credentials , self .client_nonce , self .client_public_keyshare , ake2 .server_nonce , ake2 .server_public_keyshare_bytes )
179
173
180
174
# K3dh = epkS^eskU || pkS^eskU || epkS^skU
181
- dh_components = TripleDHComponents (server_public_keyshare , self .client_private_keyshare , server_public_key , self .client_private_keyshare , server_public_keyshare , client_private_key )
175
+ dh_components = TripleDHComponents (ake2 . server_public_keyshare_bytes , self .client_private_keyshare , cleartext_credentials . server_public_key_bytes , self .client_private_keyshare , ake2 . server_public_keyshare_bytes , client_private_key )
182
176
183
177
server_mac_key , client_mac_key , session_key , handshake_secret = self .derive_3dh_keys (dh_components , self .hasher .digest ())
184
178
server_mac = hmac .digest (server_mac_key , transcript_hash , self .config .hash )
@@ -197,16 +191,20 @@ class OPAQUE3DH(KeyExchange):
197
191
198
192
return TripleDHMessageFinish (client_mac )
199
193
200
- def generate_ke3 (self , msg , client_identity , client_public_key , server_identity ):
194
+ def generate_ke3 (self , msg , client_identity , server_identity ):
201
195
cred_response , offset = deserialize_credential_response (self .config , msg )
202
196
ake2 = deserialize_tripleDH_respond (self .config , msg [offset :])
203
197
client_private_key_bytes , cleartext_credentials , export_key = self .core .recover_credentials (self .password , self .cred_metadata , cred_response , client_identity , server_identity )
204
- client_private_key = OS2IP (client_private_key_bytes )
205
- if "ristretto" in self .config .group .name or "decaf" in self .config .group .name :
198
+
199
+ if "curve25519" in self .config .group .name :
200
+ client_private_key = client_private_key_bytes
201
+ elif "ristretto" in self .config .group .name or "decaf" in self .config .group .name :
206
202
client_private_key = OS2IP_le (client_private_key_bytes )
207
- self .export_key = export_key
203
+ else :
204
+ client_private_key = OS2IP (client_private_key_bytes )
208
205
209
- ke3 = self .auth_client_finalize (cred_response , ake2 , cleartext_credentials , client_private_key , client_public_key )
206
+ self .export_key = export_key
207
+ ke3 = self .auth_client_finalize (cred_response , ake2 , cleartext_credentials , client_private_key )
210
208
211
209
return ke3 .serialize ()
212
210
@@ -228,11 +226,11 @@ class OPAQUE3DH(KeyExchange):
228
226
# } KE1M;
229
227
def deserialize_tripleDH_init (config , data ):
230
228
client_nonce = data [0 :OPAQUE_NONCE_LENGTH ]
231
- client_public_keyshare_bytes = data [OPAQUE_NONCE_LENGTH :]
229
+ client_public_keyshare = data [OPAQUE_NONCE_LENGTH :]
232
230
length = config .oprf_suite .group .element_byte_length ()
233
- if len (client_public_keyshare_bytes ) != length :
234
- raise Exception ("Invalid client_public_keyshare length: %d %d" % (len (client_public_keyshare_bytes ), length ))
235
- return TripleDHMessageInit (client_nonce , client_public_keyshare_bytes )
231
+ if len (client_public_keyshare ) != length :
232
+ raise Exception ("Invalid client_public_keyshare length: %d %d" % (len (client_public_keyshare ), length ))
233
+ return TripleDHMessageInit (client_nonce , client_public_keyshare )
236
234
237
235
class TripleDHMessageInit (object ):
238
236
def __init__ (self , client_nonce , client_public_keyshare ):
0 commit comments