pub fn update(&mut self, message: &[u8]) -> io::Result<()> {
        let (client_nonce, password) = match mem::replace(&mut self.state, State::Done) {
            State::Update { nonce, password } => (nonce, password),
            _ => return Err(io::Error::new(io::ErrorKind::Other, "invalid SCRAM state")),
        };

        let message = str::from_utf8(message).map_err(|e| {
            io::Error::new(io::ErrorKind::InvalidInput, e)
        })?;

        let parsed = Parser::new(message).server_first_message()?;

        if !parsed.nonce.starts_with(&client_nonce) {
            return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid nonce"));
        }

        let salt = match base64::decode(parsed.salt) {
            Ok(salt) => salt,
            Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidInput, e)),
        };

        let salted_password = hi(&password, &salt, parsed.iteration_count);

        let mut hmac = Hmac::<Sha256>::new(&salted_password)
            .expect("HMAC is able to accept all key sizes");
        hmac.input(b"Client Key");
        let client_key = hmac.result().code();

        let mut hash = Sha256::default();
        hash.input(client_key.as_slice());
        let stored_key = hash.result();

        self.message.clear();
        write!(&mut self.message, "c=biws,r={}", parsed.nonce).unwrap();

        let auth_message = format!("n=,r={},{},{}", client_nonce, message, self.message);

        let mut hmac = Hmac::<Sha256>::new(&stored_key)
            .expect("HMAC is able to accept all key sizes");
        hmac.input(auth_message.as_bytes());
        let client_signature = hmac.result();

        let mut client_proof = GenericArray::<u8, U32>::clone_from_slice(&client_key);
        for (proof, signature) in client_proof.iter_mut().zip(client_signature.code()) {
            *proof ^= signature;
        }

        write!(&mut self.message, ",p={}", base64::encode(&*client_proof)).unwrap();

        self.state = State::Finish {
            salted_password: salted_password,
            auth_message: auth_message,
        };
        Ok(())
    }
/// Updates the state machine with the response from the backend.
///
/// This should be called when an `AuthenticationSASLContinue` message is received.
Updates the state machine with the response from the backend.
This should be called when an `AuthenticationSASLContinue` message is received.
Updates the state machine with the response from the backend . This should be called when an ` AuthenticationSASLContinue ` message is received .
pub fn update(&mut self, message: &[u8]) -> io::Result<()> {
        let (client_nonce, password) = match mem::replace(&mut self.state, State::Done) {
            State::Update { nonce, password } => (nonce, password),
            _ => return Err(io::Error::new(io::ErrorKind::Other, "invalid SCRAM state")),
        };
        let message = str::from_utf8(message).map_err(|e| {
            io::Error::new(io::ErrorKind::InvalidInput, e)
        })?;
        let parsed = Parser::new(message).server_first_message()?;
        if !parsed.nonce.starts_with(&client_nonce) {
            return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid nonce"));
        }
        let salt = match base64::decode(parsed.salt) {
            Ok(salt) => salt,
            Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidInput, e)),
        };
        let salted_password = hi(&password, &salt, parsed.iteration_count);
        let mut hmac = Hmac::<Sha256>::new(&salted_password)
            .expect("HMAC is able to accept all key sizes");
        hmac.input(b"Client Key");
        let client_key = hmac.result().code();
        let mut hash = Sha256::default();
        hash.input(client_key.as_slice());
        let stored_key = hash.result();
        self.message.clear();
        write!(&mut self.message, "c=biws,r={}", parsed.nonce).unwrap();
        let auth_message = format!("n=,r={},{},{}", client_nonce, message, self.message);
        let mut hmac = Hmac::<Sha256>::new(&stored_key)
            .expect("HMAC is able to accept all key sizes");
        hmac.input(auth_message.as_bytes());
        let client_signature = hmac.result();
        let mut client_proof = GenericArray::<u8, U32>::clone_from_slice(&client_key);
        for (proof, signature) in client_proof.iter_mut().zip(client_signature.code()) {
            *proof ^= signature;
        }
        write!(&mut self.message, ",p={}", base64::encode(&*client_proof)).unwrap();
        self.state = State::Finish {
            salted_password: salted_password,
            auth_message: auth_message,
        };
        Ok(())
    }
pub fn update ( & mut self , message : & [ u8 ] ) -> io :: Result < ( ) > { let ( client_nonce , password ) = match mem :: replace ( & mut self . state , State :: Done ) { State :: Update { nonce , password } => ( nonce , password ) , _ => return Err ( io :: Error :: new ( io :: ErrorKind :: Other , " " ) ) , } ; let message = str :: from_utf8 ( message ) . map_err ( | e | { io :: Error :: new ( io :: ErrorKind :: InvalidInput , e ) } ) ? ; let parsed = Parser :: new ( message ) . server_first_message ( ) ? ; if ! parsed . nonce . starts_with ( & client_nonce ) { return Err ( io :: Error :: new ( io :: ErrorKind :: InvalidInput , " " ) ) ; } let salt = match base64 :: decode ( parsed . salt ) { Ok ( salt ) => salt , Err ( e ) => return Err ( io :: Error :: new ( io :: ErrorKind :: InvalidInput , e ) ) , } ; let salted_password = hi ( & password , & salt , parsed . iteration_count ) ; let mut hmac = Hmac :: < Sha256 > :: new ( & salted_password ) . expect ( " " ) ; hmac . input ( b" " ) ; let client_key = hmac . result ( ) . code ( ) ; let mut hash = Sha256 :: default ( ) ; hash . input ( client_key . as_slice ( ) ) ; let stored_key = hash . result ( ) ; self . message . clear ( ) ; write ! ( mut self message " " parsed nonce ) . unwrap ( ) ; let auth_message = format ! ( " " client_nonce message self message ) ; let mut hmac = Hmac :: < Sha256 > :: new ( & stored_key ) . expect ( " " ) ; hmac . input ( auth_message . as_bytes ( ) ) ; let client_signature = hmac . result ( ) ; let mut client_proof = GenericArray :: < u8 , U32 > :: clone_from_slice ( & client_key ) ; for ( proof , signature ) in client_proof . iter_mut ( ) . zip ( client_signature . code ( ) ) { * proof ^= signature ; } write ! ( mut self message " " base64 encode ( client_proof ) ) . unwrap ( ) ; self . state = State :: Finish { salted_password : salted_password , auth_message : auth_message , } ; Ok ( ( ) ) }
Updates the state machine with the response from the backend.
Updates the state machine with the response from the backend .
&mut self
message
&[u8]
&mut self
message
&[u8]