Compare commits
6 Commits
15547f237b
...
d989b15582
Author | SHA1 | Date | |
---|---|---|---|
d989b15582 | |||
5de74ba6c3 | |||
7ac92f9341 | |||
6a56cc8433 | |||
f75a3ccb34 | |||
6791dec745 |
@ -29,7 +29,7 @@ impl QMCv2Cipher {
|
|||||||
let key = key.as_ref();
|
let key = key.as_ref();
|
||||||
let cipher = match key.len() {
|
let cipher = match key.len() {
|
||||||
0 => Err(QmcCryptoError::QMCV2MapKeyEmpty)?,
|
0 => Err(QmcCryptoError::QMCV2MapKeyEmpty)?,
|
||||||
..=300 => QMCv2Cipher::MapL(QMC2Map::new(key)?),
|
1..=300 => QMCv2Cipher::MapL(QMC2Map::new(key)?),
|
||||||
_ => QMCv2Cipher::RC4(QMC2RC4::new(key)),
|
_ => QMCv2Cipher::RC4(QMC2RC4::new(key)),
|
||||||
};
|
};
|
||||||
Ok(cipher)
|
Ok(cipher)
|
||||||
|
@ -11,14 +11,14 @@ const RC4_STREAM_CACHE_SIZE: usize = OTHER_SEGMENT_SIZE + 512;
|
|||||||
pub struct QMC2RC4 {
|
pub struct QMC2RC4 {
|
||||||
hash: f64,
|
hash: f64,
|
||||||
key: Box<[u8]>,
|
key: Box<[u8]>,
|
||||||
key_stream: [u8; RC4_STREAM_CACHE_SIZE],
|
key_stream: Box<[u8; RC4_STREAM_CACHE_SIZE]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QMC2RC4 {
|
impl QMC2RC4 {
|
||||||
pub fn new(key: &[u8]) -> Self {
|
pub fn new(key: &[u8]) -> Self {
|
||||||
let mut rc4 = RC4::new(key);
|
let mut rc4 = RC4::new(key);
|
||||||
let mut key_stream = [0u8; RC4_STREAM_CACHE_SIZE];
|
let mut key_stream = Box::new([0u8; RC4_STREAM_CACHE_SIZE]);
|
||||||
rc4.derive(&mut key_stream);
|
rc4.derive(&mut key_stream[..]);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
hash: hash(key),
|
hash: hash(key),
|
||||||
@ -31,8 +31,9 @@ impl QMC2RC4 {
|
|||||||
let n = self.key.len();
|
let n = self.key.len();
|
||||||
|
|
||||||
for (datum, offset) in data.iter_mut().zip(offset..) {
|
for (datum, offset) in data.iter_mut().zip(offset..) {
|
||||||
let idx = get_segment_key(offset as u64, self.key[offset % n], self.hash) as usize;
|
let idx = get_segment_key(offset as u64, self.key[offset % n], self.hash);
|
||||||
*datum ^= self.key[idx % n];
|
let idx = idx % (n as u64);
|
||||||
|
*datum ^= self.key[idx as usize];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,10 +44,11 @@ impl QMC2RC4 {
|
|||||||
let block_offset = offset % OTHER_SEGMENT_SIZE;
|
let block_offset = offset % OTHER_SEGMENT_SIZE;
|
||||||
|
|
||||||
let seed = self.key[id % n];
|
let seed = self.key[id % n];
|
||||||
let skip = get_segment_key(id as u64, seed, self.hash) % 512;
|
let skip = get_segment_key(id as u64, seed, self.hash);
|
||||||
|
let skip = (skip & 0x1FF) as usize;
|
||||||
|
|
||||||
debug_assert!(data.len() <= OTHER_SEGMENT_SIZE - block_offset);
|
debug_assert!(data.len() <= OTHER_SEGMENT_SIZE - block_offset);
|
||||||
let key_stream = self.key_stream.iter().skip(skip as usize + block_offset);
|
let key_stream = self.key_stream.iter().skip(skip + block_offset);
|
||||||
for (datum, &key) in data.iter_mut().zip(key_stream) {
|
for (datum, &key) in data.iter_mut().zip(key_stream) {
|
||||||
*datum ^= key;
|
*datum ^= key;
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,11 @@ impl RC4 {
|
|||||||
self.state[index]
|
self.state[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn derive(&mut self, buffer: &mut [u8]) {
|
pub fn derive<T>(&mut self, buffer: &mut T)
|
||||||
for item in buffer.iter_mut() {
|
where
|
||||||
|
T: AsMut<[u8]> + ?Sized,
|
||||||
|
{
|
||||||
|
for item in buffer.as_mut().iter_mut() {
|
||||||
*item ^= self.generate();
|
*item ^= self.generate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
pub fn get_segment_key(id: u64, seed: u8, hash: f64) -> u32 {
|
pub fn get_segment_key(id: u64, seed: u8, hash: f64) -> u64 {
|
||||||
match seed {
|
match seed {
|
||||||
0 => 0,
|
0 => 0,
|
||||||
seed => {
|
seed => {
|
||||||
let result = hash / ((id + 1).wrapping_mul(seed.into()) as f64) * 100.0;
|
let result = hash / ((id + 1).wrapping_mul(seed.into()) as f64) * 100.0;
|
||||||
result as u32
|
result as u64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -21,4 +21,14 @@ mod tests {
|
|||||||
fn test_segment_key_123() {
|
fn test_segment_key_123() {
|
||||||
assert_eq!(get_segment_key(1, 123, 12345.0), 5018);
|
assert_eq!(get_segment_key(1, 123, 12345.0), 5018);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_segment_key_large_1() {
|
||||||
|
assert_eq!(get_segment_key(51, 35, 516402887.0), 28373784);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_segment_key_large_2() {
|
||||||
|
assert_eq!(get_segment_key(0, 66, 3908240000.0), 5921575757);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,8 @@ impl JsQMC2 {
|
|||||||
/// Create a new QMC2 (mgg/mflac) cipher instance.
|
/// Create a new QMC2 (mgg/mflac) cipher instance.
|
||||||
#[wasm_bindgen(constructor)]
|
#[wasm_bindgen(constructor)]
|
||||||
pub fn new(ekey: &str) -> Result<JsQMC2, JsError> {
|
pub fn new(ekey: &str) -> Result<JsQMC2, JsError> {
|
||||||
let cipher = QMCv2Cipher::new(ekey.as_bytes()).map_err(map_js_error)?;
|
let key = umc_qmc::ekey::decrypt(ekey).map_err(map_js_error)?;
|
||||||
|
let cipher = QMCv2Cipher::new(key).map_err(map_js_error)?;
|
||||||
Ok(JsQMC2(cipher))
|
Ok(JsQMC2(cipher))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,8 @@ async function main() {
|
|||||||
const wasmDistDir = path.resolve(__dirname, 'dist');
|
const wasmDistDir = path.resolve(__dirname, 'dist');
|
||||||
await rm(wasmOutDir, { recursive: true, force: true });
|
await rm(wasmOutDir, { recursive: true, force: true });
|
||||||
const wasmRelOutDir = path.relative(wasmSourceDir, wasmOutDir);
|
const wasmRelOutDir = path.relative(wasmSourceDir, wasmOutDir);
|
||||||
await run(['wasm-pack', 'build', '--target', 'web', '--out-dir', wasmRelOutDir], {
|
const profileFlag = process.env.BUILD_RELEASE ? '--release' : '--dev';
|
||||||
|
await run(['wasm-pack', 'build', profileFlag, '--target', 'web', '--out-dir', wasmRelOutDir], {
|
||||||
cwd: path.resolve(__dirname, '..', 'um_wasm'),
|
cwd: path.resolve(__dirname, '..', 'um_wasm'),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ function loader() {
|
|||||||
const url = new URL('um_wasm_bg.wasm', import.meta.url);
|
const url = new URL('um_wasm_bg.wasm', import.meta.url);
|
||||||
const wasm =
|
const wasm =
|
||||||
url.protocol === 'file:'
|
url.protocol === 'file:'
|
||||||
? import('node:f' + 's/promises')
|
? import(/* @vite-ignore */ 'node:f' + 's/promises')
|
||||||
.then((fs) => fs.readFile(url))
|
.then((fs) => fs.readFile(url))
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log('read wasm failed', err);
|
console.log('read wasm failed', err);
|
||||||
|
Loading…
Reference in New Issue
Block a user