fathonix / MikrotikCaptiveAutologin

Node.js script that automatically logs into Mikrotik captive portal.
MIT License
5 stars 1 forks source link

Rewrite in a compiled language and use QuickJS for md5.js? #2

Open fathonix opened 9 months ago

fathonix commented 9 months ago

This project was intended to be written in a language with minimal dependency, but the first time we wrote this we didn't find a compatible MD5 implementation. So we relied on Node.js to run md5.js.

Recently, I found a tiny JS runtime called QuickJS. It implements most of ES2020 (which is way more than we need) and only adds ~200KB when embedded into a C program. Would be nice to have a statically compiled, lightweight single executable that could run without any external dependency.

fathonix commented 9 months ago

cc @iyxan23

iyxan23 commented 9 months ago

sounds cool, but sounds a bit over-engineered if im gonna be honest. i don't really have the time to do things like this, so ig its up to you. se7-se7 aja sih if you want to explore things further.

fathonix commented 9 months ago

I agree, I think I'm too fascinated by minimal binaries like BusyBox and Toybox lately haha. Is there any suggestion on which language to use btw? I'm thinking of C for the sake of minimalism but I wanna hear yours.

iyxan23 commented 9 months ago

what else would I choose? rust ofc lol hehe

iyxan23 commented 9 months ago

anyways, now that AI is rampant, I made it convert the weirdly incompatible md5.js to rust:

use std::num::Wrapping;

fn safe_add(x: u32, y: u32) -> u32 {
    let lsw = (Wrapping(x) & Wrapping(0xFFFF)).0 + (Wrapping(y) & Wrapping(0xFFFF)).0;
    let msw = (x >> 16) + (y >> 16) + (lsw >> 16);
    (msw << 16) | (lsw & 0xFFFF)
}

fn rol(num: u32, cnt: u32) -> u32 {
    (num << cnt) | (num >> (32 - cnt))
}

fn cmn(q: u32, a: u32, b: u32, x: u32, s: u32, t: u32) -> u32 {
    safe_add(rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b)
}

fn ff(a: u32, b: u32, c: u32, d: u32, x: u32, s: u32, t: u32) -> u32 {
    cmn((b & c) | ((!b) & d), a, b, x, s, t)
}

fn gg(a: u32, b: u32, c: u32, d: u32, x: u32, s: u32, t: u32) -> u32 {
    cmn((b & d) | (c & (!d)), a, b, x, s, t)
}

fn hh(a: u32, b: u32, c: u32, d: u32, x: u32, s: u32, t: u32) -> u32 {
    cmn(b ^ c ^ d, a, b, x, s, t)
}

fn ii(a: u32, b: u32, c: u32, d: u32, x: u32, s: u32, t: u32) -> u32 {
    cmn(c ^ (b | (!d)), a, b, x, s, t)
}

