mirror of
https://git.um-react.app/um/lib_um_crypto_rust.git
synced 2026-03-07 20:19:51 +00:00
qmc: remove use of anyhow
This commit is contained in:
18
Cargo.lock
generated
18
Cargo.lock
generated
@@ -316,6 +316,15 @@ dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.76"
|
||||
@@ -577,7 +586,7 @@ version = "0.1.9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byteorder",
|
||||
"itertools",
|
||||
"itertools 0.13.0",
|
||||
"thiserror",
|
||||
"umc_qmc",
|
||||
"umc_utils",
|
||||
@@ -600,7 +609,7 @@ dependencies = [
|
||||
"byteorder",
|
||||
"cipher",
|
||||
"crc",
|
||||
"itertools",
|
||||
"itertools 0.13.0",
|
||||
"thiserror",
|
||||
"umc_utils",
|
||||
]
|
||||
@@ -609,9 +618,8 @@ dependencies = [
|
||||
name = "umc_qmc"
|
||||
version = "0.1.9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byteorder",
|
||||
"itertools",
|
||||
"itertools 0.14.0",
|
||||
"lazy_static",
|
||||
"tc_tea",
|
||||
"thiserror",
|
||||
@@ -624,7 +632,7 @@ version = "0.1.9"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"hex",
|
||||
"itertools",
|
||||
"itertools 0.13.0",
|
||||
"miniz_oxide",
|
||||
"thiserror",
|
||||
"umc_qmc",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user