qmc: remove use of anyhow

This commit is contained in:
鲁树人
2025-05-04 21:00:27 +09:00
parent a1a6c4b1e8
commit 190ceb1903
8 changed files with 38 additions and 23 deletions

View File

@@ -4,9 +4,8 @@ version = "0.1.9"
edition = "2021"
[dependencies]
anyhow = "1.0.86"
byteorder = "1.5.0"
itertools = "0.13.0"
itertools = "0.14"
lazy_static = "1.5.0"
tc_tea = { version = "0.2.1", default-features = false }
thiserror = "2.0.7"

View File

@@ -1,4 +1,3 @@
use anyhow::Result;
use itertools::Itertools;
use lazy_static::lazy_static;
use std::ops::Mul;
@@ -27,6 +26,8 @@ pub enum EKeyDecryptError {
FailDecryptV1(TcTeaError),
#[error("Error when decrypting ekey v2: {0}")]
FailDecryptV2(TcTeaError),
#[error("Failed to decode b64 content: {0}")]
Base64Decode(#[from] base64::DecodeError),
}
fn make_simple_key<const N: usize>() -> [u8; N] {
@@ -42,7 +43,7 @@ fn make_simple_key<const N: usize>() -> [u8; N] {
result
}
pub fn decrypt_v1(ekey: &[u8]) -> Result<Vec<u8>> {
pub fn decrypt_v1(ekey: &[u8]) -> Result<Vec<u8>, EKeyDecryptError> {
if ekey.len() < 12 {
Err(EKeyDecryptError::EKeyTooShort)?;
}
@@ -61,7 +62,7 @@ pub fn decrypt_v1(ekey: &[u8]) -> Result<Vec<u8>> {
Ok([header, &plaintext].concat())
}
pub fn decrypt_v2(ekey: &[u8]) -> Result<Vec<u8>> {
pub fn decrypt_v2(ekey: &[u8]) -> Result<Vec<u8>, EKeyDecryptError> {
let ekey = base64::decode(ekey)?;
let ekey = tc_tea::decrypt(ekey, EKEY_V2_KEY1).map_err(EKeyDecryptError::FailDecryptV2)?;
let ekey = tc_tea::decrypt(ekey, EKEY_V2_KEY2).map_err(EKeyDecryptError::FailDecryptV2)?;
@@ -70,7 +71,7 @@ pub fn decrypt_v2(ekey: &[u8]) -> Result<Vec<u8>> {
decrypt_v1(&ekey)
}
pub fn decrypt<T: AsRef<[u8]>>(ekey: T) -> Result<Vec<u8>> {
pub fn decrypt<T: AsRef<[u8]>>(ekey: T) -> Result<Vec<u8>, EKeyDecryptError> {
let ekey = ekey.as_ref();
match ekey.strip_prefix(EKEY_V2_PREFIX) {
Some(v2_ekey) => decrypt_v2(v2_ekey),

View File

@@ -26,8 +26,6 @@ pub enum FooterParseError {
PCv2InvalidVersion(u32),
#[error("PCv2/MusicEx: Invalid `MusicEx` size: {0}")]
PCv2MusicExUnsupportedPayloadSize(usize),
#[error("PCv2/MusicEx: Invalid `MusicEx` data: {0}")]
PCv2MusicExInvalidError(anyhow::Error),
#[error("Android/STag: Invalid ID field: {0}")]
STagInvalidId(String),
@@ -45,6 +43,9 @@ pub enum FooterParseError {
#[error("Parse: Failed to parse string '{0}' as integer")]
StringToIntError(String),
#[error("Failed to parse MusicExV1: {0}")]
MusicEx1ParseError(std::io::Error),
}
/// Footer type

View File

@@ -36,7 +36,8 @@ impl Default for MusicExV1 {
}
impl MusicExV1 {
pub fn from_bytes(buffer: &[u8]) -> anyhow::Result<MusicExV1> {
#[allow(clippy::field_reassign_with_default)]
fn from_bytes_inner(buffer: &[u8]) -> Result<MusicExV1, std::io::Error> {
assert_eq!(buffer.len(), 0xC0 - 0x10);
let mut cursor = Cursor::new(&buffer);
@@ -50,11 +51,15 @@ impl MusicExV1 {
Ok(result)
}
pub fn from_bytes(buffer: &[u8]) -> Result<MusicExV1, FooterParseError> {
Self::from_bytes_inner(buffer).map_err(FooterParseError::MusicEx1ParseError)
}
}
pub fn parse_v1(footer: &[u8]) -> Result<Option<Metadata>, FooterParseError> {
let (payload, payload_len) = footer.split_at(footer.len() - 4);
let payload_len = LE::read_u32(&payload_len) as usize;
let payload_len = LE::read_u32(payload_len) as usize;
if payload_len != 0xC0 {
Err(FooterParseError::PCv2MusicExUnsupportedPayloadSize(
payload_len,
@@ -62,8 +67,7 @@ pub fn parse_v1(footer: &[u8]) -> Result<Option<Metadata>, FooterParseError> {
}
let payload = &payload[payload.len() - (payload_len - 0x10)..];
let payload =
MusicExV1::from_bytes(payload).map_err(FooterParseError::PCv2MusicExInvalidError)?;
let payload = MusicExV1::from_bytes(payload)?;
let mid = from_ascii_utf16(&payload.mid);
let media_filename = from_ascii_utf16(&payload.media_filename);

View File

@@ -1,6 +1,5 @@
use crate::v2_map::QMC2Map;
use crate::v2_rc4::cipher::QMC2RC4;
use anyhow::Result;
use thiserror::Error;
pub mod ekey;
@@ -13,6 +12,9 @@ pub mod v2_rc4;
pub enum QmcCryptoError {
#[error("QMC V2/Map Cipher: Key is empty")]
QMCV2MapKeyEmpty,
#[error("EKey: {0}")]
EKeyParseError(#[from] ekey::EKeyDecryptError),
}
#[derive(Debug, PartialEq, Clone)]
@@ -22,7 +24,7 @@ pub enum QMCv2Cipher {
}
impl QMCv2Cipher {
pub fn new<T>(key: T) -> Result<Self>
pub fn new<T>(key: T) -> Result<Self, QmcCryptoError>
where
T: AsRef<[u8]>,
{
@@ -35,7 +37,7 @@ impl QMCv2Cipher {
Ok(cipher)
}
pub fn new_from_ekey<T: AsRef<[u8]>>(ekey_str: T) -> Result<Self> {
pub fn new_from_ekey<T: AsRef<[u8]>>(ekey_str: T) -> Result<Self, QmcCryptoError> {
let key = ekey::decrypt(ekey_str)?;
Self::new(key)
}

View File

@@ -3,7 +3,7 @@ use crate::QmcCryptoError;
const INDEX_OFFSET: usize = 71214;
pub fn key_compress<T: AsRef<[u8]>>(long_key: T) -> anyhow::Result<[u8; V1_KEY_SIZE]> {
pub fn key_compress<T: AsRef<[u8]>>(long_key: T) -> Result<[u8; V1_KEY_SIZE], QmcCryptoError> {
let long_key = long_key.as_ref();
if long_key.is_empty() {
Err(QmcCryptoError::QMCV2MapKeyEmpty)?;

View File

@@ -2,7 +2,7 @@ mod key;
use crate::v1::cipher::{qmc1_transform, V1_KEY_SIZE};
use crate::v2_map::key::key_compress;
use anyhow::Result;
use crate::QmcCryptoError;
#[derive(Debug, PartialEq, Clone)]
pub struct QMC2Map {
@@ -10,7 +10,7 @@ pub struct QMC2Map {
}
impl QMC2Map {
pub fn new<T: AsRef<[u8]>>(key: T) -> Result<Self> {
pub fn new<T: AsRef<[u8]>>(key: T) -> Result<Self, QmcCryptoError> {
let key = key_compress(key)?;
Ok(Self { key })
}