fn core_md5(x: &[u32]) -> [u32; 4] {
    let mut a: u32 = 1732584193;
    let mut b: u32 = -271733879;
    let mut c: u32 = -1732584194;
    let mut d: u32 = 271733878;

    for i in (0..x.len()).step_by(16) {
        let olda = a;
        let oldb = b;
        let oldc = c;
        let oldd = d;

        a = ff(a, b, c, d, x[i + 0], 7, -680876936);
        d = ff(d, a, b, c, x[i + 1], 12, -389564586);
        c = ff(c, d, a, b, x[i + 2], 17, 606105819);
        b = ff(b, c, d, a, x[i + 3], 22, -1044525330);
        a = ff(a, b, c, d, x[i + 4], 7, -176418897);
        d = ff(d, a, b, c, x[i + 5], 12, 1200080426);
        c = ff(c, d, a, b, x[i + 6], 17, -1473231341);
        b = ff(b, c, d, a, x[i + 7], 22, -45705983);
        a = ff(a, b, c, d, x[i + 8], 7, 1770035416);
        d = ff(d, a, b, c, x[i + 9], 12, -1958414417);
        c = ff(c, d, a, b, x[i + 10], 17, -42063);
        b = ff(b, c, d, a, x[i + 11], 22, -1990404162);
        a = ff(a, b, c, d, x[i + 12], 7, 1804603682);
        d = ff(d, a, b, c, x[i + 13], 12, -40341101);
        c = ff(c, d, a, b, x[i + 14], 17, -1502002290);
        b = ff(b, c, d, a, x[i + 15], 22, 1236535329);

        a = gg(a, b, c, d, x[i + 1], 5, -165796510);
        d = gg(d, a, b, c, x[i + 6], 9, -1069501632);
        c = gg(c, d, a, b, x[i + 11], 14, 643717713);
        b = gg(b, c, d, a, x[i + 0], 20, -373897302);
        a = gg(a, b, c, d, x[i + 5], 5, -701558691);
        d = gg(d, a, b, c, x[i + 10], 9, 38016083);
        c = gg(c, d, a, b, x[i + 15], 14, -660478335);
        b = gg(b, c, d, a, x[i + 4], 20, -405537848);
        a = gg(a, b, c, d, x[i + 9], 5, 568446438);
        d = gg(d, a, b, c, x[i + 14], 9, -1019803690);
        c = gg(c, d, a, b, x[i + 3], 14, -187363961);
        b = gg(b, c, d, a, x[i + 8], 20, 1163531501);
        a = gg(a, b, c, d, x[i + 13], 5, -1444681467);
        d = gg(d, a, b, c, x[i + 2], 9, -51403784);
        c = gg(c, d, a, b, x[i + 7], 14, 1735328473);
        b = gg(b, c, d, a, x[i + 12], 20, -1926607734);

        a = hh(a, b, c, d, x[i + 5], 4, -378558);
        d = hh(d, a, b, c, x[i + 8], 11, -2022574463);
        c = hh(c, d, a, b, x[i + 11], 16, 1839030562);
        b = hh(b, c, d, a, x[i + 14], 23, -35309556);
        a = hh(a, b, c, d, x[i + 1], 4, -1530992060);
        d = hh(d, a, b, c, x[i + 4], 11, 1272893353);
        c = hh(c, d, a, b, x[i + 7], 16, -155497632);
        b = hh(b, c, d, a, x[i + 10], 23, -1094730640);
        a = hh(a, b, c, d, x[i + 13], 4, 681279174);
        d = hh(d, a, b, c, x[i + 0], 11, -358537222);
        c = hh(c, d, a, b, x[i + 3], 16, -722521979);
        b = hh(b, c, d, a, x[i + 6], 23, 76029189);
        a = hh(a, b, c, d, x[i + 9], 4, -640364487);
        d = hh(d, a, b, c, x[i + 12], 11, -421815835);
        c = hh(c, d, a, b, x[i + 15], 16, 530742520);
        b = hh(b, c, d, a, x[i + 2], 23, -995338651);

        a = ii(a, b, c, d, x[i + 0], 6, -198630844);
        d = ii(d, a, b, c, x[i + 7], 10, 1126891415);
        c = ii(c, d, a, b, x[i + 14], 15, -1416354905);
        b = ii(b, c, d, a, x[i + 5], 21, -57434055);
        a = ii(a, b, c, d, x[i + 12], 6, 1700485571);
        d = ii(d, a, b, c, x[i + 3], 10, -1894986606);
        c = ii(c, d, a, b, x[i + 10], 15, -1051523);
        b = ii(b, c, d, a, x[i + 1], 21, -2054922799);
        a = ii(a, b, c, d, x[i + 8], 6, 1873313359);
        d = ii(d, a, b, c, x[i + 15], 10, -30611744);
        c = ii(c, d, a, b, x[i + 6], 15, -1560198380);
        b = ii(b, c, d, a, x[i + 13], 21, 1309151649);
        a = ii(a, b, c, d, x[i + 4], 6, -145523070);
        d = ii(d, a, b, c, x[i + 11], 10, -1120210379);
        c = ii(c, d, a, b, x[i + 2], 15, 718787259);
        b = ii(b, c, d, a, x[i + 9], 21, -343485551);

        a = safe_add(a, olda);
        b = safe_add(b, oldb);
        c = safe_add(c, oldc);
        d = safe_add(d, oldd);
    }

    [a, b, c, d]
}

fn binl2hex(binarray: &[u32]) -> String {
    let hex_tab = "0123456789abcdef";
    let mut result = String::new();

    for i in 0..binarray.len() * 4 {
        result.push(
            hex_tab.chars()
                .nth(((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 0xF) as usize)
                .unwrap(),
        );
        result.push(
            hex_tab.chars()
                .nth(((binarray[i >> 2] >> ((i % 4) * 8)) & 0xF) as usize)
                .unwrap(),
        );
    }

    result
}

fn str2binl(input: &str) -> Vec<u32> {
    let nblk = (input.len() + 8) >> 6 + 1;
    let mut blks = vec![0; nblk * 16];

    for (i, &c) in input.as_bytes().iter().enumerate() {
        blks[i >> 2] |= (c as u32) << ((i % 4) * 8);
    }

    let len_bits = (input.len() as u64) * 8;
    blks[nblk * 16 - 2] = len_bits as u32;

    blks
}

fn hex_md5(input: &str) -> String {
    let bin_array = str2binl(input);
    let result = binl2hex(&core_md5(&bin_array));
    result
}

fn main() {
    let input_str = "Hello, world!";
    let md5_result = hex_md5(input_str);
    println!("MD5 Hash: {}", md5_result);
}

Dunno if this'll work or not, just my 2 cents if you wanted to investigate further.