Skip to content

Commit 753d327

Browse files
committed
Run SHA256 in a blocking executor
1 parent 648250d commit 753d327

File tree

2 files changed

+58
-21
lines changed

2 files changed

+58
-21
lines changed

sqlx-postgres/src/connection/sasl.rs

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
use crate::connection::stream::PgStream;
22
use crate::error::Error;
3-
use crate::message::{Authentication, AuthenticationSasl, SaslInitialResponse, SaslResponse};
3+
use crate::message::{
4+
Authentication, AuthenticationSasl, AuthenticationSaslContinue, SaslInitialResponse,
5+
SaslResponse,
6+
};
7+
use crate::rt;
48
use crate::PgConnectOptions;
59
use hmac::{Hmac, Mac};
610
use rand::Rng;
@@ -85,12 +89,36 @@ pub(crate) async fn authenticate(
8589
}
8690
};
8791

92+
let password = options.password.clone().unwrap_or_default();
93+
let (mac, client_final_message) = rt::spawn_blocking(move || {
94+
final_message(client_first_message_bare, channel_binding, cont, password)
95+
})
96+
.await?;
97+
98+
stream.send(SaslResponse(&client_final_message)).await?;
99+
100+
let data = match stream.recv_expect().await? {
101+
Authentication::SaslFinal(data) => data,
102+
103+
auth => {
104+
return Err(err_protocol!("expected SASLFinal but received {:?}", auth));
105+
}
106+
};
107+
108+
// authentication is only considered valid if this verification passes
109+
mac.verify_slice(&data.verifier).map_err(Error::protocol)?;
110+
111+
Ok(())
112+
}
113+
114+
fn final_message(
115+
client_first_message_bare: String,
116+
channel_binding: String,
117+
cont: AuthenticationSaslContinue,
118+
password: String,
119+
) -> Result<(Hmac<Sha256>, String), Error> {
88120
// SaltedPassword := Hi(Normalize(password), salt, i)
89-
let salted_password = hi(
90-
options.password.as_deref().unwrap_or_default(),
91-
&cont.salt,
92-
cont.iterations,
93-
)?;
121+
let salted_password = hi(&password, &cont.salt, cont.iterations)?;
94122

95123
// ClientKey := HMAC(SaltedPassword, "Client Key")
96124
let mut mac = Hmac::<Sha256>::new_from_slice(&salted_password).map_err(Error::protocol)?;
@@ -143,20 +171,7 @@ pub(crate) async fn authenticate(
143171
let mut client_final_message = format!("{client_final_message_wo_proof},{CLIENT_PROOF_ATTR}=");
144172
BASE64_STANDARD.encode_string(client_proof, &mut client_final_message);
145173

146-
stream.send(SaslResponse(&client_final_message)).await?;
147-
148-
let data = match stream.recv_expect().await? {
149-
Authentication::SaslFinal(data) => data,
150-
151-
auth => {
152-
return Err(err_protocol!("expected SASLFinal but received {:?}", auth));
153-
}
154-
};
155-
156-
// authentication is only considered valid if this verification passes
157-
mac.verify_slice(&data.verifier).map_err(Error::protocol)?;
158-
159-
Ok(())
174+
Ok((mac, client_final_message))
160175
}
161176

162177
// nonce is a sequence of random printable bytes
@@ -223,3 +238,25 @@ fn bench_sasl_hi(b: &mut test::Bencher) {
223238
);
224239
});
225240
}
241+
242+
#[cfg(test)]
243+
mod tests {
244+
245+
use super::*;
246+
247+
use crate::io::ProtocolDecode;
248+
249+
#[test]
250+
fn mac() {
251+
let start = std::time::Instant::now();
252+
let (_mac, _client_final_message) = final_message(
253+
"first_message_bare".to_string(),
254+
"channel_binding".to_string(),
255+
AuthenticationSaslContinue::decode_with("r=/z+giZiTxAH7r8sNAeHr7cvpqV3uo7G/bJBIJO3pjVM7t3ng,s=4UV68bIkC8f9/X8xH7aPhg==,i=4096".as_bytes().into(), ()).unwrap(),
256+
"some-password".to_string(),
257+
)
258+
.unwrap();
259+
let duration = start.elapsed();
260+
dbg!(duration);
261+
}
262+
}

sqlx-postgres/src/message/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ mod startup;
3030
mod sync;
3131
mod terminate;
3232

33-
pub use authentication::{Authentication, AuthenticationSasl};
33+
pub use authentication::{Authentication, AuthenticationSasl, AuthenticationSaslContinue};
3434
pub use backend_key_data::BackendKeyData;
3535
pub use bind::Bind;
3636
pub use close::Close;

0 commit comments

Comments
 (0)