According to MDN, every WebSocket message is sent as one or more frames. Your job is to extract the payload given a (masked) client-to-server text frame. The steps to extract the payload is as follows:
- ignore byte 1; read byte 2
- if it is 254, skip the next 2 bytes
- if it is 255, skip the next 8 bytes,
- otherwise, continue
- interpret the next 4 bytes as an XOR-cipher key
- decrypt the final bytes using the (repeating) key and interpret it as a UTF-8 encoded string
For reference, here is an ungolfed solution:
#!/usr/bin/env python3
frame = open(0, 'rb').read()
pos = 2
if frame[1] == 254:
pos += 2 # skip 2 bytes
if frame[1] == 255:
pos += 8 # skip 8 bytes
# read the key (4 bytes)
key = frame[pos:][:4]
pos += 4
# decode the payload
payload = bytes(x ^ key[i % 4] for i, x in enumerate(frame[pos:]))
# output
print(payload.decode("utf-8"))
Test Cases
frame (octets are represented in hex) | payload |
---|---|
81 83 3D 54 23 06 70 10 6D |
MDN |
81 85 3D 54 23 06 55 31 4F 6A 52 |
hello |
81 FE 01 BD 3D 54 23 06 71 3B 51 63 50 74 4A 76 4E 21 4E 26 59 3B 4F 69 4F 74 50 6F 49 74 42 6B 58 20 0F 26 5E 3B 4D 75 58 37 57 63 49 21 51 26 5C 30 4A 76 54 27 40 6F 53 33 03 63 51 3D 57 2A 1D 27 46 62 1D 30 4C 26 58 3D 56 75 50 3B 47 26 49 31 4E 76 52 26 03 6F 53 37 4A 62 54 30 56 68 49 74 56 72 1D 38 42 64 52 26 46 26 58 20 03 62 52 38 4C 74 58 74 4E 67 5A 3A 42 26 5C 38 4A 77 48 35 0D 26 68 20 03 63 53 3D 4E 26 5C 30 03 6B 54 3A 4A 6B 1D 22 46 68 54 35 4E 2A 1D 25 56 6F 4E 74 4D 69 4E 20 51 73 59 74 46 7E 58 26 40 6F 49 35 57 6F 52 3A 03 73 51 38 42 6B 5E 3B 03 6A 5C 36 4C 74 54 27 03 68 54 27 4A 26 48 20 03 67 51 3D 52 73 54 24 03 63 45 74 46 67 1D 37 4C 6B 50 3B 47 69 1D 37 4C 68 4E 31 52 73 5C 20 0D 26 79 21 4A 75 1D 35 56 72 58 74 4A 74 48 26 46 26 59 3B 4F 69 4F 74 4A 68 1D 26 46 76 4F 31 4B 63 53 30 46 74 54 20 03 6F 53 74 55 69 51 21 53 72 5C 20 46 26 4B 31 4F 6F 49 74 46 75 4E 31 03 65 54 38 4F 73 50 74 47 69 51 3B 51 63 1D 31 56 26 5B 21 44 6F 5C 20 03 68 48 38 4F 67 1D 24 42 74 54 35 57 73 4F 7A 03 43 45 37 46 76 49 31 56 74 1D 27 4A 68 49 74 4C 65 5E 35 46 65 5C 20 03 65 48 24 4A 62 5C 20 42 72 1D 3A 4C 68 1D 24 51 69 54 30 46 68 49 78 03 75 48 3A 57 26 54 3A 03 65 48 38 53 67 1D 25 56 6F 1D 3B 45 60 54 37 4A 67 1D 30 46 75 58 26 56 68 49 74 4E 69 51 38 4A 72 1D 35 4D 6F 50 74 4A 62 1D 31 50 72 1D 38 42 64 52 26 56 6B 13 |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. |
Standard loopholes are forbidden. Shortest code wins.
unsigned short
and used as the payload length. When anunsigned short
is still inadequate to express the payload length, byte 2 is set to 0xFF and the next 8 bytes are interpreted as anunsigned long
. Furthermore, messages can be longer if sent across multiple frames, but that is out of the scope of this problem. \$\endgroup\$