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 cipher = match key.len() {
|
||||
0 => Err(QmcCryptoError::QMCV2MapKeyEmpty)?,
|
||||
..=300 => QMCv2Cipher::MapL(QMC2Map::new(key)?),
|
||||
1..=300 => QMCv2Cipher::MapL(QMC2Map::new(key)?),
|
||||
_ => QMCv2Cipher::RC4(QMC2RC4::new(key)),
|
||||
};
|
||||
Ok(cipher)
|
||||
|
@ -11,14 +11,14 @@ const RC4_STREAM_CACHE_SIZE: usize = OTHER_SEGMENT_SIZE + 512;
|
||||
pub struct QMC2RC4 {
|
||||
hash: f64,
|
||||
key: Box<[u8]>,
|
||||
key_stream: [u8; RC4_STREAM_CACHE_SIZE],
|
||||
key_stream: Box<[u8; RC4_STREAM_CACHE_SIZE]>,
|
||||
}
|
||||
|
||||
impl QMC2RC4 {
|
||||
pub fn new(key: &[u8]) -> Self {
|
||||
let mut rc4 = RC4::new(key);
|
||||
let mut key_stream = [0u8; RC4_STREAM_CACHE_SIZE];
|
||||
rc4.derive(&mut key_stream);
|
||||
let mut key_stream = Box::new([0u8; RC4_STREAM_CACHE_SIZE]);
|
||||
rc4.derive(&mut key_stream[..]);
|
||||
|
||||
Self {
|
||||
hash: hash(key),
|
||||
@ -31,8 +31,9 @@ impl QMC2RC4 {
|
||||
let n = self.key.len();
|
||||
|
||||
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;
|
||||
*datum ^= self.key[idx % n];
|
||||
let idx = get_segment_key(offset as u64, self.key[offset % n], self.hash);
|
||||
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 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);
|
||||
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) {
|
||||
*datum ^= key;
|
||||
}
|
||||
|
@ -42,8 +42,11 @@ impl RC4 {
|
||||
self.state[index]
|
||||
}
|
||||
|
||||
pub fn derive(&mut self, buffer: &mut [u8]) {
|
||||
for item in buffer.iter_mut() {
|
||||
pub fn derive<T>(&mut self, buffer: &mut T)
|
||||
where
|
||||
T: AsMut<[u8]> + ?Sized,
|
||||
{
|
||||
for item in buffer.as_mut().iter_mut() {
|
||||
*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 {
|
||||
0 => 0,
|
||||
seed => {
|
||||
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() {
|
||||
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.
|
||||
#[wasm_bindgen(constructor)]
|
||||
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))
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,8 @@ async function main() {
|
||||
const wasmDistDir = path.resolve(__dirname, 'dist');
|
||||
await rm(wasmOutDir, { recursive: true, force: true });
|
||||
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'),
|
||||
});
|
||||
|
||||
|
@ -11,7 +11,7 @@ function loader() {
|
||||
const url = new URL('um_wasm_bg.wasm', import.meta.url);
|
||||
const wasm =
|
||||
url.protocol === 'file:'
|
||||
? import('node:f' + 's/promises')
|
||||
? import(/* @vite-ignore */ 'node:f' + 's/promises')
|
||||
.then((fs) => fs.readFile(url))
|
||||
.catch((err) => {
|
||||
console.log('read wasm failed', err);
|
||||
|
Loading…
Reference in New Issue
Block a user