mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Almost eliminate util module
This commit is contained in:
parent
9378ae5b6f
commit
e688e7e886
9 changed files with 59 additions and 67 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -1335,6 +1335,7 @@ dependencies = [
|
|||
"base64",
|
||||
"block-modes",
|
||||
"dns-sd",
|
||||
"form_urlencoded",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"hmac",
|
||||
|
@ -1363,6 +1364,7 @@ dependencies = [
|
|||
"byteorder",
|
||||
"bytes",
|
||||
"env_logger",
|
||||
"form_urlencoded",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"hmac",
|
||||
|
@ -1640,6 +1642,7 @@ dependencies = [
|
|||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -11,6 +11,7 @@ edition = "2018"
|
|||
aes-ctr = "0.6"
|
||||
base64 = "0.13"
|
||||
block-modes = "0.7"
|
||||
form_urlencoded = "1.0"
|
||||
futures-core = "0.3"
|
||||
futures-util = { version = "0.3", default_features = false }
|
||||
hmac = "0.10"
|
||||
|
|
|
@ -7,7 +7,6 @@ use crate::core::config::{ConnectConfig, VolumeCtrl};
|
|||
use crate::core::mercury::{MercuryError, MercurySender};
|
||||
use crate::core::session::Session;
|
||||
use crate::core::spotify_id::{SpotifyAudioType, SpotifyId, SpotifyIdError};
|
||||
use crate::core::util::url_encode;
|
||||
use crate::core::util::SeqGenerator;
|
||||
use crate::core::version;
|
||||
use crate::playback::mixer::Mixer;
|
||||
|
@ -244,6 +243,10 @@ fn volume_to_mixer(volume: u16, volume_ctrl: &VolumeCtrl) -> u16 {
|
|||
}
|
||||
}
|
||||
|
||||
fn url_encode(bytes: impl AsRef<[u8]>) -> String {
|
||||
form_urlencoded::byte_serialize(bytes.as_ref()).collect()
|
||||
}
|
||||
|
||||
impl Spirc {
|
||||
pub fn new(
|
||||
config: ConnectConfig,
|
||||
|
@ -256,7 +259,7 @@ impl Spirc {
|
|||
let ident = session.device_id().to_owned();
|
||||
|
||||
// Uri updated in response to issue #288
|
||||
debug!("canonical_username: {}", url_encode(&session.username()));
|
||||
debug!("canonical_username: {}", &session.username());
|
||||
let uri = format!("hm://remote/user/{}/", url_encode(&session.username()));
|
||||
|
||||
let subscription = Box::pin(
|
||||
|
|
|
@ -17,6 +17,7 @@ aes = "0.6"
|
|||
base64 = "0.13"
|
||||
byteorder = "1.4"
|
||||
bytes = "1.0"
|
||||
form_urlencoded = "1.0"
|
||||
futures-core = { version = "0.3", default-features = false }
|
||||
futures-util = { version = "0.3", default-features = false, features = ["alloc", "bilock", "unstable", "sink"] }
|
||||
hmac = "0.10"
|
||||
|
@ -25,7 +26,7 @@ http = "0.2"
|
|||
hyper = { version = "0.14", optional = true, features = ["client", "tcp", "http1"] }
|
||||
hyper-proxy = { version = "0.9.1", optional = true, default-features = false }
|
||||
log = "0.4"
|
||||
num-bigint = "0.4"
|
||||
num-bigint = { version = "0.4", features = ["rand"] }
|
||||
num-integer = "0.1"
|
||||
num-traits = "0.2"
|
||||
once_cell = "1.5.2"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
|
||||
use hmac::{Hmac, Mac, NewMac};
|
||||
use protobuf::{self, Message};
|
||||
use rand::thread_rng;
|
||||
use rand::{thread_rng, RngCore};
|
||||
use sha1::Sha1;
|
||||
use std::io;
|
||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||
|
@ -11,7 +11,6 @@ use super::codec::ApCodec;
|
|||
use crate::diffie_hellman::DhLocalKeys;
|
||||
use crate::protocol;
|
||||
use crate::protocol::keyexchange::{APResponseMessage, ClientHello, ClientResponsePlaintext};
|
||||
use crate::util;
|
||||
|
||||
pub async fn handshake<T: AsyncRead + AsyncWrite + Unpin>(
|
||||
mut connection: T,
|
||||
|
@ -40,6 +39,9 @@ async fn client_hello<T>(connection: &mut T, gc: Vec<u8>) -> io::Result<Vec<u8>>
|
|||
where
|
||||
T: AsyncWrite + Unpin,
|
||||
{
|
||||
let mut client_nonce = vec![0; 0x10];
|
||||
thread_rng().fill_bytes(&mut client_nonce);
|
||||
|
||||
let mut packet = ClientHello::new();
|
||||
packet
|
||||
.mut_build_info()
|
||||
|
@ -59,7 +61,7 @@ where
|
|||
.mut_login_crypto_hello()
|
||||
.mut_diffie_hellman()
|
||||
.set_server_keys_known(1);
|
||||
packet.set_client_nonce(util::rand_vec(&mut thread_rng(), 0x10));
|
||||
packet.set_client_nonce(client_nonce);
|
||||
packet.set_padding(vec![0x1e]);
|
||||
|
||||
let mut buffer = vec![0, 4];
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use num_bigint::BigUint;
|
||||
use num_bigint::{BigUint, RandBigInt};
|
||||
use num_integer::Integer;
|
||||
use num_traits::{One, Zero};
|
||||
use once_cell::sync::Lazy;
|
||||
use rand::Rng;
|
||||
use rand::{CryptoRng, Rng};
|
||||
|
||||
use crate::util;
|
||||
|
||||
pub static DH_GENERATOR: Lazy<BigUint> = Lazy::new(|| BigUint::from_bytes_be(&[0x02]));
|
||||
pub static DH_PRIME: Lazy<BigUint> = Lazy::new(|| {
|
||||
static DH_GENERATOR: Lazy<BigUint> = Lazy::new(|| BigUint::from_bytes_be(&[0x02]));
|
||||
static DH_PRIME: Lazy<BigUint> = Lazy::new(|| {
|
||||
BigUint::from_bytes_be(&[
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2,
|
||||
0x34, 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67,
|
||||
|
@ -17,17 +17,31 @@ pub static DH_PRIME: Lazy<BigUint> = Lazy::new(|| {
|
|||
])
|
||||
});
|
||||
|
||||
fn powm(base: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint {
|
||||
let mut base = base.clone();
|
||||
let mut exp = exp.clone();
|
||||
let mut result: BigUint = One::one();
|
||||
|
||||
while !exp.is_zero() {
|
||||
if exp.is_odd() {
|
||||
result = (result * &base) % modulus;
|
||||
}
|
||||
exp >>= 1;
|
||||
base = (&base * &base) % modulus;
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub struct DhLocalKeys {
|
||||
private_key: BigUint,
|
||||
public_key: BigUint,
|
||||
}
|
||||
|
||||
impl DhLocalKeys {
|
||||
pub fn random<R: Rng>(rng: &mut R) -> DhLocalKeys {
|
||||
let key_data = util::rand_vec(rng, 95);
|
||||
|
||||
let private_key = BigUint::from_bytes_be(&key_data);
|
||||
let public_key = util::powm(&DH_GENERATOR, &private_key, &DH_PRIME);
|
||||
pub fn random<R: Rng + CryptoRng>(rng: &mut R) -> DhLocalKeys {
|
||||
let private_key = rng.gen_biguint(95 * 8);
|
||||
let public_key = powm(&DH_GENERATOR, &private_key, &DH_PRIME);
|
||||
|
||||
DhLocalKeys {
|
||||
private_key,
|
||||
|
@ -40,7 +54,7 @@ impl DhLocalKeys {
|
|||
}
|
||||
|
||||
pub fn shared_secret(&self, remote_key: &[u8]) -> Vec<u8> {
|
||||
let shared_key = util::powm(
|
||||
let shared_key = powm(
|
||||
&BigUint::from_bytes_be(remote_key),
|
||||
&self.private_key,
|
||||
&DH_PRIME,
|
||||
|
|
|
@ -14,12 +14,14 @@ pub mod cache;
|
|||
pub mod channel;
|
||||
pub mod config;
|
||||
mod connection;
|
||||
#[doc(hidden)]
|
||||
pub mod diffie_hellman;
|
||||
pub mod keymaster;
|
||||
pub mod mercury;
|
||||
mod proxytunnel;
|
||||
pub mod session;
|
||||
pub mod spotify_id;
|
||||
#[doc(hidden)]
|
||||
pub mod util;
|
||||
pub mod version;
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ use bytes::Bytes;
|
|||
use tokio::sync::{mpsc, oneshot};
|
||||
|
||||
use crate::protocol;
|
||||
use crate::util::url_encode;
|
||||
use crate::util::SeqGenerator;
|
||||
|
||||
mod types;
|
||||
|
@ -199,7 +198,7 @@ impl MercuryManager {
|
|||
let header: protocol::mercury::Header = protobuf::parse_from_bytes(&header_data).unwrap();
|
||||
|
||||
let response = MercuryResponse {
|
||||
uri: url_encode(header.get_uri()),
|
||||
uri: header.get_uri().to_string(),
|
||||
status_code: header.get_status_code(),
|
||||
payload: pending.parts,
|
||||
};
|
||||
|
@ -214,8 +213,21 @@ impl MercuryManager {
|
|||
} else if cmd == 0xb5 {
|
||||
self.lock(|inner| {
|
||||
let mut found = false;
|
||||
|
||||
// TODO: This is just a workaround to make utf-8 encoded usernames work.
|
||||
// A better solution would be to use an uri struct and urlencode it directly
|
||||
// before sending while saving the subscription under its unencoded form.
|
||||
let mut uri_split = response.uri.split('/');
|
||||
|
||||
let encoded_uri = std::iter::once(uri_split.next().unwrap().to_string())
|
||||
.chain(uri_split.map(|component| {
|
||||
form_urlencoded::byte_serialize(component.as_bytes()).collect::<String>()
|
||||
}))
|
||||
.collect::<Vec<String>>()
|
||||
.join("/");
|
||||
|
||||
inner.subscriptions.retain(|&(ref prefix, ref sub)| {
|
||||
if response.uri.starts_with(prefix) {
|
||||
if encoded_uri.starts_with(prefix) {
|
||||
found = true;
|
||||
|
||||
// if send fails, remove from list of subs
|
||||
|
|
|
@ -1,50 +1,4 @@
|
|||
use num_bigint::BigUint;
|
||||
use num_integer::Integer;
|
||||
use num_traits::{One, Zero};
|
||||
use rand::Rng;
|
||||
use std::mem;
|
||||
use std::ops::{Mul, Rem, Shr};
|
||||
|
||||
pub fn rand_vec<G: Rng>(rng: &mut G, size: usize) -> Vec<u8> {
|
||||
::std::iter::repeat(())
|
||||
.map(|()| rng.gen())
|
||||
.take(size)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn url_encode(inp: &str) -> String {
|
||||
let mut encoded = String::new();
|
||||
|
||||
for c in inp.as_bytes().iter() {
|
||||
match *c as char {
|
||||
'A'..='Z' | 'a'..='z' | '0'..='9' | '-' | '_' | '.' | '~' | ':' | '/' => {
|
||||
encoded.push(*c as char)
|
||||
}
|
||||
c => encoded.push_str(format!("%{:02X}", c as u32).as_str()),
|
||||
};
|
||||
}
|
||||
|
||||
encoded
|
||||
}
|
||||
|
||||
pub fn powm(base: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint {
|
||||
let mut base = base.clone();
|
||||
let mut exp = exp.clone();
|
||||
let mut result: BigUint = One::one();
|
||||
|
||||
while !exp.is_zero() {
|
||||
if exp.is_odd() {
|
||||
result = result.mul(&base).rem(modulus);
|
||||
}
|
||||
exp = exp.shr(1);
|
||||
base = (&base).mul(&base).rem(modulus);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub trait ReadSeek: ::std::io::Read + ::std::io::Seek {}
|
||||
impl<T: ::std::io::Read + ::std::io::Seek> ReadSeek for T {}
|
||||
|
||||
pub trait Seq {
|
||||
fn next(&self) -> Self;
|
||||
|
|
Loading…
Reference in a new issue