diff --git a/hive-ag3nt/assets/screen.html b/hive-ag3nt/assets/screen.html
index 5ce270e..4899567 100644
--- a/hive-ag3nt/assets/screen.html
+++ b/hive-ag3nt/assets/screen.html
@@ -242,7 +242,9 @@ canvas { display: block; cursor: default; }
: j<48 ? [bb^cc^dd, (3*j+5)%16]
: [cc^(bb|(~dd)), (7*j)%16];
f = add(add(aa, f), add(m[i+g], T[j]));
- [aa,dd,cc,bb] = [dd, cc, bb, add(bb, r(f, S[(j%4)+((j>>2&3)*4)]))];
+ // Rotation amount: round = j>>4 (changes every 16 steps),
+ // position-in-round = j%4. S is laid out as 4 rounds × 4.
+ [aa,dd,cc,bb] = [dd, cc, bb, add(bb, r(f, S[(j%4)+((j>>4)*4)]))];
}
[a,b2,c,d] = [add(a,aa), add(b2,bb), add(c,cc), add(d,dd)];
}
@@ -419,8 +421,15 @@ canvas { display: block; cursor: default; }
const aesKey = md5(sharedBytes);
dbg('Apple-DH: shared MD5 key=' + hex(aesKey));
- // Credentials: 64 bytes username (zeroed) + 64 bytes password (zeroed)
- const creds = new Uint8Array(128); // empty username + empty password
+ // Credentials: 64 bytes username + 64 bytes password.
+ // weston's vnc_handle_auth (libweston/backend-vnc/vnc.c) does
+ // getpwnam(username) and requires pw_uid == weston's own uid
+ // BEFORE PAM is ever consulted — an empty/garbage username is
+ // rejected outright. weston runs as root, so the username must
+ // be "root". The password stays empty; pam_permit.so on the
+ // weston-remote-access PAM service accepts it.
+ const creds = new Uint8Array(128);
+ creds.set(new TextEncoder().encode('root'), 0);
const encCreds = await aes128ecb(aesKey, creds);
// Send: encrypted_creds + client_pub