diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..74244fd --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[registries] +spbr = { index = "sparse+https://crates.spbr.net/api/v1/crates/" } diff --git a/Cargo.toml b/Cargo.toml index 527f400..7009f57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "spbr-common" version = "0.1.0" edition = "2024" +publish = ["spbr"] [dependencies] aes = "0.9.1" @@ -17,3 +18,9 @@ rand = "0.10.2" [features] crypto = ["dep:base64", "dep:hmac", "dep:md-5", "dep:hybrid-array"] +default = ["crypto"] + +[[bin]] +name = "encsign-keygen" +path = "utilities/encsign_keygen.rs" +required-features = ["crypto"] diff --git a/src/crypto/encsign.rs b/src/crypto/encsign.rs index bd53bcc..f3dc64a 100644 --- a/src/crypto/encsign.rs +++ b/src/crypto/encsign.rs @@ -1,15 +1,20 @@ +use std::{fmt::Display, str::FromStr}; + use aes::{ Aes128, - cipher::{Block, BlockCipherDecrypt, BlockCipherEncrypt, BlockSizeUser, block}, + cipher::{Block, BlockCipherDecrypt, BlockCipherEncrypt}, }; -use bytemuck::{Pod, PodCastError, Zeroable}; +use base64::{Engine, engine::general_purpose::STANDARD}; +use bytemuck::PodCastError; use hmac::{Hmac, KeyInit, Mac}; use hybrid_array::Array; use md5::Md5; use rand::random; use thiserror::Error; -use crate::crypto::encsign::Error::{BlockCastError, InvalidSignature, MessageTooSmall}; +use crate::crypto::encsign::Error::{ + BlockCastError, InvalidKeyComponentSize, InvalidSignature, MessageTooSmall, NoSeperator, +}; // first is aes second is hmac pub struct EncSignKeypair(pub [u8; 0x10], pub [u8; 0x40]); @@ -17,11 +22,53 @@ pub struct EncSignKeypair(pub [u8; 0x10], pub [u8; 0x40]); type HmacMd5 = Hmac; impl EncSignKeypair { - fn new_random() -> Self { + pub fn new_random() -> Self { Self(random(), random()) } } +#[derive(Error, Debug, PartialEq)] +pub enum Error { + #[error("an error occurred whilest casting data to blocks: {0}")] + BlockCastError(PodCastError), + #[error("invalid signature")] + InvalidSignature, + #[error("message too small, it must be at least 0x10 in size")] + MessageTooSmall, + #[error("input contains no seperator")] + NoSeperator, + #[error("base64 decoding error")] + Base64(#[from] base64::DecodeError), + #[error("invalid key component size")] + InvalidKeyComponentSize, +} + +pub type Result = std::result::Result; + +impl Display for EncSignKeypair { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}.{}", + STANDARD.encode(&self.0), + STANDARD.encode(&self.1) + ) + } +} + +impl FromStr for EncSignKeypair { + type Err = Error; + fn from_str(s: &str) -> Result { + let (aes, hmac) = s.split_once('.').ok_or(NoSeperator)?; + let aes = STANDARD.decode(aes)?; + let hmac = STANDARD.decode(hmac)?; + Ok(Self( + aes.try_into().map_err(|_| InvalidKeyComponentSize)?, + hmac.try_into().map_err(|_| InvalidKeyComponentSize)?, + )) + } +} + pub fn blob_calc_signature(data: &[u8], key: &[u8; 0x40]) -> [u8; 0x10] { let mut hmac = HmacMd5::new(Array::cast_from_core(key)); @@ -46,18 +93,6 @@ pub fn decrypt_and_gen_signature_blocks<'a, 'b>( blob_calc_signature(bytemuck::cast_slice(&data), &pair.1) } -#[derive(Error, Debug, PartialEq)] -pub enum Error { - #[error("an error occurred whilest casting data to blocks: {0}")] - BlockCastError(PodCastError), - #[error("invalid signature")] - InvalidSignature, - #[error("message too small, it must be at least 0x10 in size")] - MessageTooSmall, -} - -pub type Result = std::result::Result; - pub fn encrypt_and_sign(mut data: Vec, keypair: &EncSignKeypair) -> Result> { let block_data = bytemuck::try_cast_slice_mut(&mut data).map_err(BlockCastError)?; let signature = encrypt_and_gen_signature_blocks(block_data, keypair); diff --git a/utilities/encsign_keygen.rs b/utilities/encsign_keygen.rs new file mode 100644 index 0000000..5ea991a --- /dev/null +++ b/utilities/encsign_keygen.rs @@ -0,0 +1,6 @@ +fn main() { + println!( + "{}", + spbr_common::crypto::encsign::EncSignKeypair::new_random() + ); +}