Skip to content

Commit

Permalink
Merge pull request snapview#174 from de-vri-es/derive-accept-key
Browse files Browse the repository at this point in the history
Expose `handshake::derive_accept_key` as public API.
  • Loading branch information
Alexey Galakhov committed Feb 6, 2021
2 parents 5586d0a + 9661274 commit 985d657
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,7 @@

- Add `CapacityError`, `UrlError`, and `ProtocolError` types to represent the different types of capacity, URL, and protocol errors respectively.
- Modify variants `Error::Capacity`, `Error::Url`, and `Error::Protocol` to hold the above errors types instead of string error messages.
- Add `handshake::derive_accept_key` to facilitate external handshakes.

# 0.12.0

Expand Down
4 changes: 2 additions & 2 deletions src/handshake/client.rs
Expand Up @@ -10,7 +10,7 @@ use httparse::Status;
use log::*;

use super::{
convert_key,
derive_accept_key,
headers::{FromHttparse, MAX_HEADERS},
machine::{HandshakeMachine, StageResult, TryParse},
HandshakeRole, MidHandshake, ProcessingResult,
Expand Down Expand Up @@ -60,7 +60,7 @@ impl<S: Read + Write> ClientHandshake<S> {
};

let client = {
let accept_key = convert_key(key.as_ref()).unwrap();
let accept_key = derive_accept_key(key.as_ref());
ClientHandshake { verify_data: VerifyData { accept_key }, config, _marker: PhantomData }
};

Expand Down
15 changes: 9 additions & 6 deletions src/handshake/mod.rs
Expand Up @@ -110,26 +110,29 @@ pub enum ProcessingResult<Stream, FinalResult> {
Done(FinalResult),
}

/// Turns a Sec-WebSocket-Key into a Sec-WebSocket-Accept.
fn convert_key(input: &[u8]) -> Result<String, Error> {
/// Derive the `Sec-WebSocket-Accept` response header from a `Sec-WebSocket-Key` request header.
///
/// This function can be used to perform a handshake before passing a raw TCP stream to
/// [`WebSocket::from_raw_socket`][crate::protocol::WebSocket::from_raw_socket].
pub fn derive_accept_key(request_key: &[u8]) -> String {
// ... field is constructed by concatenating /key/ ...
// ... with the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" (RFC 6455)
const WS_GUID: &[u8] = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
let mut sha1 = Sha1::default();
sha1.update(input);
sha1.update(request_key);
sha1.update(WS_GUID);
Ok(base64::encode(&sha1.finalize()))
base64::encode(&sha1.finalize())
}

#[cfg(test)]
mod tests {
use super::convert_key;
use super::derive_accept_key;

#[test]
fn key_conversion() {
// example from RFC 6455
assert_eq!(
convert_key(b"dGhlIHNhbXBsZSBub25jZQ==").unwrap(),
derive_accept_key(b"dGhlIHNhbXBsZSBub25jZQ=="),
"s3pPLMBiTxaQ9kYGzzhZRbK+xOo="
);
}
Expand Down
4 changes: 2 additions & 2 deletions src/handshake/server.rs
Expand Up @@ -13,7 +13,7 @@ use httparse::Status;
use log::*;

use super::{
convert_key,
derive_accept_key,
headers::{FromHttparse, MAX_HEADERS},
machine::{HandshakeMachine, StageResult, TryParse},
HandshakeRole, MidHandshake, ProcessingResult,
Expand Down Expand Up @@ -75,7 +75,7 @@ fn create_parts<T>(request: &HttpRequest<T>) -> Result<Builder> {
.version(request.version())
.header("Connection", "Upgrade")
.header("Upgrade", "websocket")
.header("Sec-WebSocket-Accept", convert_key(key.as_bytes())?);
.header("Sec-WebSocket-Accept", derive_accept_key(key.as_bytes()));

Ok(builder)
}
Expand Down

0 comments on commit 985d657

Please sign in to comment.