1
0
Fork 0
mirror of https://github.com/librespot-org/librespot.git synced 2025-10-04 18:29:45 +02:00

Get access token via login5 (#1344)

* core: Obtain spclient access token using login5 instead of keymaster (Fixes #1179)
* core: move solving hashcash into util
* login5: add login for mobile

---------

Co-authored-by: Nick Steel <nick@nsteel.co.uk>
This commit is contained in:
Felix Prillwitz 2024-10-19 20:27:26 +02:00 committed by GitHub
parent d8e84238ab
commit 4580dab73f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 362 additions and 55 deletions

View file

@ -1,12 +1,16 @@
use crate::Error;
use byteorder::{BigEndian, ByteOrder};
use futures_core::ready;
use futures_util::{future, FutureExt, Sink, SinkExt};
use hmac::digest::Digest;
use sha1::Sha1;
use std::time::{Duration, Instant};
use std::{
future::Future,
mem,
pin::Pin,
task::{Context, Poll},
};
use futures_core::ready;
use futures_util::{future, FutureExt, Sink, SinkExt};
use tokio::{task::JoinHandle, time::timeout};
/// Returns a future that will flush the sink, even if flushing is temporarily completed.
@ -120,3 +124,44 @@ impl<T: Seq> SeqGenerator<T> {
mem::replace(&mut self.0, value)
}
}
pub fn solve_hash_cash(
ctx: &[u8],
prefix: &[u8],
length: i32,
dst: &mut [u8],
) -> Result<Duration, Error> {
// after a certain number of seconds, the challenge expires
const TIMEOUT: u64 = 5; // seconds
let now = Instant::now();
let md = Sha1::digest(ctx);
let mut counter: i64 = 0;
let target: i64 = BigEndian::read_i64(&md[12..20]);
let suffix = loop {
if now.elapsed().as_secs() >= TIMEOUT {
return Err(Error::deadline_exceeded(format!(
"{TIMEOUT} seconds expired"
)));
}
let suffix = [(target + counter).to_be_bytes(), counter.to_be_bytes()].concat();
let mut hasher = Sha1::new();
hasher.update(prefix);
hasher.update(&suffix);
let md = hasher.finalize();
if BigEndian::read_i64(&md[12..20]).trailing_zeros() >= (length as u32) {
break suffix;
}
counter += 1;
};
dst.copy_from_slice(&suffix);
Ok(now.elapsed())
}