use aes::Aes128;
use ecb::cipher::{BlockEncryptMut, KeyInit, block_padding::Pkcs7};
use md5::{Digest, Md5};
const EAPI_KEY: &[u8; 16] = b"e82ckenh8dichen8";
const SEP: &str = "-36cd479b6b5-";
fn hex(bytes: &[u8], upper: bool) -> String {
bytes
.iter()
.map(|b| {
if upper {
format!("{b:02X}")
} else {
format!("{b:02x}")
}
})
.collect()
}
pub fn eapi_params(url: &str, payload: &str) -> String {
let path = url
.split_once("://")
.map_or(url, |(_, rest)| rest.find('/').map_or("/", |i| &rest[i..]));
let path = path.split(['?', '#']).next().unwrap_or(path);
let path = path.replacen("/eapi/", "/api/", 1);
let digest = hex(
&Md5::digest(format!("nobody{path}use{payload}md5forencrypt")),
false,
);
let text = format!("{path}{SEP}{payload}{SEP}{digest}");
let cipher = ecb::Encryptor::<Aes128>::new(EAPI_KEY.into());
hex(
&cipher.encrypt_padded_vec_mut::<Pkcs7>(text.as_bytes()),
true,
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn matches_python() {
let payload = r#"{"ids": [1481929839], "level": "lossless", "encodeType": "flac", "header": "{\"os\": \"pc\"}"}"#;
let got = eapi_params(
"https://interface3.music.163.com/eapi/song/enhance/player/url/v1",
payload,
);
assert_eq!(
got,
"FA90B329E9614F79E79598F37DC2EDB487F00D1BC4C9B24CD57E6C318B9073569338432CD7D98D1A3626E997A2C53121BFE81D9222A8D04359B4F8FFADE611200BB82A0EA8B7D5803EA22FC6D16FEC2103120DD979E9F233DBA3BF88DAFFDDDBAE669ADE4C0033AAA3F58BF0C6CB38546FA4810885F0EB19CE90ED6CAAD8CD5DC8C0A76BF64464937416FF12D9932A1D385E4B95F21F5A0EF2C6BC7D4FB3A728C00F9EA146422AF407CE03B3948E4C469EEF83350DAFEAF61AEB9849F7CE9BF3"
);
}
#[test]
fn hex_case() {
assert_eq!(hex(&[0x0a, 0xff], true), "0AFF");
assert_eq!(hex(&[0x0a, 0xff], false), "0aff");
}
}