• Help with reversing a function

    From Tenjin@21:1/5 to All on Mon Aug 30 05:13:50 2021
    <?xml version="1.0"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html>
    <head>
    <title>Fun with && and ||</title>
    <script type="text/javascript">
    function g(s, C, m) {
    console.log(String.fromCharCode(96 + C));
    return (
    (!C && !s[m]) ||
    (C &&
    s[m] &&
    s[m++] == String.fromCharCode(96 + C) &&
    f(s, (++C * C++ + C++ * ++C) >> ++m, --m))
    );
    }
    </script>
    </head>
    <body style="text-align: center">
    <form
    onsubmit="alert((g(pass.value,1,0) ? 'Correct! The password is ' : 'Wrong! not ')+pass.value); return false;"
    >
    <div>
    <input type="text" name="pass" />
    <input type="submit" value="Login" />
    </div>
    </form>
    </body>
    </html>

    I need some help in finding what the correct password is. So far I understand that te first character must contain an "a"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julio Di Egidio@21:1/5 to Tenjin on Tue Aug 31 08:05:41 2021
    On Monday, 30 August 2021 at 14:14:45 UTC+2, Tenjin wrote:

    function g(s, C, m) {
    console.log(String.fromCharCode(96 + C));
    return (
    (!C && !s[m]) ||
    (C &&
    s[m] &&
    s[m++] == String.fromCharCode(96 + C) &&
    f(s, (++C * C++ + C++ * ++C) >> ++m, --m))

    I take that should read 'g', not 'f'.

    );
    }

    onsubmit="alert((g(pass.value,1,0) ? 'Correct! The password is ' : 'Wrong! not ')+pass.value); return false;"

    I need some help in finding what the correct password is. So far I understand that te first character must contain an "a"

    1) Firstly, few transformations [best viewed in monospace]:

    1.1) Some clean-up and fixes:

    (Fixed the exit conditions: note that 'false || undefined' is 'undefined', not 'false'.)

    function g_1(s, c, m) {
    var L = s.length;
    return (
    (!c && m === L)
    || (c && m < L
    && s[m++] === String.fromCharCode(96+c)
    && g_1(s, (++c*c++ + c++*++c) >> ++m, --m))
    );
    }

    1.2) Resolve increments:

    function g_2(s, c, m) {
    var L = s.length;
    return (
    (!c && m === L)
    || (c && m < L
    && s[m] === String.fromCharCode(96+c)
    && g_2(s, ((c+1)*(c+1) + (c+2)*(c+4)) >> (m+2), (m+1)))
    );
    }

    1.3) Unwind recursion and subsume 'm':

    (We can subsume 'm' since it is the index into the string, bound to start from zero.)

    function g(s, c) {
    var L = s.length;
    if (c === 0) { // short-cut
    return L === 0;
    }
    for (var m = 0; m < L; ++m) {
    if(!(s[m] === String.fromCharCode(96+c))) {
    return false;
    }
    c = (c+1)*(c+1) + (c+2)*(c+4) >> m+2;
    }
    return c === 0;
    }

    2) Now from 1.3 we can extract the password generator:

    (There is in 1.3 simply a comparison char by char with the expected password, so we can extrapolate the logic that just produces the password.)

    function h(c) {
    var s = "";
    for (var m = 0; c !== 0; ++m) {
    s += String.fromCharCode(96+c);
    c = (c+1)*(c+1) + (c+2)*(c+4) >> m+2;
    }
    return s;
    }

    T) Some basic (and quick) testing in the console:

    (Preliminarily, copy-paste the functions g_1, g, and h in the console.)

    T.1) Check the code transformation:

    h(1)
    <- "adiorlc"

    g_1("adiorlc", 1, 0)
    <- true

    g_1("adiorlC", 1, 0)
    <- false

    g_1("adiorl", 1, 0)
    <- false

    g("adiorlc", 1)
    <- true

    g("adiorlC", 1)
    <- false

    g("adiorl", 1)
    <- false

    T.2) Test the roundtrip:

    g(h(100), 100)
    <- true

    g(h(100), 99)
    <- false

    var lo = -9, hi = 5; for (var c = lo; c <= hi; ++c) { var s = h(c), e_1 = g_1(s, c, 0), e = g(s, c); console.log(c, s, e_1, e); }
    -9 "Wxĉວ셭ﵗ黡繗目护눕뙉ꯡ찁ᗋȫa" true true
    -8 "XrÄմ鸾늲户抉韙哵많䮑䰶ⵐࡄ" true true
    -7 "Yl‘ƥ᩻侚碸酟풂툲㒂ጕ鮐벋ቘā" true true
    -6 "Zhy»ɼ␼ᨲ皏徕騐鼧弫Ⱪ빗ᩓ́c" true true
    -5 "[diorlc" true true
    -4 "\\bddb" true true
    -3 "]" true true
    -2 "^" true true
    -1 "_" true true
    0 "" true true
    1 "adiorlc" true true
    2 "bhy»ɼ␼ᨲ皏徕騐鼧弫Ⱪ빗ᩓ́c" true true
    3 "cl‘ƥ᩻侚碸酟풂툲㒂ጕ鮐벋ቘā" true true
    4 "drÄմ鸾늲户抉韙哵많䮑䰶ⵐࡄ" true true
    5 "exĉວ셭ﵗ黡繗目护눕뙉ꯡ찁ᗋȫa" true true
    <- undefined

    Seems to work fine for all 'c' integer, but I have neither *proved* that, nor I have proved that 'h' always terminates.

    N.B. It is definitely NOT a secure scheme...

    Have fun,

    Julio

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)