upgrade base64 crate to 0.21 (#289)

This commit is contained in:
Carson McManus 2023-07-10 11:41:36 -04:00 committed by GitHub
parent d1ff150cbf
commit 96f342137a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 98 additions and 57 deletions

14
Cargo.lock generated
View file

@ -262,12 +262,6 @@ version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270"
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.21.2" version = "0.21.2"
@ -2427,7 +2421,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55"
dependencies = [ dependencies = [
"async-compression", "async-compression",
"base64 0.21.2", "base64",
"bytes", "bytes",
"cookie 0.16.2", "cookie 0.16.2",
"cookie_store", "cookie_store",
@ -2567,7 +2561,7 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2"
dependencies = [ dependencies = [
"base64 0.21.2", "base64",
] ]
[[package]] [[package]]
@ -3009,7 +3003,7 @@ name = "steamguard"
version = "0.10.1" version = "0.10.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64 0.13.1", "base64",
"cookie 0.14.4", "cookie 0.14.4",
"hmac", "hmac",
"lazy_static 1.4.0", "lazy_static 1.4.0",
@ -3043,7 +3037,7 @@ dependencies = [
"aes 0.8.3", "aes 0.8.3",
"anyhow", "anyhow",
"argon2", "argon2",
"base64 0.13.1", "base64",
"cbc", "cbc",
"clap", "clap",
"clap_complete", "clap_complete",

View file

@ -31,7 +31,7 @@ path = "src/main.rs"
[dependencies] [dependencies]
anyhow = "^1.0" anyhow = "^1.0"
base64 = "0.13.0" base64 = "0.21.2"
text_io = "0.1.8" text_io = "0.1.8"
rpassword = "5.0" rpassword = "5.0"
reqwest = { version = "0.11", default-features = false, features = ["blocking", "json", "cookies", "gzip", "rustls-tls"] } reqwest = { version = "0.11", default-features = false, features = ["blocking", "json", "cookies", "gzip", "rustls-tls"] }

View file

@ -1,7 +1,9 @@
use aes::cipher::block_padding::Pkcs7; use aes::cipher::block_padding::Pkcs7;
use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit}; use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit};
use aes::Aes256; use aes::Aes256;
use anyhow::Context;
use argon2::Argon2; use argon2::Argon2;
use base64::Engine;
use log::*; use log::*;
use super::*; use super::*;
@ -19,7 +21,7 @@ impl Argon2idAes256 {
fn get_encryption_key(passkey: &str, salt: &str) -> anyhow::Result<[u8; Self::KEY_SIZE_BYTES]> { fn get_encryption_key(passkey: &str, salt: &str) -> anyhow::Result<[u8; Self::KEY_SIZE_BYTES]> {
let password_bytes = passkey.as_bytes(); let password_bytes = passkey.as_bytes();
let salt_bytes = base64::decode(salt)?; let salt_bytes = base64::engine::general_purpose::STANDARD.decode(salt)?;
let mut full_key: [u8; Self::KEY_SIZE_BYTES] = [0u8; Self::KEY_SIZE_BYTES]; let mut full_key: [u8; Self::KEY_SIZE_BYTES] = [0u8; Self::KEY_SIZE_BYTES];
let deriver = Argon2::new( let deriver = Argon2::new(
argon2::Algorithm::Argon2id, argon2::Algorithm::Argon2id,
@ -40,6 +42,14 @@ impl Argon2idAes256 {
) )
.expect("Unable to create Argon2 config.") .expect("Unable to create Argon2 config.")
} }
fn decode_iv(&self) -> anyhow::Result<[u8; Self::IV_LENGTH]> {
let mut iv = [0u8; Self::IV_LENGTH];
base64::engine::general_purpose::STANDARD
.decode_slice_unchecked(&self.iv, &mut iv)
.context("decoding iv")?;
Ok(iv)
}
} }
impl EntryEncryptor for Argon2idAes256 { impl EntryEncryptor for Argon2idAes256 {
@ -50,8 +60,8 @@ impl EntryEncryptor for Argon2idAes256 {
rng.fill(&mut salt); rng.fill(&mut salt);
rng.fill(&mut iv); rng.fill(&mut iv);
Argon2idAes256 { Argon2idAes256 {
iv: base64::encode(iv), iv: base64::engine::general_purpose::STANDARD.encode(iv),
salt: base64::encode(salt), salt: base64::engine::general_purpose::STANDARD.encode(salt),
} }
} }
@ -65,11 +75,11 @@ impl EntryEncryptor for Argon2idAes256 {
debug!("key derivation took: {:?}", start.elapsed()); debug!("key derivation took: {:?}", start.elapsed());
let start = std::time::Instant::now(); let start = std::time::Instant::now();
let mut iv = [0u8; Self::IV_LENGTH]; let iv = self.decode_iv()?;
base64::decode_config_slice(&self.iv, base64::STANDARD, &mut iv)?; let cipher =
let cipher = cbc::Encryptor::<Aes256>::new_from_slices(&key, &iv)?; cbc::Encryptor::<Aes256>::new_from_slices(&key, &iv).context("creating cipher")?;
let ciphertext = cipher.encrypt_padded_vec_mut::<Pkcs7>(&plaintext); let ciphertext = cipher.encrypt_padded_vec_mut::<Pkcs7>(&plaintext);
let encoded = base64::encode(ciphertext); let encoded = base64::engine::general_purpose::STANDARD.encode(ciphertext);
debug!("encryption took: {:?}", start.elapsed()); debug!("encryption took: {:?}", start.elapsed());
Ok(encoded.as_bytes().to_vec()) Ok(encoded.as_bytes().to_vec())
} }
@ -84,10 +94,10 @@ impl EntryEncryptor for Argon2idAes256 {
debug!("key derivation took: {:?}", start.elapsed()); debug!("key derivation took: {:?}", start.elapsed());
let start = std::time::Instant::now(); let start = std::time::Instant::now();
let mut iv = [0u8; Self::IV_LENGTH]; let iv = self.decode_iv()?;
base64::decode_config_slice(&self.iv, base64::STANDARD, &mut iv)?; let cipher =
let cipher = cbc::Decryptor::<Aes256>::new_from_slices(&key, &iv)?; cbc::Decryptor::<Aes256>::new_from_slices(&key, &iv).context("creating cipher")?;
let decoded = base64::decode(ciphertext)?; let decoded = base64::engine::general_purpose::STANDARD.decode(ciphertext)?;
let size: usize = decoded.len() / 16 + (if decoded.len() % 16 == 0 { 0 } else { 1 }); let size: usize = decoded.len() / 16 + (if decoded.len() % 16 == 0 { 0 } else { 1 });
let mut buffer = vec![0xffu8; 16 * size]; let mut buffer = vec![0xffu8; 16 * size];
buffer[..decoded.len()].copy_from_slice(&decoded); buffer[..decoded.len()].copy_from_slice(&decoded);
@ -104,7 +114,7 @@ mod tests {
#[test] #[test]
fn test_encryption_key() { fn test_encryption_key() {
assert_eq!( assert_eq!(
base64::encode( base64::engine::general_purpose::STANDARD.encode(
Argon2idAes256::get_encryption_key("password", "GMhL0N2hqXg=") Argon2idAes256::get_encryption_key("password", "GMhL0N2hqXg=")
.unwrap() .unwrap()
.as_slice() .as_slice()
@ -116,7 +126,7 @@ mod tests {
#[test] #[test]
fn test_encryption_key2() { fn test_encryption_key2() {
assert_eq!( assert_eq!(
base64::encode( base64::engine::general_purpose::STANDARD.encode(
Argon2idAes256::get_encryption_key("password", "wTzTE9A6aN8=") Argon2idAes256::get_encryption_key("password", "wTzTE9A6aN8=")
.unwrap() .unwrap()
.as_slice() .as_slice()

View file

@ -1,6 +1,8 @@
use aes::cipher::block_padding::Pkcs7; use aes::cipher::block_padding::Pkcs7;
use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit}; use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit};
use aes::Aes256; use aes::Aes256;
use anyhow::Context;
use base64::Engine;
use log::*; use log::*;
use sha1::Sha1; use sha1::Sha1;
@ -21,7 +23,7 @@ impl LegacySdaCompatible {
fn get_encryption_key(passkey: &str, salt: &str) -> anyhow::Result<[u8; Self::KEY_SIZE_BYTES]> { fn get_encryption_key(passkey: &str, salt: &str) -> anyhow::Result<[u8; Self::KEY_SIZE_BYTES]> {
let password_bytes = passkey.as_bytes(); let password_bytes = passkey.as_bytes();
let salt_bytes = base64::decode(salt)?; let salt_bytes = base64::engine::general_purpose::STANDARD.decode(salt)?;
let mut full_key: [u8; Self::KEY_SIZE_BYTES] = [0u8; Self::KEY_SIZE_BYTES]; let mut full_key: [u8; Self::KEY_SIZE_BYTES] = [0u8; Self::KEY_SIZE_BYTES];
pbkdf2::pbkdf2_hmac::<Sha1>( pbkdf2::pbkdf2_hmac::<Sha1>(
password_bytes, password_bytes,
@ -31,6 +33,14 @@ impl LegacySdaCompatible {
); );
Ok(full_key) Ok(full_key)
} }
fn decode_iv(&self) -> anyhow::Result<[u8; Self::IV_LENGTH]> {
let mut iv = [0u8; Self::IV_LENGTH];
base64::engine::general_purpose::STANDARD
.decode_slice_unchecked(&self.iv, &mut iv)
.context("decoding iv")?;
Ok(iv)
}
} }
impl EntryEncryptor for LegacySdaCompatible { impl EntryEncryptor for LegacySdaCompatible {
@ -41,8 +51,8 @@ impl EntryEncryptor for LegacySdaCompatible {
rng.fill(&mut salt); rng.fill(&mut salt);
rng.fill(&mut iv); rng.fill(&mut iv);
LegacySdaCompatible { LegacySdaCompatible {
iv: base64::encode(iv), iv: base64::engine::general_purpose::STANDARD.encode(iv),
salt: base64::encode(salt), salt: base64::engine::general_purpose::STANDARD.encode(salt),
} }
} }
@ -56,11 +66,11 @@ impl EntryEncryptor for LegacySdaCompatible {
debug!("key derivation took: {:?}", start.elapsed()); debug!("key derivation took: {:?}", start.elapsed());
let start = std::time::Instant::now(); let start = std::time::Instant::now();
let mut iv = [0u8; Self::IV_LENGTH]; let iv = self.decode_iv()?;
base64::decode_config_slice(&self.iv, base64::STANDARD, &mut iv)?; let cipher =
let cipher = cbc::Encryptor::<Aes256>::new_from_slices(&key, &iv)?; cbc::Encryptor::<Aes256>::new_from_slices(&key, &iv).context("creating cipher")?;
let ciphertext = cipher.encrypt_padded_vec_mut::<Pkcs7>(&plaintext); let ciphertext = cipher.encrypt_padded_vec_mut::<Pkcs7>(&plaintext);
let encoded = base64::encode(ciphertext); let encoded = base64::engine::general_purpose::STANDARD.encode(ciphertext);
debug!("encryption took: {:?}", start.elapsed()); debug!("encryption took: {:?}", start.elapsed());
Ok(encoded.as_bytes().to_vec()) Ok(encoded.as_bytes().to_vec())
} }
@ -75,10 +85,10 @@ impl EntryEncryptor for LegacySdaCompatible {
debug!("key derivation took: {:?}", start.elapsed()); debug!("key derivation took: {:?}", start.elapsed());
let start = std::time::Instant::now(); let start = std::time::Instant::now();
let mut iv = [0u8; Self::IV_LENGTH]; let iv = self.decode_iv()?;
base64::decode_config_slice(&self.iv, base64::STANDARD, &mut iv)?; let cipher =
let cipher = cbc::Decryptor::<Aes256>::new_from_slices(&key, &iv)?; cbc::Decryptor::<Aes256>::new_from_slices(&key, &iv).context("creating cipher")?;
let decoded = base64::decode(ciphertext)?; let decoded = base64::engine::general_purpose::STANDARD.decode(ciphertext)?;
let size: usize = decoded.len() / 16 + (if decoded.len() % 16 == 0 { 0 } else { 1 }); let size: usize = decoded.len() / 16 + (if decoded.len() % 16 == 0 { 0 } else { 1 });
let mut buffer = vec![0xffu8; 16 * size]; let mut buffer = vec![0xffu8; 16 * size];
buffer[..decoded.len()].copy_from_slice(&decoded); buffer[..decoded.len()].copy_from_slice(&decoded);
@ -100,7 +110,8 @@ mod tests {
LegacySdaCompatible::get_encryption_key("password", "GMhL0N2hqXg=") LegacySdaCompatible::get_encryption_key("password", "GMhL0N2hqXg=")
.unwrap() .unwrap()
.as_slice(), .as_slice(),
base64::decode("KtiRa4/OxW83MlB6URf+Z8rAGj7CBY+pDlwD/NuVo6Y=") base64::engine::general_purpose::STANDARD
.decode("KtiRa4/OxW83MlB6URf+Z8rAGj7CBY+pDlwD/NuVo6Y=")
.unwrap() .unwrap()
.as_slice() .as_slice()
); );
@ -109,7 +120,8 @@ mod tests {
LegacySdaCompatible::get_encryption_key("password", "wTzTE9A6aN8=") LegacySdaCompatible::get_encryption_key("password", "wTzTE9A6aN8=")
.unwrap() .unwrap()
.as_slice(), .as_slice(),
base64::decode("Dqpej/3DqEat0roJaHmu3luYgDzRCUmzX94n4fqvWj8=") base64::engine::general_purpose::STANDARD
.decode("Dqpej/3DqEat0roJaHmu3luYgDzRCUmzX94n4fqvWj8=")
.unwrap() .unwrap()
.as_slice() .as_slice()
); );
@ -140,8 +152,8 @@ mod tests {
/// An insecure but reproducible strategy for generating encryption params. /// An insecure but reproducible strategy for generating encryption params.
fn encryption_params()(salt in any::<[u8; LegacySdaCompatible::SALT_LENGTH]>(), iv in any::<[u8; LegacySdaCompatible::IV_LENGTH]>()) -> LegacySdaCompatible { fn encryption_params()(salt in any::<[u8; LegacySdaCompatible::SALT_LENGTH]>(), iv in any::<[u8; LegacySdaCompatible::IV_LENGTH]>()) -> LegacySdaCompatible {
LegacySdaCompatible { LegacySdaCompatible {
salt: base64::encode(salt), salt: base64::engine::general_purpose::STANDARD.encode(salt),
iv: base64::encode(iv), iv: base64::engine::general_purpose::STANDARD.encode(iv),
} }
} }
} }

View file

@ -13,7 +13,7 @@ license = "MIT OR Apache-2.0"
[dependencies] [dependencies]
anyhow = "^1.0" anyhow = "^1.0"
sha1 = "^0.10" sha1 = "^0.10"
base64 = "0.13.0" base64 = "^0.21"
reqwest = { version = "0.11", default-features = false, features = ["blocking", "json", "cookies", "gzip", "rustls-tls", "multipart"] } reqwest = { version = "0.11", default-features = false, features = ["blocking", "json", "cookies", "gzip", "rustls-tls", "multipart"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"

View file

@ -5,6 +5,7 @@ use crate::steamapi::twofactor::TwoFactorClient;
use crate::token::TwoFactorSecret; use crate::token::TwoFactorSecret;
use crate::transport::Transport; use crate::transport::Transport;
use crate::{steamapi::EResult, token::Tokens, SteamGuardAccount}; use crate::{steamapi::EResult, token::Tokens, SteamGuardAccount};
use base64::Engine;
use log::*; use log::*;
use thiserror::Error; use thiserror::Error;
@ -64,9 +65,13 @@ where
uri: resp.take_uri().into(), uri: resp.take_uri().into(),
shared_secret: TwoFactorSecret::from_bytes(resp.take_shared_secret()), shared_secret: TwoFactorSecret::from_bytes(resp.take_shared_secret()),
token_gid: resp.take_token_gid(), token_gid: resp.take_token_gid(),
identity_secret: base64::encode(resp.take_identity_secret()).into(), identity_secret: base64::engine::general_purpose::STANDARD
.encode(resp.take_identity_secret())
.into(),
device_id: self.device_id.clone(), device_id: self.device_id.clone(),
secret_1: base64::encode(resp.take_secret_1()).into(), secret_1: base64::engine::general_purpose::STANDARD
.encode(resp.take_secret_1())
.into(),
tokens: Some(self.tokens.clone()), tokens: Some(self.tokens.clone()),
}; };
let success = AccountLinkSuccess { let success = AccountLinkSuccess {

View file

@ -1,5 +1,6 @@
use std::borrow::Cow; use std::borrow::Cow;
use base64::Engine;
use hmac::{Hmac, Mac}; use hmac::{Hmac, Mac};
use log::*; use log::*;
use reqwest::{ use reqwest::{
@ -403,13 +404,15 @@ fn generate_confirmation_hash_for_time(
tag: &str, tag: &str,
identity_secret: impl AsRef<[u8]>, identity_secret: impl AsRef<[u8]>,
) -> String { ) -> String {
let decode: &[u8] = &base64::decode(identity_secret).unwrap(); let decode: &[u8] = &base64::engine::general_purpose::STANDARD
.decode(identity_secret)
.unwrap();
let mut mac = Hmac::<Sha1>::new_from_slice(decode).unwrap(); let mut mac = Hmac::<Sha1>::new_from_slice(decode).unwrap();
mac.update(&build_time_bytes(time)); mac.update(&build_time_bytes(time));
mac.update(tag.as_bytes()); mac.update(tag.as_bytes());
let result = mac.finalize(); let result = mac.finalize();
let hash = result.into_bytes(); let hash = result.into_bytes();
base64::encode(hash) base64::engine::general_purpose::STANDARD.encode(hash)
} }
#[cfg(test)] #[cfg(test)]

View file

@ -24,6 +24,7 @@ impl Zeroize for Ip_addr {
#[cfg(test)] #[cfg(test)]
mod parse_tests { mod parse_tests {
use base64::Engine;
use protobuf::Message; use protobuf::Message;
use super::steammessages_auth_steamclient::CAuthentication_GetPasswordRSAPublicKey_Request; use super::steammessages_auth_steamclient::CAuthentication_GetPasswordRSAPublicKey_Request;
@ -34,7 +35,7 @@ mod parse_tests {
req.set_account_name("hydrastar2".to_owned()); req.set_account_name("hydrastar2".to_owned());
let bytes = req.write_to_bytes().unwrap(); let bytes = req.write_to_bytes().unwrap();
let s = base64::encode_config(bytes, base64::URL_SAFE); let s = base64::engine::general_purpose::URL_SAFE.encode(bytes);
assert_eq!(s, "CgpoeWRyYXN0YXIy"); assert_eq!(s, "CgpoeWRyYXN0YXIy");
} }
} }

View file

@ -1,3 +1,4 @@
use base64::Engine;
use hmac::{Hmac, Mac}; use hmac::{Hmac, Mac};
use secrecy::{ExposeSecret, Secret, SecretString}; use secrecy::{ExposeSecret, Secret, SecretString};
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
@ -25,7 +26,10 @@ impl TwoFactorSecret {
pub fn parse_shared_secret(secret: String) -> anyhow::Result<Self> { pub fn parse_shared_secret(secret: String) -> anyhow::Result<Self> {
ensure!(!secret.is_empty(), "unable to parse empty shared secret"); ensure!(!secret.is_empty(), "unable to parse empty shared secret");
let result: [u8; 20] = base64::decode(secret)?.try_into().unwrap(); let result: [u8; 20] = base64::engine::general_purpose::STANDARD
.decode(secret)?
.try_into()
.unwrap();
Ok(Self(result.into())) Ok(Self(result.into()))
} }
@ -67,7 +71,11 @@ impl Serialize for TwoFactorSecret {
where where
S: Serializer, S: Serializer,
{ {
serializer.serialize_str(base64::encode(self.0.expose_secret()).as_str()) serializer.serialize_str(
base64::engine::general_purpose::STANDARD
.encode(self.0.expose_secret())
.as_str(),
)
} }
} }
@ -152,7 +160,7 @@ fn decode_jwt(jwt: impl AsRef<str>) -> anyhow::Result<SteamJwtData> {
ensure!(parts.len() == 3, "Invalid JWT"); ensure!(parts.len() == 3, "Invalid JWT");
let data = parts[1]; let data = parts[1];
let bytes = base64::decode_config(data, base64::URL_SAFE)?; let bytes = base64::engine::general_purpose::URL_SAFE.decode(data)?;
let json = String::from_utf8(bytes)?; let json = String::from_utf8(bytes)?;
let jwt_data: SteamJwtData = serde_json::from_str(&json)?; let jwt_data: SteamJwtData = serde_json::from_str(&json)?;
Ok(jwt_data) Ok(jwt_data)

View file

@ -43,7 +43,10 @@ impl Transport for WebApiTransport {
let mut req = self.client.request(Req::method(), &url); let mut req = self.client.request(Req::method(), &url);
req = if Req::method() == reqwest::Method::GET { req = if Req::method() == reqwest::Method::GET {
let encoded = encode_msg(apireq.request_data(), base64::URL_SAFE)?; let encoded = encode_msg(
apireq.request_data(),
base64::engine::general_purpose::URL_SAFE,
)?;
let mut params = vec![("input_protobuf_encoded", encoded.as_str())]; let mut params = vec![("input_protobuf_encoded", encoded.as_str())];
if let Some(access_token) = apireq.access_token() { if let Some(access_token) = apireq.access_token() {
params.push(("access_token", access_token.expose_secret())); params.push(("access_token", access_token.expose_secret()));
@ -53,7 +56,10 @@ impl Transport for WebApiTransport {
if let Some(access_token) = apireq.access_token() { if let Some(access_token) = apireq.access_token() {
req = req.query(&[("access_token", access_token)]); req = req.query(&[("access_token", access_token)]);
} }
let encoded = encode_msg(apireq.request_data(), base64::STANDARD)?; let encoded = encode_msg(
apireq.request_data(),
base64::engine::general_purpose::STANDARD,
)?;
let form = Form::new().text("input_protobuf_encoded", encoded); let form = Form::new().text("input_protobuf_encoded", encoded);
req.multipart(form) req.multipart(form)
}; };
@ -119,9 +125,9 @@ impl Transport for WebApiTransport {
} }
} }
fn encode_msg<T: MessageFull>(msg: &T, config: base64::Config) -> anyhow::Result<String> { fn encode_msg<T: MessageFull>(msg: &T, engine: impl base64::Engine) -> anyhow::Result<String> {
let bytes = msg.write_to_bytes()?; let bytes = msg.write_to_bytes()?;
let b64 = base64::encode_config(bytes, config); let b64 = engine.encode(bytes);
Ok(b64) Ok(b64)
} }
@ -138,12 +144,13 @@ mod tests {
}; };
use super::*; use super::*;
use base64::{engine::general_purpose::STANDARD, Engine};
#[test] #[test]
fn test_parse_poll_response() { fn test_parse_poll_response() {
let sample = b"GuUDZXlBaWRIbHdJam9nSWtwWFZDSXNJQ0poYkdjaU9pQWlSV1JFVTBFaUlIMC5leUFpYVhOeklqb2dJbk4wWldGdElpd2dJbk4xWWlJNklDSTNOalUyTVRFNU9URTFOVGN3TmpnNU1pSXNJQ0poZFdRaU9pQmJJQ0ozWldJaUxDQWljbVZ1WlhjaUxDQWlaR1Z5YVhabElpQmRMQ0FpWlhod0lqb2dNVGN3TlRBeE1UazFOU3dnSW01aVppSTZJREUyTnpnME5qUTRNemNzSUNKcFlYUWlPaUF4TmpnM01UQTBPRE0zTENBaWFuUnBJam9nSWpFNFF6VmZNakpDTTBZME16RmZRMFJHTmtFaUxDQWliMkYwSWpvZ01UWTROekV3TkRnek55d2dJbkJsY2lJNklERXNJQ0pwY0Y5emRXSnFaV04wSWpvZ0lqWTVMakV5TUM0eE16WXVNVEkwSWl3Z0ltbHdYMk52Ym1acGNtMWxjaUk2SUNJMk9TNHhNakF1TVRNMkxqRXlOQ0lnZlEuR3A1VFBqOXBHUWJ4SXpXREROQ1NQOU9rS1lTZXduV0JFOEUtY1ZxalFxcVQ1M0FzRTRya213OER5TThoVXJ4T0VQQ1dDWHdyYkRVcmgxOTlSempQRHci/gNleUFpZEhsd0lqb2dJa3BYVkNJc0lDSmhiR2NpT2lBaVJXUkVVMEVpSUgwLmV5QWlhWE56SWpvZ0luSTZNVGhETlY4eU1rSXpSalF6TVY5RFJFWTJRU0lzSUNKemRXSWlPaUFpTnpZMU5qRXhPVGt4TlRVM01EWTRPVElpTENBaVlYVmtJam9nV3lBaWQyVmlJaUJkTENBaVpYaHdJam9nTVRZNE56RTVNamM0T0N3Z0ltNWlaaUk2SURFMk56ZzBOalE0TXpjc0lDSnBZWFFpT2lBeE5qZzNNVEEwT0RNM0xDQWlhblJwSWpvZ0lqRXlSREZmTWpKQ00wVTROekZmT1RaRk5EQWlMQ0FpYjJGMElqb2dNVFk0TnpFd05EZ3pOeXdnSW5KMFgyVjRjQ0k2SURFM01EVXdNVEU1TlRVc0lDSndaWElpT2lBd0xDQWlhWEJmYzNWaWFtVmpkQ0k2SUNJMk9TNHhNakF1TVRNMkxqRXlOQ0lzSUNKcGNGOWpiMjVtYVhKdFpYSWlPaUFpTmprdU1USXdMakV6Tmk0eE1qUWlJSDAuMVNnUEotSVZuWEp6Nk9nSW1udUdOQ0hMbEJTcGdvc0Z0UkxoOV9iVVBHQ1RaMmFtRWY2ZTZVYkJzVWZ3bnlYbEdFdG5LSHhPemhibTdLNzBwVFhEQ0EoADIKaHlkcmFzdGFyMg=="; let sample = b"GuUDZXlBaWRIbHdJam9nSWtwWFZDSXNJQ0poYkdjaU9pQWlSV1JFVTBFaUlIMC5leUFpYVhOeklqb2dJbk4wWldGdElpd2dJbk4xWWlJNklDSTNOalUyTVRFNU9URTFOVGN3TmpnNU1pSXNJQ0poZFdRaU9pQmJJQ0ozWldJaUxDQWljbVZ1WlhjaUxDQWlaR1Z5YVhabElpQmRMQ0FpWlhod0lqb2dNVGN3TlRBeE1UazFOU3dnSW01aVppSTZJREUyTnpnME5qUTRNemNzSUNKcFlYUWlPaUF4TmpnM01UQTBPRE0zTENBaWFuUnBJam9nSWpFNFF6VmZNakpDTTBZME16RmZRMFJHTmtFaUxDQWliMkYwSWpvZ01UWTROekV3TkRnek55d2dJbkJsY2lJNklERXNJQ0pwY0Y5emRXSnFaV04wSWpvZ0lqWTVMakV5TUM0eE16WXVNVEkwSWl3Z0ltbHdYMk52Ym1acGNtMWxjaUk2SUNJMk9TNHhNakF1TVRNMkxqRXlOQ0lnZlEuR3A1VFBqOXBHUWJ4SXpXREROQ1NQOU9rS1lTZXduV0JFOEUtY1ZxalFxcVQ1M0FzRTRya213OER5TThoVXJ4T0VQQ1dDWHdyYkRVcmgxOTlSempQRHci/gNleUFpZEhsd0lqb2dJa3BYVkNJc0lDSmhiR2NpT2lBaVJXUkVVMEVpSUgwLmV5QWlhWE56SWpvZ0luSTZNVGhETlY4eU1rSXpSalF6TVY5RFJFWTJRU0lzSUNKemRXSWlPaUFpTnpZMU5qRXhPVGt4TlRVM01EWTRPVElpTENBaVlYVmtJam9nV3lBaWQyVmlJaUJkTENBaVpYaHdJam9nTVRZNE56RTVNamM0T0N3Z0ltNWlaaUk2SURFMk56ZzBOalE0TXpjc0lDSnBZWFFpT2lBeE5qZzNNVEEwT0RNM0xDQWlhblJwSWpvZ0lqRXlSREZmTWpKQ00wVTROekZmT1RaRk5EQWlMQ0FpYjJGMElqb2dNVFk0TnpFd05EZ3pOeXdnSW5KMFgyVjRjQ0k2SURFM01EVXdNVEU1TlRVc0lDSndaWElpT2lBd0xDQWlhWEJmYzNWaWFtVmpkQ0k2SUNJMk9TNHhNakF1TVRNMkxqRXlOQ0lzSUNKcGNGOWpiMjVtYVhKdFpYSWlPaUFpTmprdU1USXdMakV6Tmk0eE1qUWlJSDAuMVNnUEotSVZuWEp6Nk9nSW1udUdOQ0hMbEJTcGdvc0Z0UkxoOV9iVVBHQ1RaMmFtRWY2ZTZVYkJzVWZ3bnlYbEdFdG5LSHhPemhibTdLNzBwVFhEQ0EoADIKaHlkcmFzdGFyMg==";
let bytes = base64::decode_config(sample, base64::STANDARD).unwrap(); let bytes = STANDARD.decode(sample).unwrap();
let resp: CAuthentication_PollAuthSessionStatus_Response = decode_msg(&bytes).unwrap(); let resp: CAuthentication_PollAuthSessionStatus_Response = decode_msg(&bytes).unwrap();
@ -154,7 +161,7 @@ mod tests {
fn parse_get_public_rsa_response() { fn parse_get_public_rsa_response() {
let sample = b"CoAEYjYyMGI1ZWNhMWIxMjgyYjkxYzZkZmZkYWFhOWI0ODI0YjlhNmRiYmEyZDVmYjc0ODcxNDczZDc1MDYxNGEzNWM4ODQ3NDYzZTEyNjAwNTJmNzZlNTYxMDM5ODdlN2U3NGJkMWZjZGRjYWJhMDVmZGM5OTBjMWIyNmQ2ZDg5MGM2MTEzZmRkNTZmMmQ1YmZjNzU4ODhlMzZhNTM2NjM3N2IzZTE3ZTJiZWM5MjhlNGY4MmE1YzY0NGYxZTZlMTk3NzZkNjIzMDIxYjhmYTA0MGRjNWE5YjY0M2I0N2I5YmVhMjM2YmEyZjM4ODVjM2ZlNWVhNjMzZThlNjJjNGE1YTY4NjNmMzNiMzdlMTQ4M2MwZTUzZTg4ODIzMGFkNTVjNzg5ZmU4Y2NkMjVjNzdiMTkxOTg0ZThjN2JmNWYzNzY2MjI0OGI1NWVmOWM1OGY3NDM5YjA4ZjNhNWJiNzljNTc5ZDE5M2I3NzhmMzFiY2IwYTA3MmVhZWYxOGEyYjljZDY2M2VmYmY2YmRiZDU3MGEyMTNiOTIxNTc4ODk0MjJkMDY3ODFiNTVkY2VjYjQ4NjA4MjUyMmUzZWQyOWM4MjExYzQ5N2Q1YjNhYTk2OGM2MDY1YWFhZTNhNGVmYzZiMGJjNDYyMzMxNmVmYTUxN2JjNzRiZDYzODcxMWU4ZWYSBjAxMDAwMRiQn6Ly3wk="; let sample = b"CoAEYjYyMGI1ZWNhMWIxMjgyYjkxYzZkZmZkYWFhOWI0ODI0YjlhNmRiYmEyZDVmYjc0ODcxNDczZDc1MDYxNGEzNWM4ODQ3NDYzZTEyNjAwNTJmNzZlNTYxMDM5ODdlN2U3NGJkMWZjZGRjYWJhMDVmZGM5OTBjMWIyNmQ2ZDg5MGM2MTEzZmRkNTZmMmQ1YmZjNzU4ODhlMzZhNTM2NjM3N2IzZTE3ZTJiZWM5MjhlNGY4MmE1YzY0NGYxZTZlMTk3NzZkNjIzMDIxYjhmYTA0MGRjNWE5YjY0M2I0N2I5YmVhMjM2YmEyZjM4ODVjM2ZlNWVhNjMzZThlNjJjNGE1YTY4NjNmMzNiMzdlMTQ4M2MwZTUzZTg4ODIzMGFkNTVjNzg5ZmU4Y2NkMjVjNzdiMTkxOTg0ZThjN2JmNWYzNzY2MjI0OGI1NWVmOWM1OGY3NDM5YjA4ZjNhNWJiNzljNTc5ZDE5M2I3NzhmMzFiY2IwYTA3MmVhZWYxOGEyYjljZDY2M2VmYmY2YmRiZDU3MGEyMTNiOTIxNTc4ODk0MjJkMDY3ODFiNTVkY2VjYjQ4NjA4MjUyMmUzZWQyOWM4MjExYzQ5N2Q1YjNhYTk2OGM2MDY1YWFhZTNhNGVmYzZiMGJjNDYyMzMxNmVmYTUxN2JjNzRiZDYzODcxMWU4ZWYSBjAxMDAwMRiQn6Ly3wk=";
let bytes = base64::decode_config(sample, base64::STANDARD).unwrap(); let bytes = STANDARD.decode(sample).unwrap();
let resp: CAuthentication_GetPasswordRSAPublicKey_Response = decode_msg(&bytes).unwrap(); let resp: CAuthentication_GetPasswordRSAPublicKey_Response = decode_msg(&bytes).unwrap();
@ -165,11 +172,11 @@ mod tests {
fn test_decode_encode_roundtrip() { fn test_decode_encode_roundtrip() {
let sample = b"EgpoeWRyYXN0YXIyGtgCRUxaNTBXdHM2Z0kxWlZaVjl6bzRJNFBEcEhTMGRZR3RSNzJPbytqZkR5QmRBUitrbnBUcUVGcGF4NDd1UVdqdUQ1R2hpRC9JanA2cEtGQzlrdUZDdzBFT0RMSFpINERZUG5hci9IMktOZGoxSFNjWEhyemZjNmk1OWpsRE5OTTI0RVllNUEyUjVSdzBoa2lodU14Z1A4NDJESFUxMkgwNWFyYmdRUWp3NFJmVHh6cDBQQlRjdTk4VUViUjJnak1RajlVK3RsYStPdTN6WTQ5K1BKc0szTkpMTVdxWm4vaFZ1dTR3NFprZGhXNVBqNWphb2Flb3J6MG8zbWIvUXo2M0NlNFdwWmUra1lFYUlSa29oUXBaZkliaW4rTWdQcVpNelg4cW4vNDcyNFp5N05mblpETlVBV3RoTkowTkUxSDVESXZ4N0IwRFJHZVBwdk5FbVdqWEJ3PT0g4MCW2tYBOAFCBk1vYmlsZUocCgpHYWxheHkgUzIyEAMYjPz/////////ASCQBA=="; let sample = b"EgpoeWRyYXN0YXIyGtgCRUxaNTBXdHM2Z0kxWlZaVjl6bzRJNFBEcEhTMGRZR3RSNzJPbytqZkR5QmRBUitrbnBUcUVGcGF4NDd1UVdqdUQ1R2hpRC9JanA2cEtGQzlrdUZDdzBFT0RMSFpINERZUG5hci9IMktOZGoxSFNjWEhyemZjNmk1OWpsRE5OTTI0RVllNUEyUjVSdzBoa2lodU14Z1A4NDJESFUxMkgwNWFyYmdRUWp3NFJmVHh6cDBQQlRjdTk4VUViUjJnak1RajlVK3RsYStPdTN6WTQ5K1BKc0szTkpMTVdxWm4vaFZ1dTR3NFprZGhXNVBqNWphb2Flb3J6MG8zbWIvUXo2M0NlNFdwWmUra1lFYUlSa29oUXBaZkliaW4rTWdQcVpNelg4cW4vNDcyNFp5N05mblpETlVBV3RoTkowTkUxSDVESXZ4N0IwRFJHZVBwdk5FbVdqWEJ3PT0g4MCW2tYBOAFCBk1vYmlsZUocCgpHYWxheHkgUzIyEAMYjPz/////////ASCQBA==";
let bytes = base64::decode_config(sample, base64::STANDARD).unwrap(); let bytes = STANDARD.decode(sample).unwrap();
let decoded: CAuthentication_BeginAuthSessionViaCredentials_Request = let decoded: CAuthentication_BeginAuthSessionViaCredentials_Request =
decode_msg(&bytes).expect("Failed to decode"); decode_msg(&bytes).expect("Failed to decode");
let encoded = encode_msg(&decoded, base64::STANDARD).expect("Failed to encode"); let encoded = encode_msg(&decoded, STANDARD).expect("Failed to encode");
assert_eq!(encoded, String::from_utf8(sample.to_vec()).unwrap()); assert_eq!(encoded, String::from_utf8(sample.to_vec()).unwrap());
} }

View file

@ -17,6 +17,7 @@ use crate::steamapi::authentication::AuthenticationClient;
use crate::steamapi::EResult; use crate::steamapi::EResult;
use crate::token::Tokens; use crate::token::Tokens;
use crate::transport::Transport; use crate::transport::Transport;
use base64::Engine;
use log::*; use log::*;
use rsa::{Pkcs1v15Encrypt, RsaPublicKey}; use rsa::{Pkcs1v15Encrypt, RsaPublicKey};
use std::time::Duration; use std::time::Duration;
@ -275,7 +276,7 @@ fn encrypt_password(
let mut rng = tests::MockStepRng(rand::rngs::mock::StepRng::new(2, 1)); let mut rng = tests::MockStepRng(rand::rngs::mock::StepRng::new(2, 1));
#[cfg(not(test))] #[cfg(not(test))]
let mut rng = rand::rngs::OsRng; let mut rng = rand::rngs::OsRng;
base64::encode( base64::engine::general_purpose::STANDARD.encode(
public_key public_key
.encrypt(&mut rng, Pkcs1v15Encrypt, password.as_ref()) .encrypt(&mut rng, Pkcs1v15Encrypt, password.as_ref())
.unwrap(), .unwrap(),