refactor: remove anyhow from kuwo

This commit is contained in:
鲁树人
2025-05-04 21:15:31 +09:00
parent 190ceb1903
commit 91f54423a2
4 changed files with 29 additions and 18 deletions

View File

@@ -4,7 +4,6 @@ version = "0.1.9"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
anyhow = "1.0.86"
byteorder = "1.5.0" byteorder = "1.5.0"
itertools = "0.13.0" itertools = "0.13.0"
thiserror = "2.0.7" thiserror = "2.0.7"

View File

@@ -1,6 +1,5 @@
use super::{constants, helper}; use super::{constants, helper};
use crate::KuwoCryptoError; use crate::KuwoCryptoError;
use anyhow::Result;
use itertools::Either; use itertools::Either;
/// Encrypt or Decrypt? /// Encrypt or Decrypt?
@@ -82,13 +81,13 @@ impl KuwoDes {
state state
} }
pub fn transform(&self, data: &mut [u8]) -> Result<()> { pub fn transform(&self, data: &mut [u8]) -> Result<(), KuwoCryptoError> {
if data.len() % 8 != 0 { if data.len() % 8 != 0 {
Err(KuwoCryptoError::InvalidDesDataSize(data.len()))? Err(KuwoCryptoError::InvalidDesDataSize(data.len()))?
} }
for block in data.chunks_exact_mut(8) { for block in data.chunks_exact_mut(8) {
let value = u64::from_le_bytes(block.try_into()?); let value = u64::from_le_bytes(block.try_into().unwrap_or_default());
let value = self.transform_block(value); let value = self.transform_block(value);
block.copy_from_slice(&value.to_le_bytes()); block.copy_from_slice(&value.to_le_bytes());
} }

View File

@@ -1,13 +1,13 @@
use anyhow::Result;
mod constants; mod constants;
mod core; mod core;
mod helper; mod helper;
use core::{KuwoDes, Mode}; use core::{KuwoDes, Mode};
use umc_utils::base64; use umc_utils::base64;
use crate::KuwoCryptoError;
/// Decrypt string content /// Decrypt string content
pub fn decrypt_ksing<T: AsRef<[u8]>>(data: T, key: &[u8; 8]) -> Result<String> { pub fn decrypt_ksing<T: AsRef<[u8]>>(data: T, key: &[u8; 8]) -> Result<String, KuwoCryptoError> {
let mut decoded = base64::decode(data)?; let mut decoded = base64::decode(data)?;
let des = KuwoDes::new(key, Mode::Decrypt); let des = KuwoDes::new(key, Mode::Decrypt);
@@ -20,17 +20,19 @@ pub fn decrypt_ksing<T: AsRef<[u8]>>(data: T, key: &[u8; 8]) -> Result<String> {
Ok(result) Ok(result)
} }
pub fn encrypt_ksing<T: AsRef<[u8]>>(data: T, key: &[u8; 8]) -> Result<String> { pub fn encrypt_ksing<T: AsRef<[u8]>>(data: T, key: &[u8; 8]) -> Result<String, KuwoCryptoError> {
let mut data = Vec::from(data.as_ref()); let mut data = Vec::from(data.as_ref());
let padded_len = ((data.len() + 7) / 8) * 8; let padded_len = data.len() % 8;
data.resize(padded_len, 0u8); if padded_len != 0 {
data.resize(data.len() + (8 - padded_len), 0);
}
let des = KuwoDes::new(key, Mode::Encrypt); let des = KuwoDes::new(key, Mode::Encrypt);
des.transform(&mut data[..])?; des.transform(&mut data[..])?;
Ok(base64::encode(data)) Ok(base64::encode(data))
} }
pub fn decode_ekey<T: AsRef<[u8]>>(data: T, key: &[u8; 8]) -> Result<String> { pub fn decode_ekey<T: AsRef<[u8]>>(data: T, key: &[u8; 8]) -> Result<String, KuwoCryptoError> {
let decoded = decrypt_ksing(data, key)?; let decoded = decrypt_ksing(data, key)?;
Ok(decoded[16..].to_string()) Ok(decoded[16..].to_string())
} }

View File

@@ -1,15 +1,14 @@
use crate::kwm_v1::CipherV1; use crate::kwm_v1::CipherV1;
use anyhow::Result;
use byteorder::{ReadBytesExt, LE}; use byteorder::{ReadBytesExt, LE};
use std::fmt; use std::fmt;
use std::io::{Cursor, Read}; use std::io::{Cursor, Read};
use thiserror::Error; use thiserror::Error;
use umc_qmc::QMCv2Cipher; use umc_utils::base64::DecodeError;
pub mod des; pub mod des;
pub mod kwm_v1; pub mod kwm_v1;
pub use umc_qmc::QMCv2Cipher as CipherV2; pub use umc_qmc::{QMCv2Cipher as CipherV2, QmcCryptoError};
/// Commonly used secret key for Kuwo services. /// Commonly used secret key for Kuwo services.
pub const SECRET_KEY: [u8; 8] = *b"ylzsxkwm"; pub const SECRET_KEY: [u8; 8] = *b"ylzsxkwm";
@@ -30,6 +29,15 @@ pub enum KuwoCryptoError {
#[error("KWM: Unsupported version {0}")] #[error("KWM: Unsupported version {0}")]
UnsupportedVersion(usize), UnsupportedVersion(usize),
#[error("Failed to decode base64: {0}")]
Base64DecodeError(#[from] DecodeError),
#[error("{0}")]
QMCCipherError(#[from] QmcCryptoError),
#[error("Failed to read data: {0}")]
IoError(#[from] std::io::Error),
} }
impl fmt::Display for HeaderMagicBytes { impl fmt::Display for HeaderMagicBytes {
@@ -49,7 +57,10 @@ pub enum Decipher {
} }
impl Decipher { impl Decipher {
pub fn new<T: AsRef<[u8]>>(header: &Header, ekey: Option<T>) -> Result<Decipher> { pub fn new<T: AsRef<[u8]>>(
header: &Header,
ekey: Option<T>,
) -> Result<Decipher, KuwoCryptoError> {
let cipher = match header.version { let cipher = match header.version {
1 => Decipher::V1(CipherV1::new(header.resource_id)), 1 => Decipher::V1(CipherV1::new(header.resource_id)),
2 => match ekey { 2 => match ekey {
@@ -89,7 +100,7 @@ impl Header {
const MAGIC_1: [u8; 16] = *b"yeelion-kuwo-tme"; const MAGIC_1: [u8; 16] = *b"yeelion-kuwo-tme";
const MAGIC_2: [u8; 16] = *b"yeelion-kuwo\0\0\0\0"; const MAGIC_2: [u8; 16] = *b"yeelion-kuwo\0\0\0\0";
pub fn from_bytes<T>(bytes: T) -> Result<Self> pub fn from_bytes<T>(bytes: T) -> Result<Self, KuwoCryptoError>
where where
T: AsRef<[u8]>, T: AsRef<[u8]>,
{ {
@@ -128,10 +139,10 @@ impl Header {
} }
} }
pub struct CipherBoDian(QMCv2Cipher); pub struct CipherBoDian(CipherV2);
impl CipherBoDian { impl CipherBoDian {
pub fn new<T: AsRef<[u8]>>(ekey: T) -> Result<Self> { pub fn new<T: AsRef<[u8]>>(ekey: T) -> Result<Self, KuwoCryptoError> {
let ekey = des::decode_ekey(ekey, &SECRET_KEY)?; let ekey = des::decode_ekey(ekey, &SECRET_KEY)?;
let cipher = CipherV2::new_from_ekey(ekey.as_str())?; let cipher = CipherV2::new_from_ekey(ekey.as_str())?;
Ok(Self(cipher)) Ok(Self(cipher))