@honeybbq/teamspeak-client 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/address-BR-5unVo.cjs.map +1 -1
  2. package/dist/address-BfmovVpp.js.map +1 -1
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/client.d.ts +16 -1
  5. package/dist/client.d.ts.map +1 -1
  6. package/dist/command/index.cjs +1 -1
  7. package/dist/command/index.mjs +1 -1
  8. package/dist/command/parser.d.ts.map +1 -1
  9. package/dist/{crypt-init2-D70ha4LB.js → crypt-init2-BcGT--df.js} +2 -2
  10. package/dist/{crypt-init2-D70ha4LB.js.map → crypt-init2-BcGT--df.js.map} +1 -1
  11. package/dist/{crypt-init2-DparLekm.cjs → crypt-init2-Bkee1YxV.cjs} +2 -2
  12. package/dist/{crypt-init2-DparLekm.cjs.map → crypt-init2-Bkee1YxV.cjs.map} +1 -1
  13. package/dist/crypto/identity.d.ts +13 -1
  14. package/dist/crypto/identity.d.ts.map +1 -1
  15. package/dist/crypto/index.cjs +1 -1
  16. package/dist/crypto/index.d.ts +2 -1
  17. package/dist/crypto/index.d.ts.map +1 -1
  18. package/dist/crypto/index.mjs +3 -3
  19. package/dist/{crypto-CDlweUL3.cjs → crypto-BfDd9DP6.cjs} +2 -2
  20. package/dist/{crypto-CDlweUL3.cjs.map → crypto-BfDd9DP6.cjs.map} +1 -1
  21. package/dist/{crypto-Bg02m4ZE.js → crypto-DLV3oH5F.js} +12 -12
  22. package/dist/{crypto-Bg02m4ZE.js.map → crypto-DLV3oH5F.js.map} +1 -1
  23. package/dist/{handler-DI_abe9c.js → handler-BpdZFsKo.js} +104 -102
  24. package/dist/handler-BpdZFsKo.js.map +1 -0
  25. package/dist/handler-aywHvv7I.cjs +2 -0
  26. package/dist/handler-aywHvv7I.cjs.map +1 -0
  27. package/dist/handshake/index.cjs +1 -1
  28. package/dist/handshake/index.mjs +1 -1
  29. package/dist/handshake.d.ts +9 -0
  30. package/dist/handshake.d.ts.map +1 -1
  31. package/dist/index.cjs +2 -2
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.mjs +294 -290
  34. package/dist/index.mjs.map +1 -1
  35. package/dist/{parser-DZMv3Jm-.js → parser-BX8NEiBe.js} +4 -4
  36. package/dist/parser-BX8NEiBe.js.map +1 -0
  37. package/dist/parser-BfwYH2fT.cjs +2 -0
  38. package/dist/parser-BfwYH2fT.cjs.map +1 -0
  39. package/dist/{primitives-xIr6Tjk4.js → primitives-CdX74Rgu.js} +194 -190
  40. package/dist/primitives-CdX74Rgu.js.map +1 -0
  41. package/dist/primitives-DkwW7wcP.cjs +2 -0
  42. package/dist/primitives-DkwW7wcP.cjs.map +1 -0
  43. package/dist/transfer.d.ts.map +1 -1
  44. package/dist/transport/handler.d.ts +9 -1
  45. package/dist/transport/handler.d.ts.map +1 -1
  46. package/dist/transport/index.cjs +1 -1
  47. package/dist/transport/index.mjs +1 -1
  48. package/dist/types.d.ts +11 -0
  49. package/dist/types.d.ts.map +1 -1
  50. package/package.json +5 -2
  51. package/dist/handler-DI_abe9c.js.map +0 -1
  52. package/dist/handler-DuwoO5RC.cjs +0 -2
  53. package/dist/handler-DuwoO5RC.cjs.map +0 -1
  54. package/dist/parser-CL33R9tr.cjs +0 -2
  55. package/dist/parser-CL33R9tr.cjs.map +0 -1
  56. package/dist/parser-DZMv3Jm-.js.map +0 -1
  57. package/dist/primitives-cNNAeFCo.cjs +0 -2
  58. package/dist/primitives-cNNAeFCo.cjs.map +0 -1
  59. package/dist/primitives-xIr6Tjk4.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"address-BR-5unVo.cjs","names":["isIP","node_net","ClientStatus","\"Disconnected\"","\"Connecting\"","\"Connected\"","noopLogger","consoleLogger","splitHostPort","input","address","closingBracket","host","suffix","defaultPort","lastColon","candidatePort","joinHostPort","normalizedHost","stripBrackets","port","isIpAddress"],"sources":["../src/types.ts","../src/address.ts"],"sourcesContent":["// ---- Branded primitive types ------------------------------------------------\n\n/** A TS3-escaped string. Obtained only via escape(). */\nexport type EscapedString = string & { readonly __escaped: unique symbol };\n\n// ---- Event map --------------------------------------------------------------\n\nexport interface TextMessage {\n invokerName: string;\n invokerUID: string;\n message: string;\n invokerGroups: string[];\n targetMode: number;\n targetID: bigint;\n invokerID: number;\n}\n\nexport interface ClientMovedEvent {\n invokerName: string;\n invokerUID: string;\n targetChannelID: bigint;\n reasonID: number;\n id: number;\n invokerID: number;\n}\n\nexport interface ClientLeftViewEvent {\n reasonMsg: string;\n reasonID: number;\n id: number;\n targetID: number;\n}\n\nexport interface ClientInfo {\n nickname: string;\n uid: string;\n serverGroups: string[];\n channelID: bigint;\n type: number;\n id: number;\n}\n\nexport interface ChannelInfo {\n name: string;\n description: string;\n id: bigint;\n parentID: bigint;\n /** ID of the sibling channel this one is sorted after; 0 means first. */\n order: bigint;\n}\n\nexport interface FileUploadInfo {\n fileTransferKey: string;\n seekPosition: bigint;\n clientFileTransferID: number;\n serverFileTransferID: number;\n port: number;\n}\n\nexport interface FileDownloadInfo {\n fileTransferKey: string;\n size: bigint;\n clientFileTransferID: number;\n serverFileTransferID: number;\n port: number;\n}\n\nexport interface FileTransferStatusInfo {\n message: string;\n status: number;\n clientFileTransferID: number;\n}\n\nexport interface PokeEvent {\n invokerName: string;\n invokerUID: string;\n invokerID: number;\n message: string;\n}\n\nexport interface VoiceData {\n clientId: number;\n codec: number;\n data: Uint8Array;\n}\n\n// ---- Typed event map used by Client.on() ------------------------------------\n\nexport interface EventMap {\n textMessage: TextMessage;\n clientEnter: ClientInfo;\n clientLeave: ClientLeftViewEvent;\n clientMoved: ClientMovedEvent;\n poked: PokeEvent;\n voiceData: VoiceData;\n connected: void;\n disconnected: Error | undefined;\n kicked: string;\n}\n\n// ---- Client status ----------------------------------------------------------\n\nexport const enum ClientStatus {\n Disconnected = 0,\n Connecting = 1,\n Connected = 2,\n}\n\n// ---- Middleware types --------------------------------------------------------\n\nexport type CommandMiddleware = (\n next: (cmd: string) => Promise<void>,\n) => (cmd: string) => Promise<void>;\n\nexport type EventMiddleware = (\n next: (evt: EventMap[keyof EventMap]) => void,\n) => (evt: EventMap[keyof EventMap]) => void;\n\n// ---- Logger interface --------------------------------------------------------\n\nexport interface Logger {\n debug(msg: string, ...args: unknown[]): void;\n info(msg: string, ...args: unknown[]): void;\n warn(msg: string, ...args: unknown[]): void;\n error(msg: string, ...args: unknown[]): void;\n}\n\n/** A no-op logger that discards all messages. */\nexport const noopLogger: Logger = {\n debug() {},\n info() {},\n warn() {},\n error() {},\n};\n\n/** A console-backed logger. */\nexport const consoleLogger: Logger = {\n debug: console.debug.bind(console),\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n};\n\n// ---- Resolved address (from discovery) --------------------------------------\n\nexport interface ResolvedAddr {\n addr: string;\n source: string;\n expiry: Date;\n}\n\n// ---- AddrResolver interface -------------------------------------------------\n\nexport interface AddrResolver {\n resolve(addr: string, signal?: AbortSignal): Promise<ResolvedAddr[]>;\n}\n\n// ---- ClientOptions ----------------------------------------------------------\n\nexport interface ClientOptions {\n logger?: Logger;\n resolver?: AddrResolver;\n commandMiddleware?: CommandMiddleware[];\n eventMiddleware?: EventMiddleware[];\n /** Server password sent during the initial `clientinit` handshake. */\n serverPassword?: string;\n /** Default channel name to join during the initial `clientinit` handshake. */\n defaultChannel?: string;\n /** Password for `defaultChannel`, sent during the initial `clientinit` handshake. */\n defaultChannelPassword?: string;\n}\n","import { isIP } from \"node:net\";\n\nexport interface HostPort {\n host: string;\n port: string;\n}\n\n/** Parse a TeamSpeak address without confusing an IPv6 colon for a port separator. */\nexport function splitHostPort(address: string, defaultPort = \"9987\"): HostPort {\n const input = address.trim();\n if (input.startsWith(\"[\")) {\n const closingBracket = input.indexOf(\"]\");\n if (closingBracket > 0) {\n const host = input.slice(1, closingBracket);\n const suffix = input.slice(closingBracket + 1);\n if (suffix.startsWith(\":\") && /^\\d+$/.test(suffix.slice(1))) {\n return { host, port: suffix.slice(1) };\n }\n if (!suffix) return { host, port: defaultPort };\n }\n }\n\n // A raw IPv6 literal has no unambiguous port separator. Internal callers\n // normally use bracket notation, but accepting the literal with the default\n // port prevents a final IPv6 segment from being mistaken for a port.\n if (isIP(input) === 6) return { host: input, port: defaultPort };\n\n const lastColon = input.lastIndexOf(\":\");\n if (lastColon < 0) return { host: input, port: defaultPort };\n const candidatePort = input.slice(lastColon + 1);\n if (/^\\d+$/.test(candidatePort) && input.indexOf(\":\") === lastColon) {\n return { host: input.slice(0, lastColon), port: candidatePort };\n }\n return { host: input, port: defaultPort };\n}\n\nexport function joinHostPort(host: string, port: string): string {\n const normalizedHost = stripBrackets(host);\n return isIP(normalizedHost) === 6 || normalizedHost.includes(\":\")\n ? `[${normalizedHost}]:${port}`\n : `${normalizedHost}:${port}`;\n}\n\nexport function isIpAddress(host: string): boolean {\n return isIP(stripBrackets(host)) !== 0;\n}\n\nfunction stripBrackets(host: string): string {\n return host.startsWith(\"[\") && host.endsWith(\"]\") ? host.slice(1, -1) : host;\n}\n"],"mappings":"0BAsGA,IAAkBE,EAAX,SAAA,EAAA,OACL,GAAA,EAAAC,aAAA,GAAA,eACA,EAAA,EAAAC,WAAA,GAAA,aACA,EAAA,EAAAC,UAAA,GAAA,aACF,EAAA,CAAA,CAAA,EAsBaC,EAAqB,CAChC,OAAQ,CAAC,EACT,MAAO,CAAC,EACR,MAAO,CAAC,EACR,OAAQ,CAAC,CACX,EAGaC,EAAwB,CACnC,MAAO,QAAQ,MAAM,KAAK,OAAO,EACjC,KAAM,QAAQ,KAAK,KAAK,OAAO,EAC/B,KAAM,QAAQ,KAAK,KAAK,OAAO,EAC/B,MAAO,QAAQ,MAAM,KAAK,OAAO,CACnC,ECrIA,SAAgBC,EAAc,EAAiB,EAAc,OAAkB,CAC7E,IAAMC,EAAQC,EAAQ,KAAK,EAC3B,GAAID,EAAM,WAAW,GAAG,EAAG,CACzB,IAAME,EAAiBF,EAAM,QAAQ,GAAG,EACxC,GAAIE,EAAiB,EAAG,CACtB,IAAMC,EAAOH,EAAM,MAAM,EAAGE,CAAc,EACpCE,EAASJ,EAAM,MAAME,EAAiB,CAAC,EAC7C,GAAIE,EAAO,WAAW,GAAG,GAAK,QAAQ,KAAKA,EAAO,MAAM,CAAC,CAAC,EACxD,MAAO,CAAE,OAAM,KAAMA,EAAO,MAAM,CAAC,CAAE,EAEvC,GAAI,CAACA,EAAQ,MAAO,CAAE,OAAM,KAAMC,CAAY,CAChD,CACF,CAKA,IAAA,EAAId,EAAAA,KAAAA,CAAKS,CAAK,IAAM,EAAG,MAAO,CAAE,KAAMA,EAAO,KAAMK,CAAY,EAE/D,IAAMC,EAAYN,EAAM,YAAY,GAAG,EACvC,GAAIM,EAAY,EAAG,MAAO,CAAE,KAAMN,EAAO,KAAMK,CAAY,EAC3D,IAAME,EAAgBP,EAAM,MAAMM,EAAY,CAAC,EAI/C,MAHI,QAAQ,KAAKC,CAAa,GAAKP,EAAM,QAAQ,GAAG,IAAMM,EACjD,CAAE,KAAMN,EAAM,MAAM,EAAGM,CAAS,EAAG,KAAMC,CAAc,EAEzD,CAAE,KAAMP,EAAO,KAAMK,CAAY,CAC1C,CAEA,SAAgBG,EAAa,EAAc,EAAsB,CAC/D,IAAMC,EAAiBC,EAAcP,CAAI,EACzC,OAAA,EAAOZ,EAAAA,KAAAA,CAAKkB,CAAc,IAAM,GAAKA,EAAe,SAAS,GAAG,EAC5D,IAAIA,EAAe,IAAIE,IACvB,GAAGF,EAAe,GAAGE,GAC3B,CAEA,SAAgBC,EAAY,EAAuB,CACjD,OAAA,EAAOrB,EAAAA,KAAAA,CAAKmB,EAAcP,CAAI,CAAC,IAAM,CACvC,CAEA,SAASO,EAAc,EAAsB,CAC3C,OAAOP,EAAK,WAAW,GAAG,GAAKA,EAAK,SAAS,GAAG,EAAIA,EAAK,MAAM,EAAG,EAAE,EAAIA,CAC1E"}
1
+ {"version":3,"file":"address-BR-5unVo.cjs","names":["isIP","node_net","ClientStatus","\"Disconnected\"","\"Connecting\"","\"Connected\"","noopLogger","consoleLogger","splitHostPort","input","address","closingBracket","host","suffix","defaultPort","lastColon","candidatePort","joinHostPort","normalizedHost","stripBrackets","port","isIpAddress"],"sources":["../src/types.ts","../src/address.ts"],"sourcesContent":["// ---- Branded primitive types ------------------------------------------------\n\n/** A TS3-escaped string. Obtained only via escape(). */\nexport type EscapedString = string & { readonly __escaped: unique symbol };\n\n// ---- Event map --------------------------------------------------------------\n\nexport interface TextMessage {\n invokerName: string;\n invokerUID: string;\n message: string;\n invokerGroups: string[];\n targetMode: number;\n targetID: bigint;\n invokerID: number;\n}\n\nexport interface ClientMovedEvent {\n invokerName: string;\n invokerUID: string;\n targetChannelID: bigint;\n reasonID: number;\n id: number;\n invokerID: number;\n}\n\nexport interface ClientLeftViewEvent {\n reasonMsg: string;\n reasonID: number;\n id: number;\n targetID: number;\n}\n\nexport interface ClientInfo {\n nickname: string;\n uid: string;\n serverGroups: string[];\n channelID: bigint;\n type: number;\n id: number;\n}\n\nexport interface ChannelInfo {\n name: string;\n description: string;\n id: bigint;\n parentID: bigint;\n /** ID of the sibling channel this one is sorted after; 0 means first. */\n order: bigint;\n}\n\nexport interface FileUploadInfo {\n fileTransferKey: string;\n seekPosition: bigint;\n clientFileTransferID: number;\n serverFileTransferID: number;\n port: number;\n}\n\nexport interface FileDownloadInfo {\n fileTransferKey: string;\n size: bigint;\n clientFileTransferID: number;\n serverFileTransferID: number;\n port: number;\n}\n\nexport interface FileTransferStatusInfo {\n message: string;\n status: number;\n clientFileTransferID: number;\n}\n\nexport interface PokeEvent {\n invokerName: string;\n invokerUID: string;\n invokerID: number;\n message: string;\n}\n\nexport interface VoiceData {\n clientId: number;\n codec: number;\n data: Uint8Array;\n}\n\n// ---- Typed event map used by Client.on() ------------------------------------\n\nexport interface EventMap {\n textMessage: TextMessage;\n clientEnter: ClientInfo;\n clientLeave: ClientLeftViewEvent;\n clientMoved: ClientMovedEvent;\n poked: PokeEvent;\n voiceData: VoiceData;\n connected: void;\n disconnected: Error | undefined;\n kicked: string;\n}\n\n// ---- Transport seam ---------------------------------------------------------\n\n/** Creates a UDP socket of the given address family. */\nexport type SocketFactory = (family: 4 | 6) => import(\"node:dgram\").Socket;\n\n// ---- Client status ----------------------------------------------------------\n\nexport const enum ClientStatus {\n Disconnected = 0,\n Connecting = 1,\n Connected = 2,\n}\n\n// ---- Middleware types --------------------------------------------------------\n\nexport type CommandMiddleware = (\n next: (cmd: string) => Promise<void>,\n) => (cmd: string) => Promise<void>;\n\nexport type EventMiddleware = (\n next: (evt: EventMap[keyof EventMap]) => void,\n) => (evt: EventMap[keyof EventMap]) => void;\n\n// ---- Logger interface --------------------------------------------------------\n\nexport interface Logger {\n debug(msg: string, ...args: unknown[]): void;\n info(msg: string, ...args: unknown[]): void;\n warn(msg: string, ...args: unknown[]): void;\n error(msg: string, ...args: unknown[]): void;\n}\n\n/** A no-op logger that discards all messages. */\nexport const noopLogger: Logger = {\n debug() {},\n info() {},\n warn() {},\n error() {},\n};\n\n/** A console-backed logger. */\nexport const consoleLogger: Logger = {\n debug: console.debug.bind(console),\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n};\n\n// ---- Resolved address (from discovery) --------------------------------------\n\nexport interface ResolvedAddr {\n addr: string;\n source: string;\n expiry: Date;\n}\n\n// ---- AddrResolver interface -------------------------------------------------\n\nexport interface AddrResolver {\n resolve(addr: string, signal?: AbortSignal): Promise<ResolvedAddr[]>;\n}\n\n// ---- ClientOptions ----------------------------------------------------------\n\nexport interface ClientOptions {\n logger?: Logger;\n /**\n * Creates the UDP socket the client talks through, given the address family\n * the server's address resolved to.\n *\n * Supplying one lets an application route traffic through a proxy or tunnel,\n * or drive the client from something other than a real socket. It is the only\n * seam into the transport: without it the SDK always creates its own.\n */\n socketFactory?: SocketFactory;\n resolver?: AddrResolver;\n commandMiddleware?: CommandMiddleware[];\n eventMiddleware?: EventMiddleware[];\n /** Server password sent during the initial `clientinit` handshake. */\n serverPassword?: string;\n /** Default channel name to join during the initial `clientinit` handshake. */\n defaultChannel?: string;\n /** Password for `defaultChannel`, sent during the initial `clientinit` handshake. */\n defaultChannelPassword?: string;\n}\n","import { isIP } from \"node:net\";\n\nexport interface HostPort {\n host: string;\n port: string;\n}\n\n/** Parse a TeamSpeak address without confusing an IPv6 colon for a port separator. */\nexport function splitHostPort(address: string, defaultPort = \"9987\"): HostPort {\n const input = address.trim();\n if (input.startsWith(\"[\")) {\n const closingBracket = input.indexOf(\"]\");\n if (closingBracket > 0) {\n const host = input.slice(1, closingBracket);\n const suffix = input.slice(closingBracket + 1);\n if (suffix.startsWith(\":\") && /^\\d+$/.test(suffix.slice(1))) {\n return { host, port: suffix.slice(1) };\n }\n if (!suffix) return { host, port: defaultPort };\n }\n }\n\n // A raw IPv6 literal has no unambiguous port separator. Internal callers\n // normally use bracket notation, but accepting the literal with the default\n // port prevents a final IPv6 segment from being mistaken for a port.\n if (isIP(input) === 6) return { host: input, port: defaultPort };\n\n const lastColon = input.lastIndexOf(\":\");\n if (lastColon < 0) return { host: input, port: defaultPort };\n const candidatePort = input.slice(lastColon + 1);\n if (/^\\d+$/.test(candidatePort) && input.indexOf(\":\") === lastColon) {\n return { host: input.slice(0, lastColon), port: candidatePort };\n }\n return { host: input, port: defaultPort };\n}\n\nexport function joinHostPort(host: string, port: string): string {\n const normalizedHost = stripBrackets(host);\n return isIP(normalizedHost) === 6 || normalizedHost.includes(\":\")\n ? `[${normalizedHost}]:${port}`\n : `${normalizedHost}:${port}`;\n}\n\nexport function isIpAddress(host: string): boolean {\n return isIP(stripBrackets(host)) !== 0;\n}\n\nfunction stripBrackets(host: string): string {\n return host.startsWith(\"[\") && host.endsWith(\"]\") ? host.slice(1, -1) : host;\n}\n"],"mappings":"0BA2GA,IAAkBE,EAAX,SAAA,EAAA,OACL,GAAA,EAAAC,aAAA,GAAA,eACA,EAAA,EAAAC,WAAA,GAAA,aACA,EAAA,EAAAC,UAAA,GAAA,aACF,EAAA,CAAA,CAAA,EAsBaC,EAAqB,CAChC,OAAQ,CAAC,EACT,MAAO,CAAC,EACR,MAAO,CAAC,EACR,OAAQ,CAAC,CACX,EAGaC,EAAwB,CACnC,MAAO,QAAQ,MAAM,KAAK,OAAO,EACjC,KAAM,QAAQ,KAAK,KAAK,OAAO,EAC/B,KAAM,QAAQ,KAAK,KAAK,OAAO,EAC/B,MAAO,QAAQ,MAAM,KAAK,OAAO,CACnC,EC1IA,SAAgBC,EAAc,EAAiB,EAAc,OAAkB,CAC7E,IAAMC,EAAQC,EAAQ,KAAK,EAC3B,GAAID,EAAM,WAAW,GAAG,EAAG,CACzB,IAAME,EAAiBF,EAAM,QAAQ,GAAG,EACxC,GAAIE,EAAiB,EAAG,CACtB,IAAMC,EAAOH,EAAM,MAAM,EAAGE,CAAc,EACpCE,EAASJ,EAAM,MAAME,EAAiB,CAAC,EAC7C,GAAIE,EAAO,WAAW,GAAG,GAAK,QAAQ,KAAKA,EAAO,MAAM,CAAC,CAAC,EACxD,MAAO,CAAE,OAAM,KAAMA,EAAO,MAAM,CAAC,CAAE,EAEvC,GAAI,CAACA,EAAQ,MAAO,CAAE,OAAM,KAAMC,CAAY,CAChD,CACF,CAKA,IAAA,EAAId,EAAAA,KAAAA,CAAKS,CAAK,IAAM,EAAG,MAAO,CAAE,KAAMA,EAAO,KAAMK,CAAY,EAE/D,IAAMC,EAAYN,EAAM,YAAY,GAAG,EACvC,GAAIM,EAAY,EAAG,MAAO,CAAE,KAAMN,EAAO,KAAMK,CAAY,EAC3D,IAAME,EAAgBP,EAAM,MAAMM,EAAY,CAAC,EAI/C,MAHI,QAAQ,KAAKC,CAAa,GAAKP,EAAM,QAAQ,GAAG,IAAMM,EACjD,CAAE,KAAMN,EAAM,MAAM,EAAGM,CAAS,EAAG,KAAMC,CAAc,EAEzD,CAAE,KAAMP,EAAO,KAAMK,CAAY,CAC1C,CAEA,SAAgBG,EAAa,EAAc,EAAsB,CAC/D,IAAMC,EAAiBC,EAAcP,CAAI,EACzC,OAAA,EAAOZ,EAAAA,KAAAA,CAAKkB,CAAc,IAAM,GAAKA,EAAe,SAAS,GAAG,EAC5D,IAAIA,EAAe,IAAIE,IACvB,GAAGF,EAAe,GAAGE,GAC3B,CAEA,SAAgBC,EAAY,EAAuB,CACjD,OAAA,EAAOrB,EAAAA,KAAAA,CAAKmB,EAAcP,CAAI,CAAC,IAAM,CACvC,CAEA,SAASO,EAAc,EAAsB,CAC3C,OAAOP,EAAK,WAAW,GAAG,GAAKA,EAAK,SAAS,GAAG,EAAIA,EAAK,MAAM,EAAG,EAAE,EAAIA,CAC1E"}
@@ -1 +1 @@
1
- {"version":3,"file":"address-BfmovVpp.js","names":["ClientStatus","\"Disconnected\"","\"Connecting\"","\"Connected\"","noopLogger","consoleLogger","splitHostPort","input","address","closingBracket","host","suffix","defaultPort","isIP","lastColon","candidatePort","joinHostPort","normalizedHost","stripBrackets","port","isIpAddress"],"sources":["../src/types.ts","../src/address.ts"],"sourcesContent":["// ---- Branded primitive types ------------------------------------------------\n\n/** A TS3-escaped string. Obtained only via escape(). */\nexport type EscapedString = string & { readonly __escaped: unique symbol };\n\n// ---- Event map --------------------------------------------------------------\n\nexport interface TextMessage {\n invokerName: string;\n invokerUID: string;\n message: string;\n invokerGroups: string[];\n targetMode: number;\n targetID: bigint;\n invokerID: number;\n}\n\nexport interface ClientMovedEvent {\n invokerName: string;\n invokerUID: string;\n targetChannelID: bigint;\n reasonID: number;\n id: number;\n invokerID: number;\n}\n\nexport interface ClientLeftViewEvent {\n reasonMsg: string;\n reasonID: number;\n id: number;\n targetID: number;\n}\n\nexport interface ClientInfo {\n nickname: string;\n uid: string;\n serverGroups: string[];\n channelID: bigint;\n type: number;\n id: number;\n}\n\nexport interface ChannelInfo {\n name: string;\n description: string;\n id: bigint;\n parentID: bigint;\n /** ID of the sibling channel this one is sorted after; 0 means first. */\n order: bigint;\n}\n\nexport interface FileUploadInfo {\n fileTransferKey: string;\n seekPosition: bigint;\n clientFileTransferID: number;\n serverFileTransferID: number;\n port: number;\n}\n\nexport interface FileDownloadInfo {\n fileTransferKey: string;\n size: bigint;\n clientFileTransferID: number;\n serverFileTransferID: number;\n port: number;\n}\n\nexport interface FileTransferStatusInfo {\n message: string;\n status: number;\n clientFileTransferID: number;\n}\n\nexport interface PokeEvent {\n invokerName: string;\n invokerUID: string;\n invokerID: number;\n message: string;\n}\n\nexport interface VoiceData {\n clientId: number;\n codec: number;\n data: Uint8Array;\n}\n\n// ---- Typed event map used by Client.on() ------------------------------------\n\nexport interface EventMap {\n textMessage: TextMessage;\n clientEnter: ClientInfo;\n clientLeave: ClientLeftViewEvent;\n clientMoved: ClientMovedEvent;\n poked: PokeEvent;\n voiceData: VoiceData;\n connected: void;\n disconnected: Error | undefined;\n kicked: string;\n}\n\n// ---- Client status ----------------------------------------------------------\n\nexport const enum ClientStatus {\n Disconnected = 0,\n Connecting = 1,\n Connected = 2,\n}\n\n// ---- Middleware types --------------------------------------------------------\n\nexport type CommandMiddleware = (\n next: (cmd: string) => Promise<void>,\n) => (cmd: string) => Promise<void>;\n\nexport type EventMiddleware = (\n next: (evt: EventMap[keyof EventMap]) => void,\n) => (evt: EventMap[keyof EventMap]) => void;\n\n// ---- Logger interface --------------------------------------------------------\n\nexport interface Logger {\n debug(msg: string, ...args: unknown[]): void;\n info(msg: string, ...args: unknown[]): void;\n warn(msg: string, ...args: unknown[]): void;\n error(msg: string, ...args: unknown[]): void;\n}\n\n/** A no-op logger that discards all messages. */\nexport const noopLogger: Logger = {\n debug() {},\n info() {},\n warn() {},\n error() {},\n};\n\n/** A console-backed logger. */\nexport const consoleLogger: Logger = {\n debug: console.debug.bind(console),\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n};\n\n// ---- Resolved address (from discovery) --------------------------------------\n\nexport interface ResolvedAddr {\n addr: string;\n source: string;\n expiry: Date;\n}\n\n// ---- AddrResolver interface -------------------------------------------------\n\nexport interface AddrResolver {\n resolve(addr: string, signal?: AbortSignal): Promise<ResolvedAddr[]>;\n}\n\n// ---- ClientOptions ----------------------------------------------------------\n\nexport interface ClientOptions {\n logger?: Logger;\n resolver?: AddrResolver;\n commandMiddleware?: CommandMiddleware[];\n eventMiddleware?: EventMiddleware[];\n /** Server password sent during the initial `clientinit` handshake. */\n serverPassword?: string;\n /** Default channel name to join during the initial `clientinit` handshake. */\n defaultChannel?: string;\n /** Password for `defaultChannel`, sent during the initial `clientinit` handshake. */\n defaultChannelPassword?: string;\n}\n","import { isIP } from \"node:net\";\n\nexport interface HostPort {\n host: string;\n port: string;\n}\n\n/** Parse a TeamSpeak address without confusing an IPv6 colon for a port separator. */\nexport function splitHostPort(address: string, defaultPort = \"9987\"): HostPort {\n const input = address.trim();\n if (input.startsWith(\"[\")) {\n const closingBracket = input.indexOf(\"]\");\n if (closingBracket > 0) {\n const host = input.slice(1, closingBracket);\n const suffix = input.slice(closingBracket + 1);\n if (suffix.startsWith(\":\") && /^\\d+$/.test(suffix.slice(1))) {\n return { host, port: suffix.slice(1) };\n }\n if (!suffix) return { host, port: defaultPort };\n }\n }\n\n // A raw IPv6 literal has no unambiguous port separator. Internal callers\n // normally use bracket notation, but accepting the literal with the default\n // port prevents a final IPv6 segment from being mistaken for a port.\n if (isIP(input) === 6) return { host: input, port: defaultPort };\n\n const lastColon = input.lastIndexOf(\":\");\n if (lastColon < 0) return { host: input, port: defaultPort };\n const candidatePort = input.slice(lastColon + 1);\n if (/^\\d+$/.test(candidatePort) && input.indexOf(\":\") === lastColon) {\n return { host: input.slice(0, lastColon), port: candidatePort };\n }\n return { host: input, port: defaultPort };\n}\n\nexport function joinHostPort(host: string, port: string): string {\n const normalizedHost = stripBrackets(host);\n return isIP(normalizedHost) === 6 || normalizedHost.includes(\":\")\n ? `[${normalizedHost}]:${port}`\n : `${normalizedHost}:${port}`;\n}\n\nexport function isIpAddress(host: string): boolean {\n return isIP(stripBrackets(host)) !== 0;\n}\n\nfunction stripBrackets(host: string): string {\n return host.startsWith(\"[\") && host.endsWith(\"]\") ? host.slice(1, -1) : host;\n}\n"],"mappings":";;AAsGA,IAAkBA,IAAX,yBAAA,GAAA;QACL,EAAA,EAAAC,eAAA,KAAA,gBACA,EAAA,EAAAC,aAAA,KAAA,cACA,EAAA,EAAAC,YAAA,KAAA;AACF,EAAA,CAAA,CAAA,GAsBaC,IAAqB;CAChC,QAAQ,CAAC;CACT,OAAO,CAAC;CACR,OAAO,CAAC;CACR,QAAQ,CAAC;AACX,GAGaC,IAAwB;CACnC,OAAO,QAAQ,MAAM,KAAK,OAAO;CACjC,MAAM,QAAQ,KAAK,KAAK,OAAO;CAC/B,MAAM,QAAQ,KAAK,KAAK,OAAO;CAC/B,OAAO,QAAQ,MAAM,KAAK,OAAO;AACnC;;;ACrIA,SAAgBC,EAAc,GAAiB,IAAc,QAAkB;CAC7E,IAAMC,IAAQC,EAAQ,KAAK;CAC3B,IAAID,EAAM,WAAW,GAAG,GAAG;EACzB,IAAME,IAAiBF,EAAM,QAAQ,GAAG;EACxC,IAAIE,IAAiB,GAAG;GACtB,IAAMC,IAAOH,EAAM,MAAM,GAAGE,CAAc,GACpCE,IAASJ,EAAM,MAAME,IAAiB,CAAC;GAC7C,IAAIE,EAAO,WAAW,GAAG,KAAK,QAAQ,KAAKA,EAAO,MAAM,CAAC,CAAC,GACxD,OAAO;IAAE;IAAM,MAAMA,EAAO,MAAM,CAAC;GAAE;GAEvC,IAAI,CAACA,GAAQ,OAAO;IAAE;IAAM,MAAMC;GAAY;EAChD;CACF;CAKA,IAAIC,EAAKN,CAAK,MAAM,GAAG,OAAO;EAAE,MAAMA;EAAO,MAAMK;CAAY;CAE/D,IAAME,IAAYP,EAAM,YAAY,GAAG;CACvC,IAAIO,IAAY,GAAG,OAAO;EAAE,MAAMP;EAAO,MAAMK;CAAY;CAC3D,IAAMG,IAAgBR,EAAM,MAAMO,IAAY,CAAC;CAI/C,OAHI,QAAQ,KAAKC,CAAa,KAAKR,EAAM,QAAQ,GAAG,MAAMO,IACjD;EAAE,MAAMP,EAAM,MAAM,GAAGO,CAAS;EAAG,MAAMC;CAAc,IAEzD;EAAE,MAAMR;EAAO,MAAMK;CAAY;AAC1C;AAEA,SAAgBI,EAAa,GAAc,GAAsB;CAC/D,IAAMC,IAAiBC,EAAcR,CAAI;CACzC,OAAOG,EAAKI,CAAc,MAAM,KAAKA,EAAe,SAAS,GAAG,IAC5D,IAAIA,EAAe,IAAIE,MACvB,GAAGF,EAAe,GAAGE;AAC3B;AAEA,SAAgBC,EAAY,GAAuB;CACjD,OAAOP,EAAKK,EAAcR,CAAI,CAAC,MAAM;AACvC;AAEA,SAASQ,EAAc,GAAsB;CAC3C,OAAOR,EAAK,WAAW,GAAG,KAAKA,EAAK,SAAS,GAAG,IAAIA,EAAK,MAAM,GAAG,EAAE,IAAIA;AAC1E"}
1
+ {"version":3,"file":"address-BfmovVpp.js","names":["ClientStatus","\"Disconnected\"","\"Connecting\"","\"Connected\"","noopLogger","consoleLogger","splitHostPort","input","address","closingBracket","host","suffix","defaultPort","isIP","lastColon","candidatePort","joinHostPort","normalizedHost","stripBrackets","port","isIpAddress"],"sources":["../src/types.ts","../src/address.ts"],"sourcesContent":["// ---- Branded primitive types ------------------------------------------------\n\n/** A TS3-escaped string. Obtained only via escape(). */\nexport type EscapedString = string & { readonly __escaped: unique symbol };\n\n// ---- Event map --------------------------------------------------------------\n\nexport interface TextMessage {\n invokerName: string;\n invokerUID: string;\n message: string;\n invokerGroups: string[];\n targetMode: number;\n targetID: bigint;\n invokerID: number;\n}\n\nexport interface ClientMovedEvent {\n invokerName: string;\n invokerUID: string;\n targetChannelID: bigint;\n reasonID: number;\n id: number;\n invokerID: number;\n}\n\nexport interface ClientLeftViewEvent {\n reasonMsg: string;\n reasonID: number;\n id: number;\n targetID: number;\n}\n\nexport interface ClientInfo {\n nickname: string;\n uid: string;\n serverGroups: string[];\n channelID: bigint;\n type: number;\n id: number;\n}\n\nexport interface ChannelInfo {\n name: string;\n description: string;\n id: bigint;\n parentID: bigint;\n /** ID of the sibling channel this one is sorted after; 0 means first. */\n order: bigint;\n}\n\nexport interface FileUploadInfo {\n fileTransferKey: string;\n seekPosition: bigint;\n clientFileTransferID: number;\n serverFileTransferID: number;\n port: number;\n}\n\nexport interface FileDownloadInfo {\n fileTransferKey: string;\n size: bigint;\n clientFileTransferID: number;\n serverFileTransferID: number;\n port: number;\n}\n\nexport interface FileTransferStatusInfo {\n message: string;\n status: number;\n clientFileTransferID: number;\n}\n\nexport interface PokeEvent {\n invokerName: string;\n invokerUID: string;\n invokerID: number;\n message: string;\n}\n\nexport interface VoiceData {\n clientId: number;\n codec: number;\n data: Uint8Array;\n}\n\n// ---- Typed event map used by Client.on() ------------------------------------\n\nexport interface EventMap {\n textMessage: TextMessage;\n clientEnter: ClientInfo;\n clientLeave: ClientLeftViewEvent;\n clientMoved: ClientMovedEvent;\n poked: PokeEvent;\n voiceData: VoiceData;\n connected: void;\n disconnected: Error | undefined;\n kicked: string;\n}\n\n// ---- Transport seam ---------------------------------------------------------\n\n/** Creates a UDP socket of the given address family. */\nexport type SocketFactory = (family: 4 | 6) => import(\"node:dgram\").Socket;\n\n// ---- Client status ----------------------------------------------------------\n\nexport const enum ClientStatus {\n Disconnected = 0,\n Connecting = 1,\n Connected = 2,\n}\n\n// ---- Middleware types --------------------------------------------------------\n\nexport type CommandMiddleware = (\n next: (cmd: string) => Promise<void>,\n) => (cmd: string) => Promise<void>;\n\nexport type EventMiddleware = (\n next: (evt: EventMap[keyof EventMap]) => void,\n) => (evt: EventMap[keyof EventMap]) => void;\n\n// ---- Logger interface --------------------------------------------------------\n\nexport interface Logger {\n debug(msg: string, ...args: unknown[]): void;\n info(msg: string, ...args: unknown[]): void;\n warn(msg: string, ...args: unknown[]): void;\n error(msg: string, ...args: unknown[]): void;\n}\n\n/** A no-op logger that discards all messages. */\nexport const noopLogger: Logger = {\n debug() {},\n info() {},\n warn() {},\n error() {},\n};\n\n/** A console-backed logger. */\nexport const consoleLogger: Logger = {\n debug: console.debug.bind(console),\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n};\n\n// ---- Resolved address (from discovery) --------------------------------------\n\nexport interface ResolvedAddr {\n addr: string;\n source: string;\n expiry: Date;\n}\n\n// ---- AddrResolver interface -------------------------------------------------\n\nexport interface AddrResolver {\n resolve(addr: string, signal?: AbortSignal): Promise<ResolvedAddr[]>;\n}\n\n// ---- ClientOptions ----------------------------------------------------------\n\nexport interface ClientOptions {\n logger?: Logger;\n /**\n * Creates the UDP socket the client talks through, given the address family\n * the server's address resolved to.\n *\n * Supplying one lets an application route traffic through a proxy or tunnel,\n * or drive the client from something other than a real socket. It is the only\n * seam into the transport: without it the SDK always creates its own.\n */\n socketFactory?: SocketFactory;\n resolver?: AddrResolver;\n commandMiddleware?: CommandMiddleware[];\n eventMiddleware?: EventMiddleware[];\n /** Server password sent during the initial `clientinit` handshake. */\n serverPassword?: string;\n /** Default channel name to join during the initial `clientinit` handshake. */\n defaultChannel?: string;\n /** Password for `defaultChannel`, sent during the initial `clientinit` handshake. */\n defaultChannelPassword?: string;\n}\n","import { isIP } from \"node:net\";\n\nexport interface HostPort {\n host: string;\n port: string;\n}\n\n/** Parse a TeamSpeak address without confusing an IPv6 colon for a port separator. */\nexport function splitHostPort(address: string, defaultPort = \"9987\"): HostPort {\n const input = address.trim();\n if (input.startsWith(\"[\")) {\n const closingBracket = input.indexOf(\"]\");\n if (closingBracket > 0) {\n const host = input.slice(1, closingBracket);\n const suffix = input.slice(closingBracket + 1);\n if (suffix.startsWith(\":\") && /^\\d+$/.test(suffix.slice(1))) {\n return { host, port: suffix.slice(1) };\n }\n if (!suffix) return { host, port: defaultPort };\n }\n }\n\n // A raw IPv6 literal has no unambiguous port separator. Internal callers\n // normally use bracket notation, but accepting the literal with the default\n // port prevents a final IPv6 segment from being mistaken for a port.\n if (isIP(input) === 6) return { host: input, port: defaultPort };\n\n const lastColon = input.lastIndexOf(\":\");\n if (lastColon < 0) return { host: input, port: defaultPort };\n const candidatePort = input.slice(lastColon + 1);\n if (/^\\d+$/.test(candidatePort) && input.indexOf(\":\") === lastColon) {\n return { host: input.slice(0, lastColon), port: candidatePort };\n }\n return { host: input, port: defaultPort };\n}\n\nexport function joinHostPort(host: string, port: string): string {\n const normalizedHost = stripBrackets(host);\n return isIP(normalizedHost) === 6 || normalizedHost.includes(\":\")\n ? `[${normalizedHost}]:${port}`\n : `${normalizedHost}:${port}`;\n}\n\nexport function isIpAddress(host: string): boolean {\n return isIP(stripBrackets(host)) !== 0;\n}\n\nfunction stripBrackets(host: string): string {\n return host.startsWith(\"[\") && host.endsWith(\"]\") ? host.slice(1, -1) : host;\n}\n"],"mappings":";;AA2GA,IAAkBA,IAAX,yBAAA,GAAA;QACL,EAAA,EAAAC,eAAA,KAAA,gBACA,EAAA,EAAAC,aAAA,KAAA,cACA,EAAA,EAAAC,YAAA,KAAA;AACF,EAAA,CAAA,CAAA,GAsBaC,IAAqB;CAChC,QAAQ,CAAC;CACT,OAAO,CAAC;CACR,OAAO,CAAC;CACR,QAAQ,CAAC;AACX,GAGaC,IAAwB;CACnC,OAAO,QAAQ,MAAM,KAAK,OAAO;CACjC,MAAM,QAAQ,KAAK,KAAK,OAAO;CAC/B,MAAM,QAAQ,KAAK,KAAK,OAAO;CAC/B,OAAO,QAAQ,MAAM,KAAK,OAAO;AACnC;;;AC1IA,SAAgBC,EAAc,GAAiB,IAAc,QAAkB;CAC7E,IAAMC,IAAQC,EAAQ,KAAK;CAC3B,IAAID,EAAM,WAAW,GAAG,GAAG;EACzB,IAAME,IAAiBF,EAAM,QAAQ,GAAG;EACxC,IAAIE,IAAiB,GAAG;GACtB,IAAMC,IAAOH,EAAM,MAAM,GAAGE,CAAc,GACpCE,IAASJ,EAAM,MAAME,IAAiB,CAAC;GAC7C,IAAIE,EAAO,WAAW,GAAG,KAAK,QAAQ,KAAKA,EAAO,MAAM,CAAC,CAAC,GACxD,OAAO;IAAE;IAAM,MAAMA,EAAO,MAAM,CAAC;GAAE;GAEvC,IAAI,CAACA,GAAQ,OAAO;IAAE;IAAM,MAAMC;GAAY;EAChD;CACF;CAKA,IAAIC,EAAKN,CAAK,MAAM,GAAG,OAAO;EAAE,MAAMA;EAAO,MAAMK;CAAY;CAE/D,IAAME,IAAYP,EAAM,YAAY,GAAG;CACvC,IAAIO,IAAY,GAAG,OAAO;EAAE,MAAMP;EAAO,MAAMK;CAAY;CAC3D,IAAMG,IAAgBR,EAAM,MAAMO,IAAY,CAAC;CAI/C,OAHI,QAAQ,KAAKC,CAAa,KAAKR,EAAM,QAAQ,GAAG,MAAMO,IACjD;EAAE,MAAMP,EAAM,MAAM,GAAGO,CAAS;EAAG,MAAMC;CAAc,IAEzD;EAAE,MAAMR;EAAO,MAAMK;CAAY;AAC1C;AAEA,SAAgBI,EAAa,GAAc,GAAsB;CAC/D,IAAMC,IAAiBC,EAAcR,CAAI;CACzC,OAAOG,EAAKI,CAAc,MAAM,KAAKA,EAAe,SAAS,GAAG,IAC5D,IAAIA,EAAe,IAAIE,MACvB,GAAGF,EAAe,GAAGE;AAC3B;AAEA,SAAgBC,EAAY,GAAuB;CACjD,OAAOP,EAAKK,EAAcR,CAAI,CAAC,MAAM;AACvC;AAEA,SAASQ,EAAc,GAAsB;CAC3C,OAAOR,EAAK,WAAW,GAAG,KAAKA,EAAK,SAAS,GAAG,IAAIA,EAAK,MAAM,GAAG,EAAE,IAAIA;AAC1E"}
package/dist/api.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,kFAAkF;AAClF,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,4CAA4C;AAC5C,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,QAAQ,SAAK,GACZ,OAAO,CAAC,IAAI,CAAC,CAYf;AAMD,uCAAuC;AACvC,wBAAsB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvF;AAED,6CAA6C;AAC7C,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAKjG;AAED,uCAAuC;AACvC,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAUzE;AAED,0DAA0D;AAC1D,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAavE;AAED,mCAAmC;AACnC,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,IAAI,CAAC,CASf"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,kFAAkF;AAClF,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,4CAA4C;AAC5C,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,QAAQ,SAAK,GACZ,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,uCAAuC;AACvC,wBAAsB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvF;AAED,6CAA6C;AAC7C,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAKjG;AAED,uCAAuC;AACvC,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAUzE;AAED,0DAA0D;AAC1D,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAavE;AAED,mCAAmC;AACnC,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,IAAI,CAAC,CASf"}
package/dist/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type EventMap, type ClientOptions, type CommandMiddleware, type EventMiddleware, type Logger, ClientStatus } from "./types.js";
2
- import { Identity, Crypt } from "./crypto/index.js";
2
+ import { Identity, Crypt, type UidAlgorithm } from "./crypto/index.js";
3
3
  import { PacketHandler } from "./transport/handler.js";
4
4
  import type { FileUploadInfo, FileDownloadInfo } from "./types.js";
5
5
  import type { Readable, Writable } from "node:stream";
@@ -15,6 +15,12 @@ export declare class Client {
15
15
  /** @internal */ logger: Logger;
16
16
  /** @internal */ nickname: string;
17
17
  /** @internal */ clid: number;
18
+ /**
19
+ * The UID hash the connected server uses, learned from `virtualserver_version`
20
+ * during initserver. TS3 hashes the public key with SHA-1 and TS6 with
21
+ * SHA-256, so anything comparing our UID to the server's needs this.
22
+ */
23
+ /** @internal */ uidAlgorithm: UidAlgorithm;
18
24
  constructor(identity: Identity, addr: string, nickname: string, options?: ClientOptions);
19
25
  get status(): ClientStatus;
20
26
  /** @internal */
@@ -33,6 +39,15 @@ export declare class Client {
33
39
  useCommandMiddleware(...mw: CommandMiddleware[]): this;
34
40
  useEventMiddleware(...mw: EventMiddleware[]): this;
35
41
  clientID(): number;
42
+ /**
43
+ * Our own `client_unique_identifier`, hashed with the algorithm the connected
44
+ * server uses.
45
+ *
46
+ * TS3 uses SHA-1 and TS6 SHA-256, so this reads the algorithm learned during
47
+ * initserver rather than assuming one. Comparing a hard-coded SHA-1 UID to a
48
+ * TS6 server silently never matches.
49
+ */
50
+ uniqueIdentifier(): string;
36
51
  channelID(): bigint;
37
52
  /** Send Opus voice directly to specific clients, bypassing channel routing. */
38
53
  sendWhisper(data: Uint8Array, targetClientIds: number[], codec: number): void;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../command-DAK4pUBP.cjs"),t=require("../parser-CL33R9tr.cjs");exports.buildCommand=e.t,exports.buildCommandOrdered=e.n,exports.escape=e.r,exports.parseCommand=t.t,exports.unescape=e.i;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../command-DAK4pUBP.cjs"),t=require("../parser-BfwYH2fT.cjs");exports.buildCommand=e.t,exports.buildCommandOrdered=e.n,exports.escape=e.r,exports.parseCommand=t.t,exports.unescape=e.i;
@@ -1,3 +1,3 @@
1
1
  import { i as e, n as t, r as n, t as r } from "../command-BLe-C2L2.js";
2
- import { t as i } from "../parser-DZMv3Jm-.js";
2
+ import { t as i } from "../parser-BX8NEiBe.js";
3
3
  export { r as buildCommand, t as buildCommandOrdered, n as escape, i as parseCommand, e as unescape };
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/command/parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAoCtD"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/command/parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CA6CtD"}
@@ -1,4 +1,4 @@
1
- import { a as e, c as t, f as n, i as r, m as i, n as a, s as o, t as s } from "./primitives-xIr6Tjk4.js";
1
+ import { a as e, c as t, f as n, i as r, m as i, n as a, s as o, t as s } from "./primitives-CdX74Rgu.js";
2
2
  //#region src/handshake/license.ts
3
3
  var c = new Uint8Array([
4
4
  205,
@@ -155,4 +155,4 @@ function h(e, t, n, a, s, c) {
155
155
  //#endregion
156
156
  export { l as n, u as r, h as t };
157
157
 
158
- //# sourceMappingURL=crypt-init2-D70ha4LB.js.map
158
+ //# sourceMappingURL=crypt-init2-BcGT--df.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypt-init2-D70ha4LB.js","names":["scalarMultFull","ed25519","hash512","getSharedSecret2","importPublicKey","clampScalar","verifySign","bytesToBigIntLE","LICENSE_ROOT_KEY","LicenseChain","blocks","round","block","deriveKeyFromBlock","parseLicenses","data","remaining","parseLicenseBlock","consumed","blockType","UNIX_OFFSET","view","notValidBefore","notValidAfter","key","parseBlockPayload","allLen","payloadRead","hashInput","hashFull","payload","readNullString","str","read","propCount","pos","properties","i","propLen","minBlockLen","scalarBytes","scalar","negPub","negPar","parent","raw","final","cryptoInit2","crypt","licenseBytes","license","omegaBytes","omega","proofBytes","proof","betaBytes","beta","serverPubKey","sharedSecret","privateKey"],"sources":["../src/handshake/license.ts","../src/handshake/crypt-init2.ts"],"sourcesContent":["import { hash512 } from \"../crypto/identity.js\";\nimport { clampScalar, scalarMultFull, bytesToBigIntLE } from \"../crypto/primitives.js\";\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\n\n// The root key is a 33-byte Ed25519 point\nconst LICENSE_ROOT_KEY = new Uint8Array([\n 0xcd, 0x0d, 0xe2, 0xae, 0xd4, 0x63, 0x45, 0x50, 0x9a, 0x7e, 0x3c, 0xfd, 0x8f, 0x68, 0xb3, 0xdc,\n 0x75, 0x55, 0xb2, 0x9d, 0xcc, 0xec, 0x73, 0xcd, 0x18, 0x75, 0x0f, 0x99, 0x38, 0x12, 0x40, 0x8a,\n]);\n\nconst enum LicenseBlockType {\n Intermediate = 0,\n Server = 2,\n Ts5Server = 8,\n Ephemeral = 32,\n}\n\ninterface LicenseBlock {\n readonly key: Uint8Array; // 32-byte Ed25519 point\n readonly hash: Uint8Array; // SHA-512 truncated to 32 bytes\n properties: Uint8Array[];\n issuer: string;\n notValidBefore: Date;\n notValidAfter: Date;\n blockType: LicenseBlockType;\n serverType: number;\n}\n\nexport class LicenseChain {\n readonly blocks: LicenseBlock[];\n\n constructor(blocks: LicenseBlock[]) {\n this.blocks = blocks;\n }\n\n /**\n * Derive the session key by chaining Ed25519 point arithmetic starting from\n * the root key through each license block.\n */\n deriveKey(): Uint8Array<ArrayBuffer> {\n let round: Uint8Array<ArrayBuffer> = Uint8Array.from(LICENSE_ROOT_KEY);\n for (const block of this.blocks) {\n round = deriveKeyFromBlock(block, round);\n }\n return round;\n }\n}\n\nexport function parseLicenses(data: Uint8Array): LicenseChain {\n if (data.length < 1) throw new Error(\"license too short\");\n if (data[0] !== 1) throw new Error(\"unsupported license version\");\n\n let remaining = data.slice(1);\n const blocks: LicenseBlock[] = [];\n\n while (remaining.length > 0) {\n const { block, consumed } = parseLicenseBlock(remaining);\n blocks.push(block);\n remaining = remaining.slice(consumed);\n }\n\n return new LicenseChain(blocks);\n}\n\nfunction parseLicenseBlock(data: Uint8Array): { block: LicenseBlock; consumed: number } {\n const MIN_BLOCK_LEN = 42;\n if (data.length < MIN_BLOCK_LEN) throw new Error(\"license too short\");\n if (data[0] !== 0) throw new Error(`wrong key kind in license: ${data[0]}`);\n\n const blockType = data[33] as LicenseBlockType;\n\n // Timestamps are seconds since Unix epoch offset by 0x50e22700\n const UNIX_OFFSET = 0x50e22700;\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const notValidBefore = new Date((view.getUint32(34, false) + UNIX_OFFSET) * 1000);\n const notValidAfter = new Date((view.getUint32(38, false) + UNIX_OFFSET) * 1000);\n\n if (notValidAfter < notValidBefore) {\n throw new Error(\"license times are invalid\");\n }\n\n const key = Uint8Array.from(data.slice(1, 33));\n\n const { payload, payloadRead } = parseBlockPayload(blockType, data, MIN_BLOCK_LEN);\n\n const allLen = MIN_BLOCK_LEN + payloadRead;\n const hashInput = data.slice(1, allLen);\n const hashFull = hash512(Uint8Array.from(hashInput));\n const hash = Uint8Array.from(hashFull.slice(0, 32));\n\n return {\n block: {\n key,\n hash,\n properties: payload.properties,\n issuer: payload.issuer,\n notValidBefore,\n notValidAfter,\n blockType,\n serverType: payload.serverType,\n },\n consumed: allLen,\n };\n}\n\ninterface BlockPayload {\n issuer: string;\n serverType: number;\n properties: Uint8Array[];\n read: number;\n}\n\nfunction parseBlockPayload(\n blockType: LicenseBlockType,\n data: Uint8Array,\n minBlockLen: number,\n): { payload: BlockPayload; payloadRead: number } {\n switch (blockType) {\n case LicenseBlockType.Intermediate: {\n const { str, read } = readNullString(data.slice(46));\n return {\n payload: { issuer: str, serverType: 0, properties: [], read: 5 + read },\n payloadRead: 5 + read,\n };\n }\n case LicenseBlockType.Server: {\n const { str, read } = readNullString(data.slice(47));\n return {\n payload: { issuer: str, serverType: data[42] ?? 0, properties: [], read: 6 + read },\n payloadRead: 6 + read,\n };\n }\n case LicenseBlockType.Ts5Server: {\n const propCount = data[43] !== undefined ? data[43] : 0;\n let pos = 44;\n const properties: Uint8Array[] = [];\n for (let i = 0; i < propCount; i++) {\n if (pos >= data.length) throw new Error(\"license too short\");\n const propLen = data[pos++]!;\n if (pos + propLen > data.length) throw new Error(\"license too short\");\n properties.push(Uint8Array.from(data.slice(pos, pos + propLen)));\n pos += propLen;\n }\n return {\n payload: { issuer: \"\", serverType: data[42] ?? 0, properties, read: pos - minBlockLen },\n payloadRead: pos - minBlockLen,\n };\n }\n case LicenseBlockType.Ephemeral:\n return { payload: { issuer: \"\", serverType: 0, properties: [], read: 0 }, payloadRead: 0 };\n default:\n throw new Error(`invalid license block type: ${blockType}`);\n }\n}\n\n/**\n * Scan for a null-terminated string and return its content and the index\n * of the null byte (NOT including it in the count, matching Go behaviour).\n * The parent formulas (`5 + read`, `6 + read`) already add 1 for the null.\n */\nfunction readNullString(data: Uint8Array): { str: string; read: number } {\n for (let i = 0; i < data.length; i++) {\n if (data[i] === 0) {\n return { str: new TextDecoder().decode(data.slice(0, i)), read: i };\n }\n }\n throw new Error(\"non-null-terminated issuer string\");\n}\n\n/**\n * Derive the next key given a parent key and a license block.\n * Mirrors Go's licenseBlock.deriveKey.\n */\nfunction deriveKeyFromBlock(block: LicenseBlock, parent: Uint8Array): Uint8Array<ArrayBuffer> {\n const scalarBytes = Uint8Array.from(block.hash);\n clampScalar(scalarBytes);\n\n // Use raw scalar WITHOUT reducing mod n — NaCl's ge_scalarmult_vartime\n // uses the raw 256-bit scalar. Reducing mod n changes the result when\n // the point has a small-order component (Ed25519 cofactor = 8).\n const scalar = bytesToBigIntLE(scalarBytes);\n\n const pub = ed25519.Point.fromBytes(block.key);\n const negPub = pub.negate();\n\n const par = ed25519.Point.fromBytes(parent);\n const negPar = par.negate();\n\n const res = scalarMultFull(negPub, scalar).add(negPar);\n const raw = res.toBytes();\n const final = new Uint8Array(raw.length) as Uint8Array<ArrayBuffer>;\n final.set(raw);\n final[31] = (final[31] !== undefined ? final[31] : 0) ^ 0x80;\n\n return final;\n}\n","import type { Crypt } from \"../crypto/crypt.js\";\nimport { importPublicKey } from \"../crypto/identity.js\";\nimport { verifySign, getSharedSecret2 } from \"../crypto/primitives.js\";\nimport { parseLicenses } from \"./license.js\";\n\n/**\n * CryptoInit2 performs the second stage of crypto initialization (Ed25519 ECDH).\n * Mirrors Go's handshake.CryptoInit2.\n */\nexport function cryptoInit2(\n crypt: Crypt,\n license: string,\n omega: string,\n proof: string,\n beta: string,\n privateKey: Uint8Array,\n): void {\n if (crypt.alphaTmp.length === 0) {\n throw new Error(\"alpha is not initialized\");\n }\n\n const licenseBytes = Buffer.from(license, \"base64\");\n const omegaBytes = Buffer.from(omega, \"base64\");\n const proofBytes = Buffer.from(proof, \"base64\");\n const betaBytes = Buffer.from(beta, \"base64\");\n\n const serverPubKey = importPublicKey(omegaBytes);\n if (!verifySign(serverPubKey, licenseBytes, proofBytes)) {\n throw new Error(\"init proof is not valid\");\n }\n\n const licenses = parseLicenses(licenseBytes);\n const key = licenses.deriveKey();\n\n const sharedSecret = getSharedSecret2(key, privateKey);\n\n crypt.setSharedSecret(crypt.alphaTmp, betaBytes, sharedSecret);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"crypt-init2-BcGT--df.js","names":["scalarMultFull","ed25519","hash512","getSharedSecret2","importPublicKey","clampScalar","verifySign","bytesToBigIntLE","LICENSE_ROOT_KEY","LicenseChain","blocks","round","block","deriveKeyFromBlock","parseLicenses","data","remaining","parseLicenseBlock","consumed","blockType","UNIX_OFFSET","view","notValidBefore","notValidAfter","key","parseBlockPayload","allLen","payloadRead","hashInput","hashFull","payload","readNullString","str","read","propCount","pos","properties","i","propLen","minBlockLen","scalarBytes","scalar","negPub","negPar","parent","raw","final","cryptoInit2","crypt","licenseBytes","license","omegaBytes","omega","proofBytes","proof","betaBytes","beta","serverPubKey","sharedSecret","privateKey"],"sources":["../src/handshake/license.ts","../src/handshake/crypt-init2.ts"],"sourcesContent":["import { hash512 } from \"../crypto/identity.js\";\nimport { clampScalar, scalarMultFull, bytesToBigIntLE } from \"../crypto/primitives.js\";\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\n\n// The root key is a 33-byte Ed25519 point\nconst LICENSE_ROOT_KEY = new Uint8Array([\n 0xcd, 0x0d, 0xe2, 0xae, 0xd4, 0x63, 0x45, 0x50, 0x9a, 0x7e, 0x3c, 0xfd, 0x8f, 0x68, 0xb3, 0xdc,\n 0x75, 0x55, 0xb2, 0x9d, 0xcc, 0xec, 0x73, 0xcd, 0x18, 0x75, 0x0f, 0x99, 0x38, 0x12, 0x40, 0x8a,\n]);\n\nconst enum LicenseBlockType {\n Intermediate = 0,\n Server = 2,\n Ts5Server = 8,\n Ephemeral = 32,\n}\n\ninterface LicenseBlock {\n readonly key: Uint8Array; // 32-byte Ed25519 point\n readonly hash: Uint8Array; // SHA-512 truncated to 32 bytes\n properties: Uint8Array[];\n issuer: string;\n notValidBefore: Date;\n notValidAfter: Date;\n blockType: LicenseBlockType;\n serverType: number;\n}\n\nexport class LicenseChain {\n readonly blocks: LicenseBlock[];\n\n constructor(blocks: LicenseBlock[]) {\n this.blocks = blocks;\n }\n\n /**\n * Derive the session key by chaining Ed25519 point arithmetic starting from\n * the root key through each license block.\n */\n deriveKey(): Uint8Array<ArrayBuffer> {\n let round: Uint8Array<ArrayBuffer> = Uint8Array.from(LICENSE_ROOT_KEY);\n for (const block of this.blocks) {\n round = deriveKeyFromBlock(block, round);\n }\n return round;\n }\n}\n\nexport function parseLicenses(data: Uint8Array): LicenseChain {\n if (data.length < 1) throw new Error(\"license too short\");\n if (data[0] !== 1) throw new Error(\"unsupported license version\");\n\n let remaining = data.slice(1);\n const blocks: LicenseBlock[] = [];\n\n while (remaining.length > 0) {\n const { block, consumed } = parseLicenseBlock(remaining);\n blocks.push(block);\n remaining = remaining.slice(consumed);\n }\n\n return new LicenseChain(blocks);\n}\n\nfunction parseLicenseBlock(data: Uint8Array): { block: LicenseBlock; consumed: number } {\n const MIN_BLOCK_LEN = 42;\n if (data.length < MIN_BLOCK_LEN) throw new Error(\"license too short\");\n if (data[0] !== 0) throw new Error(`wrong key kind in license: ${data[0]}`);\n\n const blockType = data[33] as LicenseBlockType;\n\n // Timestamps are seconds since Unix epoch offset by 0x50e22700\n const UNIX_OFFSET = 0x50e22700;\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const notValidBefore = new Date((view.getUint32(34, false) + UNIX_OFFSET) * 1000);\n const notValidAfter = new Date((view.getUint32(38, false) + UNIX_OFFSET) * 1000);\n\n if (notValidAfter < notValidBefore) {\n throw new Error(\"license times are invalid\");\n }\n\n const key = Uint8Array.from(data.slice(1, 33));\n\n const { payload, payloadRead } = parseBlockPayload(blockType, data, MIN_BLOCK_LEN);\n\n const allLen = MIN_BLOCK_LEN + payloadRead;\n const hashInput = data.slice(1, allLen);\n const hashFull = hash512(Uint8Array.from(hashInput));\n const hash = Uint8Array.from(hashFull.slice(0, 32));\n\n return {\n block: {\n key,\n hash,\n properties: payload.properties,\n issuer: payload.issuer,\n notValidBefore,\n notValidAfter,\n blockType,\n serverType: payload.serverType,\n },\n consumed: allLen,\n };\n}\n\ninterface BlockPayload {\n issuer: string;\n serverType: number;\n properties: Uint8Array[];\n read: number;\n}\n\nfunction parseBlockPayload(\n blockType: LicenseBlockType,\n data: Uint8Array,\n minBlockLen: number,\n): { payload: BlockPayload; payloadRead: number } {\n switch (blockType) {\n case LicenseBlockType.Intermediate: {\n const { str, read } = readNullString(data.slice(46));\n return {\n payload: { issuer: str, serverType: 0, properties: [], read: 5 + read },\n payloadRead: 5 + read,\n };\n }\n case LicenseBlockType.Server: {\n const { str, read } = readNullString(data.slice(47));\n return {\n payload: { issuer: str, serverType: data[42] ?? 0, properties: [], read: 6 + read },\n payloadRead: 6 + read,\n };\n }\n case LicenseBlockType.Ts5Server: {\n const propCount = data[43] !== undefined ? data[43] : 0;\n let pos = 44;\n const properties: Uint8Array[] = [];\n for (let i = 0; i < propCount; i++) {\n if (pos >= data.length) throw new Error(\"license too short\");\n const propLen = data[pos++]!;\n if (pos + propLen > data.length) throw new Error(\"license too short\");\n properties.push(Uint8Array.from(data.slice(pos, pos + propLen)));\n pos += propLen;\n }\n return {\n payload: { issuer: \"\", serverType: data[42] ?? 0, properties, read: pos - minBlockLen },\n payloadRead: pos - minBlockLen,\n };\n }\n case LicenseBlockType.Ephemeral:\n return { payload: { issuer: \"\", serverType: 0, properties: [], read: 0 }, payloadRead: 0 };\n default:\n throw new Error(`invalid license block type: ${blockType}`);\n }\n}\n\n/**\n * Scan for a null-terminated string and return its content and the index\n * of the null byte (NOT including it in the count, matching Go behaviour).\n * The parent formulas (`5 + read`, `6 + read`) already add 1 for the null.\n */\nfunction readNullString(data: Uint8Array): { str: string; read: number } {\n for (let i = 0; i < data.length; i++) {\n if (data[i] === 0) {\n return { str: new TextDecoder().decode(data.slice(0, i)), read: i };\n }\n }\n throw new Error(\"non-null-terminated issuer string\");\n}\n\n/**\n * Derive the next key given a parent key and a license block.\n * Mirrors Go's licenseBlock.deriveKey.\n */\nfunction deriveKeyFromBlock(block: LicenseBlock, parent: Uint8Array): Uint8Array<ArrayBuffer> {\n const scalarBytes = Uint8Array.from(block.hash);\n clampScalar(scalarBytes);\n\n // Use raw scalar WITHOUT reducing mod n — NaCl's ge_scalarmult_vartime\n // uses the raw 256-bit scalar. Reducing mod n changes the result when\n // the point has a small-order component (Ed25519 cofactor = 8).\n const scalar = bytesToBigIntLE(scalarBytes);\n\n const pub = ed25519.Point.fromBytes(block.key);\n const negPub = pub.negate();\n\n const par = ed25519.Point.fromBytes(parent);\n const negPar = par.negate();\n\n const res = scalarMultFull(negPub, scalar).add(negPar);\n const raw = res.toBytes();\n const final = new Uint8Array(raw.length) as Uint8Array<ArrayBuffer>;\n final.set(raw);\n final[31] = (final[31] !== undefined ? final[31] : 0) ^ 0x80;\n\n return final;\n}\n","import type { Crypt } from \"../crypto/crypt.js\";\nimport { importPublicKey } from \"../crypto/identity.js\";\nimport { verifySign, getSharedSecret2 } from \"../crypto/primitives.js\";\nimport { parseLicenses } from \"./license.js\";\n\n/**\n * CryptoInit2 performs the second stage of crypto initialization (Ed25519 ECDH).\n * Mirrors Go's handshake.CryptoInit2.\n */\nexport function cryptoInit2(\n crypt: Crypt,\n license: string,\n omega: string,\n proof: string,\n beta: string,\n privateKey: Uint8Array,\n): void {\n if (crypt.alphaTmp.length === 0) {\n throw new Error(\"alpha is not initialized\");\n }\n\n const licenseBytes = Buffer.from(license, \"base64\");\n const omegaBytes = Buffer.from(omega, \"base64\");\n const proofBytes = Buffer.from(proof, \"base64\");\n const betaBytes = Buffer.from(beta, \"base64\");\n\n const serverPubKey = importPublicKey(omegaBytes);\n if (!verifySign(serverPubKey, licenseBytes, proofBytes)) {\n throw new Error(\"init proof is not valid\");\n }\n\n const licenses = parseLicenses(licenseBytes);\n const key = licenses.deriveKey();\n\n const sharedSecret = getSharedSecret2(key, privateKey);\n\n crypt.setSharedSecret(crypt.alphaTmp, betaBytes, sharedSecret);\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("./primitives-cNNAeFCo.cjs");var t=new Uint8Array([205,13,226,174,212,99,69,80,154,126,60,253,143,104,179,220,117,85,178,157,204,236,115,205,24,117,15,153,56,18,64,138]),n=class{blocks;constructor(e){this.blocks=e}deriveKey(){let e=Uint8Array.from(t);for(let t of this.blocks)e=s(t,e);return e}};function r(e){if(e.length<1)throw Error(`license too short`);if(e[0]!==1)throw Error(`unsupported license version`);let t=e.slice(1),r=[];for(;t.length>0;){let{block:e,consumed:n}=i(t);r.push(e),t=t.slice(n)}return new n(r)}function i(t){if(t.length<42)throw Error(`license too short`);if(t[0]!==0)throw Error(`wrong key kind in license: ${t[0]}`);let n=t[33],r=1356998400,i=new DataView(t.buffer,t.byteOffset,t.byteLength),o=new Date((i.getUint32(34,!1)+r)*1e3),s=new Date((i.getUint32(38,!1)+r)*1e3);if(s<o)throw Error(`license times are invalid`);let c=Uint8Array.from(t.slice(1,33)),{payload:l,payloadRead:u}=a(n,t,42),d=42+u,f=t.slice(1,d),p=e.f(Uint8Array.from(f));return{block:{key:c,hash:Uint8Array.from(p.slice(0,32)),properties:l.properties,issuer:l.issuer,notValidBefore:o,notValidAfter:s,blockType:n,serverType:l.serverType},consumed:d}}function a(e,t,n){switch(e){case 0:{let{str:e,read:n}=o(t.slice(46));return{payload:{issuer:e,serverType:0,properties:[],read:5+n},payloadRead:5+n}}case 2:{let{str:e,read:n}=o(t.slice(47));return{payload:{issuer:e,serverType:t[42]??0,properties:[],read:6+n},payloadRead:6+n}}case 8:{let e=t[43]===void 0?0:t[43],r=44,i=[];for(let n=0;n<e;n++){if(r>=t.length)throw Error(`license too short`);let e=t[r++];if(r+e>t.length)throw Error(`license too short`);i.push(Uint8Array.from(t.slice(r,r+e))),r+=e}return{payload:{issuer:``,serverType:t[42]??0,properties:i,read:r-n},payloadRead:r-n}}case 32:return{payload:{issuer:``,serverType:0,properties:[],read:0},payloadRead:0};default:throw Error(`invalid license block type: ${e}`)}}function o(e){for(let t=0;t<e.length;t++)if(e[t]===0)return{str:new TextDecoder().decode(e.slice(0,t)),read:t};throw Error(`non-null-terminated issuer string`)}function s(t,n){let r=Uint8Array.from(t.hash);e.n(r);let i=e.t(r),a=e.c.Point.fromBytes(t.key).negate(),o=e.c.Point.fromBytes(n).negate(),s=e.a(a,i).add(o).toBytes(),c=new Uint8Array(s.length);return c.set(s),c[31]=(c[31]===void 0?0:c[31])^128,c}function c(t,n,i,a,o,s){if(t.alphaTmp.length===0)throw Error(`alpha is not initialized`);let c=Buffer.from(n,`base64`),l=Buffer.from(i,`base64`),u=Buffer.from(a,`base64`),d=Buffer.from(o,`base64`),f=e.m(l);if(!e.s(f,c,u))throw Error(`init proof is not valid`);let p=r(c).deriveKey(),m=e.i(p,s);t.setSharedSecret(t.alphaTmp,d,m)}Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return c}});
2
- //# sourceMappingURL=crypt-init2-DparLekm.cjs.map
1
+ const e=require("./primitives-DkwW7wcP.cjs");var t=new Uint8Array([205,13,226,174,212,99,69,80,154,126,60,253,143,104,179,220,117,85,178,157,204,236,115,205,24,117,15,153,56,18,64,138]),n=class{blocks;constructor(e){this.blocks=e}deriveKey(){let e=Uint8Array.from(t);for(let t of this.blocks)e=s(t,e);return e}};function r(e){if(e.length<1)throw Error(`license too short`);if(e[0]!==1)throw Error(`unsupported license version`);let t=e.slice(1),r=[];for(;t.length>0;){let{block:e,consumed:n}=i(t);r.push(e),t=t.slice(n)}return new n(r)}function i(t){if(t.length<42)throw Error(`license too short`);if(t[0]!==0)throw Error(`wrong key kind in license: ${t[0]}`);let n=t[33],r=1356998400,i=new DataView(t.buffer,t.byteOffset,t.byteLength),o=new Date((i.getUint32(34,!1)+r)*1e3),s=new Date((i.getUint32(38,!1)+r)*1e3);if(s<o)throw Error(`license times are invalid`);let c=Uint8Array.from(t.slice(1,33)),{payload:l,payloadRead:u}=a(n,t,42),d=42+u,f=t.slice(1,d),p=e.f(Uint8Array.from(f));return{block:{key:c,hash:Uint8Array.from(p.slice(0,32)),properties:l.properties,issuer:l.issuer,notValidBefore:o,notValidAfter:s,blockType:n,serverType:l.serverType},consumed:d}}function a(e,t,n){switch(e){case 0:{let{str:e,read:n}=o(t.slice(46));return{payload:{issuer:e,serverType:0,properties:[],read:5+n},payloadRead:5+n}}case 2:{let{str:e,read:n}=o(t.slice(47));return{payload:{issuer:e,serverType:t[42]??0,properties:[],read:6+n},payloadRead:6+n}}case 8:{let e=t[43]===void 0?0:t[43],r=44,i=[];for(let n=0;n<e;n++){if(r>=t.length)throw Error(`license too short`);let e=t[r++];if(r+e>t.length)throw Error(`license too short`);i.push(Uint8Array.from(t.slice(r,r+e))),r+=e}return{payload:{issuer:``,serverType:t[42]??0,properties:i,read:r-n},payloadRead:r-n}}case 32:return{payload:{issuer:``,serverType:0,properties:[],read:0},payloadRead:0};default:throw Error(`invalid license block type: ${e}`)}}function o(e){for(let t=0;t<e.length;t++)if(e[t]===0)return{str:new TextDecoder().decode(e.slice(0,t)),read:t};throw Error(`non-null-terminated issuer string`)}function s(t,n){let r=Uint8Array.from(t.hash);e.n(r);let i=e.t(r),a=e.c.Point.fromBytes(t.key).negate(),o=e.c.Point.fromBytes(n).negate(),s=e.a(a,i).add(o).toBytes(),c=new Uint8Array(s.length);return c.set(s),c[31]=(c[31]===void 0?0:c[31])^128,c}function c(t,n,i,a,o,s){if(t.alphaTmp.length===0)throw Error(`alpha is not initialized`);let c=Buffer.from(n,`base64`),l=Buffer.from(i,`base64`),u=Buffer.from(a,`base64`),d=Buffer.from(o,`base64`),f=e.m(l);if(!e.s(f,c,u))throw Error(`init proof is not valid`);let p=r(c).deriveKey(),m=e.i(p,s);t.setSharedSecret(t.alphaTmp,d,m)}Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return c}});
2
+ //# sourceMappingURL=crypt-init2-Bkee1YxV.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypt-init2-DparLekm.cjs","names":["hash512","bytesToBigIntLE","ed25519","scalarMultFull","importPublicKey","verifySign","getSharedSecret2","require_primitives","LICENSE_ROOT_KEY","LicenseChain","blocks","round","block","deriveKeyFromBlock","parseLicenses","data","remaining","parseLicenseBlock","consumed","blockType","UNIX_OFFSET","view","notValidBefore","notValidAfter","key","parseBlockPayload","allLen","payloadRead","hashInput","hashFull","payload","readNullString","str","read","propCount","pos","properties","i","propLen","minBlockLen","scalarBytes","scalar","negPub","negPar","parent","raw","final","cryptoInit2","crypt","licenseBytes","license","omegaBytes","omega","proofBytes","proof","betaBytes","beta","serverPubKey","sharedSecret","privateKey"],"sources":["../src/handshake/license.ts","../src/handshake/crypt-init2.ts"],"sourcesContent":["import { hash512 } from \"../crypto/identity.js\";\nimport { clampScalar, scalarMultFull, bytesToBigIntLE } from \"../crypto/primitives.js\";\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\n\n// The root key is a 33-byte Ed25519 point\nconst LICENSE_ROOT_KEY = new Uint8Array([\n 0xcd, 0x0d, 0xe2, 0xae, 0xd4, 0x63, 0x45, 0x50, 0x9a, 0x7e, 0x3c, 0xfd, 0x8f, 0x68, 0xb3, 0xdc,\n 0x75, 0x55, 0xb2, 0x9d, 0xcc, 0xec, 0x73, 0xcd, 0x18, 0x75, 0x0f, 0x99, 0x38, 0x12, 0x40, 0x8a,\n]);\n\nconst enum LicenseBlockType {\n Intermediate = 0,\n Server = 2,\n Ts5Server = 8,\n Ephemeral = 32,\n}\n\ninterface LicenseBlock {\n readonly key: Uint8Array; // 32-byte Ed25519 point\n readonly hash: Uint8Array; // SHA-512 truncated to 32 bytes\n properties: Uint8Array[];\n issuer: string;\n notValidBefore: Date;\n notValidAfter: Date;\n blockType: LicenseBlockType;\n serverType: number;\n}\n\nexport class LicenseChain {\n readonly blocks: LicenseBlock[];\n\n constructor(blocks: LicenseBlock[]) {\n this.blocks = blocks;\n }\n\n /**\n * Derive the session key by chaining Ed25519 point arithmetic starting from\n * the root key through each license block.\n */\n deriveKey(): Uint8Array<ArrayBuffer> {\n let round: Uint8Array<ArrayBuffer> = Uint8Array.from(LICENSE_ROOT_KEY);\n for (const block of this.blocks) {\n round = deriveKeyFromBlock(block, round);\n }\n return round;\n }\n}\n\nexport function parseLicenses(data: Uint8Array): LicenseChain {\n if (data.length < 1) throw new Error(\"license too short\");\n if (data[0] !== 1) throw new Error(\"unsupported license version\");\n\n let remaining = data.slice(1);\n const blocks: LicenseBlock[] = [];\n\n while (remaining.length > 0) {\n const { block, consumed } = parseLicenseBlock(remaining);\n blocks.push(block);\n remaining = remaining.slice(consumed);\n }\n\n return new LicenseChain(blocks);\n}\n\nfunction parseLicenseBlock(data: Uint8Array): { block: LicenseBlock; consumed: number } {\n const MIN_BLOCK_LEN = 42;\n if (data.length < MIN_BLOCK_LEN) throw new Error(\"license too short\");\n if (data[0] !== 0) throw new Error(`wrong key kind in license: ${data[0]}`);\n\n const blockType = data[33] as LicenseBlockType;\n\n // Timestamps are seconds since Unix epoch offset by 0x50e22700\n const UNIX_OFFSET = 0x50e22700;\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const notValidBefore = new Date((view.getUint32(34, false) + UNIX_OFFSET) * 1000);\n const notValidAfter = new Date((view.getUint32(38, false) + UNIX_OFFSET) * 1000);\n\n if (notValidAfter < notValidBefore) {\n throw new Error(\"license times are invalid\");\n }\n\n const key = Uint8Array.from(data.slice(1, 33));\n\n const { payload, payloadRead } = parseBlockPayload(blockType, data, MIN_BLOCK_LEN);\n\n const allLen = MIN_BLOCK_LEN + payloadRead;\n const hashInput = data.slice(1, allLen);\n const hashFull = hash512(Uint8Array.from(hashInput));\n const hash = Uint8Array.from(hashFull.slice(0, 32));\n\n return {\n block: {\n key,\n hash,\n properties: payload.properties,\n issuer: payload.issuer,\n notValidBefore,\n notValidAfter,\n blockType,\n serverType: payload.serverType,\n },\n consumed: allLen,\n };\n}\n\ninterface BlockPayload {\n issuer: string;\n serverType: number;\n properties: Uint8Array[];\n read: number;\n}\n\nfunction parseBlockPayload(\n blockType: LicenseBlockType,\n data: Uint8Array,\n minBlockLen: number,\n): { payload: BlockPayload; payloadRead: number } {\n switch (blockType) {\n case LicenseBlockType.Intermediate: {\n const { str, read } = readNullString(data.slice(46));\n return {\n payload: { issuer: str, serverType: 0, properties: [], read: 5 + read },\n payloadRead: 5 + read,\n };\n }\n case LicenseBlockType.Server: {\n const { str, read } = readNullString(data.slice(47));\n return {\n payload: { issuer: str, serverType: data[42] ?? 0, properties: [], read: 6 + read },\n payloadRead: 6 + read,\n };\n }\n case LicenseBlockType.Ts5Server: {\n const propCount = data[43] !== undefined ? data[43] : 0;\n let pos = 44;\n const properties: Uint8Array[] = [];\n for (let i = 0; i < propCount; i++) {\n if (pos >= data.length) throw new Error(\"license too short\");\n const propLen = data[pos++]!;\n if (pos + propLen > data.length) throw new Error(\"license too short\");\n properties.push(Uint8Array.from(data.slice(pos, pos + propLen)));\n pos += propLen;\n }\n return {\n payload: { issuer: \"\", serverType: data[42] ?? 0, properties, read: pos - minBlockLen },\n payloadRead: pos - minBlockLen,\n };\n }\n case LicenseBlockType.Ephemeral:\n return { payload: { issuer: \"\", serverType: 0, properties: [], read: 0 }, payloadRead: 0 };\n default:\n throw new Error(`invalid license block type: ${blockType}`);\n }\n}\n\n/**\n * Scan for a null-terminated string and return its content and the index\n * of the null byte (NOT including it in the count, matching Go behaviour).\n * The parent formulas (`5 + read`, `6 + read`) already add 1 for the null.\n */\nfunction readNullString(data: Uint8Array): { str: string; read: number } {\n for (let i = 0; i < data.length; i++) {\n if (data[i] === 0) {\n return { str: new TextDecoder().decode(data.slice(0, i)), read: i };\n }\n }\n throw new Error(\"non-null-terminated issuer string\");\n}\n\n/**\n * Derive the next key given a parent key and a license block.\n * Mirrors Go's licenseBlock.deriveKey.\n */\nfunction deriveKeyFromBlock(block: LicenseBlock, parent: Uint8Array): Uint8Array<ArrayBuffer> {\n const scalarBytes = Uint8Array.from(block.hash);\n clampScalar(scalarBytes);\n\n // Use raw scalar WITHOUT reducing mod n — NaCl's ge_scalarmult_vartime\n // uses the raw 256-bit scalar. Reducing mod n changes the result when\n // the point has a small-order component (Ed25519 cofactor = 8).\n const scalar = bytesToBigIntLE(scalarBytes);\n\n const pub = ed25519.Point.fromBytes(block.key);\n const negPub = pub.negate();\n\n const par = ed25519.Point.fromBytes(parent);\n const negPar = par.negate();\n\n const res = scalarMultFull(negPub, scalar).add(negPar);\n const raw = res.toBytes();\n const final = new Uint8Array(raw.length) as Uint8Array<ArrayBuffer>;\n final.set(raw);\n final[31] = (final[31] !== undefined ? final[31] : 0) ^ 0x80;\n\n return final;\n}\n","import type { Crypt } from \"../crypto/crypt.js\";\nimport { importPublicKey } from \"../crypto/identity.js\";\nimport { verifySign, getSharedSecret2 } from \"../crypto/primitives.js\";\nimport { parseLicenses } from \"./license.js\";\n\n/**\n * CryptoInit2 performs the second stage of crypto initialization (Ed25519 ECDH).\n * Mirrors Go's handshake.CryptoInit2.\n */\nexport function cryptoInit2(\n crypt: Crypt,\n license: string,\n omega: string,\n proof: string,\n beta: string,\n privateKey: Uint8Array,\n): void {\n if (crypt.alphaTmp.length === 0) {\n throw new Error(\"alpha is not initialized\");\n }\n\n const licenseBytes = Buffer.from(license, \"base64\");\n const omegaBytes = Buffer.from(omega, \"base64\");\n const proofBytes = Buffer.from(proof, \"base64\");\n const betaBytes = Buffer.from(beta, \"base64\");\n\n const serverPubKey = importPublicKey(omegaBytes);\n if (!verifySign(serverPubKey, licenseBytes, proofBytes)) {\n throw new Error(\"init proof is not valid\");\n }\n\n const licenses = parseLicenses(licenseBytes);\n const key = licenses.deriveKey();\n\n const sharedSecret = getSharedSecret2(key, privateKey);\n\n crypt.setSharedSecret(crypt.alphaTmp, betaBytes, sharedSecret);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"crypt-init2-Bkee1YxV.cjs","names":["hash512","bytesToBigIntLE","ed25519","scalarMultFull","importPublicKey","verifySign","getSharedSecret2","require_primitives","LICENSE_ROOT_KEY","LicenseChain","blocks","round","block","deriveKeyFromBlock","parseLicenses","data","remaining","parseLicenseBlock","consumed","blockType","UNIX_OFFSET","view","notValidBefore","notValidAfter","key","parseBlockPayload","allLen","payloadRead","hashInput","hashFull","payload","readNullString","str","read","propCount","pos","properties","i","propLen","minBlockLen","scalarBytes","scalar","negPub","negPar","parent","raw","final","cryptoInit2","crypt","licenseBytes","license","omegaBytes","omega","proofBytes","proof","betaBytes","beta","serverPubKey","sharedSecret","privateKey"],"sources":["../src/handshake/license.ts","../src/handshake/crypt-init2.ts"],"sourcesContent":["import { hash512 } from \"../crypto/identity.js\";\nimport { clampScalar, scalarMultFull, bytesToBigIntLE } from \"../crypto/primitives.js\";\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\n\n// The root key is a 33-byte Ed25519 point\nconst LICENSE_ROOT_KEY = new Uint8Array([\n 0xcd, 0x0d, 0xe2, 0xae, 0xd4, 0x63, 0x45, 0x50, 0x9a, 0x7e, 0x3c, 0xfd, 0x8f, 0x68, 0xb3, 0xdc,\n 0x75, 0x55, 0xb2, 0x9d, 0xcc, 0xec, 0x73, 0xcd, 0x18, 0x75, 0x0f, 0x99, 0x38, 0x12, 0x40, 0x8a,\n]);\n\nconst enum LicenseBlockType {\n Intermediate = 0,\n Server = 2,\n Ts5Server = 8,\n Ephemeral = 32,\n}\n\ninterface LicenseBlock {\n readonly key: Uint8Array; // 32-byte Ed25519 point\n readonly hash: Uint8Array; // SHA-512 truncated to 32 bytes\n properties: Uint8Array[];\n issuer: string;\n notValidBefore: Date;\n notValidAfter: Date;\n blockType: LicenseBlockType;\n serverType: number;\n}\n\nexport class LicenseChain {\n readonly blocks: LicenseBlock[];\n\n constructor(blocks: LicenseBlock[]) {\n this.blocks = blocks;\n }\n\n /**\n * Derive the session key by chaining Ed25519 point arithmetic starting from\n * the root key through each license block.\n */\n deriveKey(): Uint8Array<ArrayBuffer> {\n let round: Uint8Array<ArrayBuffer> = Uint8Array.from(LICENSE_ROOT_KEY);\n for (const block of this.blocks) {\n round = deriveKeyFromBlock(block, round);\n }\n return round;\n }\n}\n\nexport function parseLicenses(data: Uint8Array): LicenseChain {\n if (data.length < 1) throw new Error(\"license too short\");\n if (data[0] !== 1) throw new Error(\"unsupported license version\");\n\n let remaining = data.slice(1);\n const blocks: LicenseBlock[] = [];\n\n while (remaining.length > 0) {\n const { block, consumed } = parseLicenseBlock(remaining);\n blocks.push(block);\n remaining = remaining.slice(consumed);\n }\n\n return new LicenseChain(blocks);\n}\n\nfunction parseLicenseBlock(data: Uint8Array): { block: LicenseBlock; consumed: number } {\n const MIN_BLOCK_LEN = 42;\n if (data.length < MIN_BLOCK_LEN) throw new Error(\"license too short\");\n if (data[0] !== 0) throw new Error(`wrong key kind in license: ${data[0]}`);\n\n const blockType = data[33] as LicenseBlockType;\n\n // Timestamps are seconds since Unix epoch offset by 0x50e22700\n const UNIX_OFFSET = 0x50e22700;\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const notValidBefore = new Date((view.getUint32(34, false) + UNIX_OFFSET) * 1000);\n const notValidAfter = new Date((view.getUint32(38, false) + UNIX_OFFSET) * 1000);\n\n if (notValidAfter < notValidBefore) {\n throw new Error(\"license times are invalid\");\n }\n\n const key = Uint8Array.from(data.slice(1, 33));\n\n const { payload, payloadRead } = parseBlockPayload(blockType, data, MIN_BLOCK_LEN);\n\n const allLen = MIN_BLOCK_LEN + payloadRead;\n const hashInput = data.slice(1, allLen);\n const hashFull = hash512(Uint8Array.from(hashInput));\n const hash = Uint8Array.from(hashFull.slice(0, 32));\n\n return {\n block: {\n key,\n hash,\n properties: payload.properties,\n issuer: payload.issuer,\n notValidBefore,\n notValidAfter,\n blockType,\n serverType: payload.serverType,\n },\n consumed: allLen,\n };\n}\n\ninterface BlockPayload {\n issuer: string;\n serverType: number;\n properties: Uint8Array[];\n read: number;\n}\n\nfunction parseBlockPayload(\n blockType: LicenseBlockType,\n data: Uint8Array,\n minBlockLen: number,\n): { payload: BlockPayload; payloadRead: number } {\n switch (blockType) {\n case LicenseBlockType.Intermediate: {\n const { str, read } = readNullString(data.slice(46));\n return {\n payload: { issuer: str, serverType: 0, properties: [], read: 5 + read },\n payloadRead: 5 + read,\n };\n }\n case LicenseBlockType.Server: {\n const { str, read } = readNullString(data.slice(47));\n return {\n payload: { issuer: str, serverType: data[42] ?? 0, properties: [], read: 6 + read },\n payloadRead: 6 + read,\n };\n }\n case LicenseBlockType.Ts5Server: {\n const propCount = data[43] !== undefined ? data[43] : 0;\n let pos = 44;\n const properties: Uint8Array[] = [];\n for (let i = 0; i < propCount; i++) {\n if (pos >= data.length) throw new Error(\"license too short\");\n const propLen = data[pos++]!;\n if (pos + propLen > data.length) throw new Error(\"license too short\");\n properties.push(Uint8Array.from(data.slice(pos, pos + propLen)));\n pos += propLen;\n }\n return {\n payload: { issuer: \"\", serverType: data[42] ?? 0, properties, read: pos - minBlockLen },\n payloadRead: pos - minBlockLen,\n };\n }\n case LicenseBlockType.Ephemeral:\n return { payload: { issuer: \"\", serverType: 0, properties: [], read: 0 }, payloadRead: 0 };\n default:\n throw new Error(`invalid license block type: ${blockType}`);\n }\n}\n\n/**\n * Scan for a null-terminated string and return its content and the index\n * of the null byte (NOT including it in the count, matching Go behaviour).\n * The parent formulas (`5 + read`, `6 + read`) already add 1 for the null.\n */\nfunction readNullString(data: Uint8Array): { str: string; read: number } {\n for (let i = 0; i < data.length; i++) {\n if (data[i] === 0) {\n return { str: new TextDecoder().decode(data.slice(0, i)), read: i };\n }\n }\n throw new Error(\"non-null-terminated issuer string\");\n}\n\n/**\n * Derive the next key given a parent key and a license block.\n * Mirrors Go's licenseBlock.deriveKey.\n */\nfunction deriveKeyFromBlock(block: LicenseBlock, parent: Uint8Array): Uint8Array<ArrayBuffer> {\n const scalarBytes = Uint8Array.from(block.hash);\n clampScalar(scalarBytes);\n\n // Use raw scalar WITHOUT reducing mod n — NaCl's ge_scalarmult_vartime\n // uses the raw 256-bit scalar. Reducing mod n changes the result when\n // the point has a small-order component (Ed25519 cofactor = 8).\n const scalar = bytesToBigIntLE(scalarBytes);\n\n const pub = ed25519.Point.fromBytes(block.key);\n const negPub = pub.negate();\n\n const par = ed25519.Point.fromBytes(parent);\n const negPar = par.negate();\n\n const res = scalarMultFull(negPub, scalar).add(negPar);\n const raw = res.toBytes();\n const final = new Uint8Array(raw.length) as Uint8Array<ArrayBuffer>;\n final.set(raw);\n final[31] = (final[31] !== undefined ? final[31] : 0) ^ 0x80;\n\n return final;\n}\n","import type { Crypt } from \"../crypto/crypt.js\";\nimport { importPublicKey } from \"../crypto/identity.js\";\nimport { verifySign, getSharedSecret2 } from \"../crypto/primitives.js\";\nimport { parseLicenses } from \"./license.js\";\n\n/**\n * CryptoInit2 performs the second stage of crypto initialization (Ed25519 ECDH).\n * Mirrors Go's handshake.CryptoInit2.\n */\nexport function cryptoInit2(\n crypt: Crypt,\n license: string,\n omega: string,\n proof: string,\n beta: string,\n privateKey: Uint8Array,\n): void {\n if (crypt.alphaTmp.length === 0) {\n throw new Error(\"alpha is not initialized\");\n }\n\n const licenseBytes = Buffer.from(license, \"base64\");\n const omegaBytes = Buffer.from(omega, \"base64\");\n const proofBytes = Buffer.from(proof, \"base64\");\n const betaBytes = Buffer.from(beta, \"base64\");\n\n const serverPubKey = importPublicKey(omegaBytes);\n if (!verifySign(serverPubKey, licenseBytes, proofBytes)) {\n throw new Error(\"init proof is not valid\");\n }\n\n const licenses = parseLicenses(licenseBytes);\n const key = licenses.deriveKey();\n\n const sharedSecret = getSharedSecret2(key, privateKey);\n\n crypt.setSharedSecret(crypt.alphaTmp, betaBytes, sharedSecret);\n}\n"],"mappings":"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"}
@@ -10,7 +10,19 @@ export declare class Identity {
10
10
  }
11
11
  export declare function identityFromString(s: string): Identity;
12
12
  export declare function generateIdentity(targetLevel: number): Identity;
13
- export declare function getUidFromPublicKey(publicKey: string): string;
13
+ /**
14
+ * The hash a server uses for `client_unique_identifier`, keyed by the server's
15
+ * major version.
16
+ *
17
+ * TeamSpeak 3 hashes the canonical public key with SHA-1 (20 bytes); TeamSpeak
18
+ * 6 switched to SHA-256 (32 bytes). The algorithm is not negotiable on the
19
+ * wire, so a client that guesses wrong computes a UID that matches nothing the
20
+ * server ever sends — self-identification by UID silently fails.
21
+ */
22
+ export type UidAlgorithm = "sha1" | "sha256";
23
+ /** Pick the UID hash from a `virtualserver_version` string, e.g. "6.0.0-beta13.1". */
24
+ export declare function uidAlgorithmForVersion(version: string): UidAlgorithm;
25
+ export declare function getUidFromPublicKey(publicKey: string, algorithm?: UidAlgorithm): string;
14
26
  export declare function hash512(data: Uint8Array): Uint8Array;
15
27
  /** Import a TS3 public key (canonical or legacy ASN.1 DER) and return the
16
28
  * uncompressed 65-byte point [0x04 || x || y]. */
@@ -1 +1 @@
1
- {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/crypto/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;AAOrB,qBAAa,QAAQ;IACnB,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAGhD;IAED,eAAe,IAAI,MAAM,CAiBxB;IAED,QAAQ,IAAI,MAAM,CAQjB;IAED,aAAa,IAAI,MAAM,CAKtB;IAEK,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAc7E;CACF;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ,CA+BtD;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAc9D;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAG7D;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAEpD;AA+BD;mDACmD;AACnD,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAS3D"}
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/crypto/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;AAOrB,qBAAa,QAAQ;IACnB,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAGhD;IAED,eAAe,IAAI,MAAM,CAiBxB;IAED,QAAQ,IAAI,MAAM,CAQjB;IAED,aAAa,IAAI,MAAM,CAKtB;IAEK,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAc7E;CACF;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ,CA+BtD;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAc9D;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7C,sFAAsF;AACtF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAGpE;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,GAAE,YAAqB,GAAG,MAAM,CAG/F;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAEpD;AA+BD;mDACmD;AACnD,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAS3D"}
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../primitives-cNNAeFCo.cjs"),t=require("../crypto-CDlweUL3.cjs");exports.Crypt=t.t,exports.EAX=t.n,exports.Identity=e.l,exports.aesCmac=t.r,exports.clampScalar=e.n,exports.generateIdentity=e.u,exports.generateTemporaryKey=e.r,exports.getSharedSecret2=e.i,exports.getUidFromPublicKey=e.d,exports.hash512=e.f,exports.identityFromString=e.p,exports.importPublicKey=e.m,exports.sign=e.o,exports.verifySign=e.s;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../primitives-DkwW7wcP.cjs"),t=require("../crypto-BfDd9DP6.cjs");exports.Crypt=t.t,exports.EAX=t.n,exports.Identity=e.l,exports.aesCmac=t.r,exports.clampScalar=e.n,exports.generateIdentity=e.u,exports.generateTemporaryKey=e.r,exports.getSharedSecret2=e.i,exports.getUidFromPublicKey=e.d,exports.hash512=e.f,exports.identityFromString=e.p,exports.importPublicKey=e.m,exports.sign=e.o,exports.uidAlgorithmForVersion=e.h,exports.verifySign=e.s;
@@ -1,4 +1,5 @@
1
- export { Identity, identityFromString, generateIdentity, getUidFromPublicKey, hash512, importPublicKey, } from "./identity.js";
1
+ export { Identity, identityFromString, generateIdentity, getUidFromPublicKey, uidAlgorithmForVersion, hash512, importPublicKey, } from "./identity.js";
2
+ export type { UidAlgorithm } from "./identity.js";
2
3
  export { Crypt } from "./crypt.js";
3
4
  export type { KeyNonce } from "./crypt.js";
4
5
  export { EAX, aesCmac } from "./eax.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/crypto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,OAAO,EACP,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EACL,oBAAoB,EACpB,IAAI,EACJ,UAAU,EACV,gBAAgB,EAChB,WAAW,GACZ,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/crypto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,EACtB,OAAO,EACP,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EACL,oBAAoB,EACpB,IAAI,EACJ,UAAU,EACV,gBAAgB,EAChB,WAAW,GACZ,MAAM,iBAAiB,CAAC"}
@@ -1,3 +1,3 @@
1
- import { d as e, f as t, i as n, l as r, m as i, n as a, o, p as s, r as c, s as l, u } from "../primitives-xIr6Tjk4.js";
2
- import { n as d, r as f, t as p } from "../crypto-Bg02m4ZE.js";
3
- export { p as Crypt, d as EAX, r as Identity, f as aesCmac, a as clampScalar, u as generateIdentity, c as generateTemporaryKey, n as getSharedSecret2, e as getUidFromPublicKey, t as hash512, s as identityFromString, i as importPublicKey, o as sign, l as verifySign };
1
+ import { d as e, f as t, h as n, i as r, l as i, m as a, n as o, o as s, p as c, r as l, s as u, u as d } from "../primitives-CdX74Rgu.js";
2
+ import { n as f, r as p, t as m } from "../crypto-DLV3oH5F.js";
3
+ export { m as Crypt, f as EAX, i as Identity, p as aesCmac, o as clampScalar, d as generateIdentity, l as generateTemporaryKey, r as getSharedSecret2, e as getUidFromPublicKey, t as hash512, c as identityFromString, a as importPublicKey, s as sign, n as uidAlgorithmForVersion, u as verifySign };
@@ -1,2 +1,2 @@
1
- const e=require("./primitives-cNNAeFCo.cjs");let t=require("node:crypto");var n=8,r=16,i=class{#e;constructor(e){if(e.length!==16)throw Error(`EAX requires a 16-byte key`);this.#e=e}encrypt(e,t,r){let i=this.#t(0,e),o=this.#t(1,t),s=a(this.#e,i,r),c=this.#t(2,s),l=new Uint8Array(n);for(let e=0;e<n;e++)l[e]=i[e]^o[e]^c[e];return[s,l]}decrypt(r,i,o,s){let c=this.#t(0,r),l=this.#t(1,i),u=this.#t(2,o),d=new Uint8Array(n);for(let e=0;e<n;e++)d[e]=c[e]^l[e]^u[e];if(!(0,t.timingSafeEqual)(Buffer.from(d),Buffer.from(s.slice(0,n))))throw new e.v;return a(this.#e,c,o)}#t(e,t){let n=new Uint8Array(r+t.length);return n[15]=e,n.set(t,r),d(this.#e,n)}};function a(e,n,r){let i=(0,t.createCipheriv)(`aes-128-ctr`,Buffer.from(e),Buffer.from(n));return Buffer.concat([i.update(Buffer.from(r)),i.final()])}function o(e,n){let r=(0,t.createCipheriv)(`aes-128-ecb`,Buffer.from(e),null);return r.setAutoPadding(!1),Buffer.concat([r.update(Buffer.from(n)),r.final()])}function s(e,t){let n=new Uint8Array(r);for(let i=0;i<r;i++)n[i]=e[i]^t[i];return n}function c(e){let t=new Uint8Array(r),n=0;for(let r=15;r>=0;r--){let i=(e[r]<<1|n)&255;n=e[r]>>7,t[r]=i}return t}var l=new Uint8Array(r);l[15]=135;function u(e){let t=o(e,new Uint8Array(r)),n=c(t);t[0]&128&&(n=s(n,l));let i=c(n);return n[0]&128&&(i=s(i,l)),[n,i]}function d(e,t){let[n,i]=u(e),a=Math.max(1,Math.ceil(t.length/r)),c=t.length>0&&t.length%r===0,l=new Uint8Array(r);for(let n=0;n<a-1;n++){let i=t.slice(n*r,(n+1)*r);l=Uint8Array.from(o(e,s(l,i)))}let d=new Uint8Array(r),f=(a-1)*r,p=t.slice(f);d.set(p);let m;return c?m=s(d,n):(p.length<r&&(d[p.length]=128),m=s(d,i)),Uint8Array.from(o(e,s(l,m)))}var f=8,p=10,m=8,h=15,g=Buffer.from(`TS3INIT1`),_=Buffer.from(`c:\\windows\\syste`),v=Buffer.from(`m\\firewall32.cpl`),y=class{identity;ivStruct=new Uint8Array;fakeSignature=new Uint8Array(f);alphaTmp=new Uint8Array;cryptoInitComplete=!1;#e=new Map;constructor(e){this.identity=e}solveRsaChallenge(e,t,n){if(n<0||n>1e6)throw Error(`RSA challenge level out of range`);let r=e.slice(t,t+64),i=e.slice(t+64,t+128),a=x(r),o=x(i);for(let e=0;e<n;e++)a=a*a%o;return S(a,64)}initCrypto(t,n,r){let i=Buffer.from(t,`base64`),a=Buffer.from(n,`base64`),o=Buffer.from(r,`base64`),s=e.m(o),c=this.#t(s);this.setSharedSecret(i,a,c)}setSharedSecret(e,n,r){this.ivStruct=new Uint8Array(p+n.length);for(let t=0;t<p;t++){let n=r[t],i=e[t];this.ivStruct[t]=((n===void 0?0:n)^(i===void 0?0:i))&255}for(let e=0;e<n.length;e++){let t=r[p+e],i=n[e];this.ivStruct[p+e]=((t===void 0?0:t)^(i===void 0?0:i))&255}let i=(0,t.createHash)(`sha1`).update(this.ivStruct).digest();this.fakeSignature=new Uint8Array(i.buffer,i.byteOffset,f),this.cryptoInitComplete=!0}getKeyNonce(e,n,r,i,a){if(a)return[Uint8Array.from(_),Uint8Array.from(v)];let o=b(e,i,r),s=this.#e.get(o);if(s===void 0){let n=new Uint8Array(6+this.ivStruct.length);n[0]=e?48:49,n[1]=i&h,new DataView(n.buffer).setUint32(2,r,!1),n.set(this.ivStruct,6);let a=(0,t.createHash)(`sha256`).update(n).digest();s={key:Uint8Array.from(a.slice(0,16)),nonce:Uint8Array.from(a.slice(16,32)),gen:r},this.#e.set(o,s)}let c=Uint8Array.from(s.key);return c[0]=(c[0]===void 0?0:c[0])^n>>8&255,c[1]=(c[1]===void 0?0:c[1])^n&255,[c,s.nonce]}encrypt(e,t,n,r,a,o,s){if(e===m)return[a,g];if(s)return[a,this.fakeSignature];let[c,l]=this.getKeyNonce(!1,t,n,e,o);return new i(c).encrypt(l,r,a)}decrypt(t,n,r,a,o,s,c,l){if(t===m)return o;if(l){let t=s.slice(0,f);if(!Buffer.from(t).equals(Buffer.from(this.fakeSignature)))throw new e.y;return o}let[u,d]=this.getKeyNonce(!0,n,r,t,c);return new i(u).decrypt(d,a,o,s)}#t(e){let n=this.identity.privateKey.export({format:`jwk`}),r=e.export({format:`jwk`}),i=(0,t.createECDH)(`prime256v1`),a=Buffer.from(n.d,`base64url`);i.setPrivateKey(a);let o=C(r.x,32),s=C(r.y,32),c=Buffer.alloc(65);c[0]=4,o.copy(c,1),s.copy(c,33);let l=i.computeSecret(c);return(0,t.createHash)(`sha1`).update(l).digest()}};function b(e,t,n){let r=0n;return e&&(r|=1n<<40n),r|=BigInt(t&h)<<32n,r|=BigInt(n),r}function x(e){let t=0n;for(let n of e)t=t<<8n|BigInt(n);return t}function S(e,t){let n=new Uint8Array(t),r=e;for(let e=t-1;e>=0;e--)n[e]=Number(r&255n),r>>=8n;return n}function C(e,t){let n=Buffer.from(e,`base64url`);if(n.length===t)return n;let r=Buffer.alloc(t);return n.copy(r,t-n.length),r}Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return y}});
2
- //# sourceMappingURL=crypto-CDlweUL3.cjs.map
1
+ const e=require("./primitives-DkwW7wcP.cjs");let t=require("node:crypto");var n=8,r=16,i=class{#e;constructor(e){if(e.length!==16)throw Error(`EAX requires a 16-byte key`);this.#e=e}encrypt(e,t,r){let i=this.#t(0,e),o=this.#t(1,t),s=a(this.#e,i,r),c=this.#t(2,s),l=new Uint8Array(n);for(let e=0;e<n;e++)l[e]=i[e]^o[e]^c[e];return[s,l]}decrypt(r,i,o,s){let c=this.#t(0,r),l=this.#t(1,i),u=this.#t(2,o),d=new Uint8Array(n);for(let e=0;e<n;e++)d[e]=c[e]^l[e]^u[e];if(!(0,t.timingSafeEqual)(Buffer.from(d),Buffer.from(s.slice(0,n))))throw new e.y;return a(this.#e,c,o)}#t(e,t){let n=new Uint8Array(r+t.length);return n[15]=e,n.set(t,r),d(this.#e,n)}};function a(e,n,r){let i=(0,t.createCipheriv)(`aes-128-ctr`,Buffer.from(e),Buffer.from(n));return Buffer.concat([i.update(Buffer.from(r)),i.final()])}function o(e,n){let r=(0,t.createCipheriv)(`aes-128-ecb`,Buffer.from(e),null);return r.setAutoPadding(!1),Buffer.concat([r.update(Buffer.from(n)),r.final()])}function s(e,t){let n=new Uint8Array(r);for(let i=0;i<r;i++)n[i]=e[i]^t[i];return n}function c(e){let t=new Uint8Array(r),n=0;for(let r=15;r>=0;r--){let i=(e[r]<<1|n)&255;n=e[r]>>7,t[r]=i}return t}var l=new Uint8Array(r);l[15]=135;function u(e){let t=o(e,new Uint8Array(r)),n=c(t);t[0]&128&&(n=s(n,l));let i=c(n);return n[0]&128&&(i=s(i,l)),[n,i]}function d(e,t){let[n,i]=u(e),a=Math.max(1,Math.ceil(t.length/r)),c=t.length>0&&t.length%r===0,l=new Uint8Array(r);for(let n=0;n<a-1;n++){let i=t.slice(n*r,(n+1)*r);l=Uint8Array.from(o(e,s(l,i)))}let d=new Uint8Array(r),f=(a-1)*r,p=t.slice(f);d.set(p);let m;return c?m=s(d,n):(p.length<r&&(d[p.length]=128),m=s(d,i)),Uint8Array.from(o(e,s(l,m)))}var f=8,p=10,m=8,h=15,g=Buffer.from(`TS3INIT1`),_=Buffer.from(`c:\\windows\\syste`),v=Buffer.from(`m\\firewall32.cpl`),y=class{identity;ivStruct=new Uint8Array;fakeSignature=new Uint8Array(f);alphaTmp=new Uint8Array;cryptoInitComplete=!1;#e=new Map;constructor(e){this.identity=e}solveRsaChallenge(e,t,n){if(n<0||n>1e6)throw Error(`RSA challenge level out of range`);let r=e.slice(t,t+64),i=e.slice(t+64,t+128),a=x(r),o=x(i);for(let e=0;e<n;e++)a=a*a%o;return S(a,64)}initCrypto(t,n,r){let i=Buffer.from(t,`base64`),a=Buffer.from(n,`base64`),o=Buffer.from(r,`base64`),s=e.m(o),c=this.#t(s);this.setSharedSecret(i,a,c)}setSharedSecret(e,n,r){this.ivStruct=new Uint8Array(p+n.length);for(let t=0;t<p;t++){let n=r[t],i=e[t];this.ivStruct[t]=((n===void 0?0:n)^(i===void 0?0:i))&255}for(let e=0;e<n.length;e++){let t=r[p+e],i=n[e];this.ivStruct[p+e]=((t===void 0?0:t)^(i===void 0?0:i))&255}let i=(0,t.createHash)(`sha1`).update(this.ivStruct).digest();this.fakeSignature=new Uint8Array(i.buffer,i.byteOffset,f),this.cryptoInitComplete=!0}getKeyNonce(e,n,r,i,a){if(a)return[Uint8Array.from(_),Uint8Array.from(v)];let o=b(e,i,r),s=this.#e.get(o);if(s===void 0){let n=new Uint8Array(6+this.ivStruct.length);n[0]=e?48:49,n[1]=i&h,new DataView(n.buffer).setUint32(2,r,!1),n.set(this.ivStruct,6);let a=(0,t.createHash)(`sha256`).update(n).digest();s={key:Uint8Array.from(a.slice(0,16)),nonce:Uint8Array.from(a.slice(16,32)),gen:r},this.#e.set(o,s)}let c=Uint8Array.from(s.key);return c[0]=(c[0]===void 0?0:c[0])^n>>8&255,c[1]=(c[1]===void 0?0:c[1])^n&255,[c,s.nonce]}encrypt(e,t,n,r,a,o,s){if(e===m)return[a,g];if(s)return[a,this.fakeSignature];let[c,l]=this.getKeyNonce(!1,t,n,e,o);return new i(c).encrypt(l,r,a)}decrypt(t,n,r,a,o,s,c,l){if(t===m)return o;if(l){let t=s.slice(0,f);if(!Buffer.from(t).equals(Buffer.from(this.fakeSignature)))throw new e.b;return o}let[u,d]=this.getKeyNonce(!0,n,r,t,c);return new i(u).decrypt(d,a,o,s)}#t(e){let n=this.identity.privateKey.export({format:`jwk`}),r=e.export({format:`jwk`}),i=(0,t.createECDH)(`prime256v1`),a=Buffer.from(n.d,`base64url`);i.setPrivateKey(a);let o=C(r.x,32),s=C(r.y,32),c=Buffer.alloc(65);c[0]=4,o.copy(c,1),s.copy(c,33);let l=i.computeSecret(c);return(0,t.createHash)(`sha1`).update(l).digest()}};function b(e,t,n){let r=0n;return e&&(r|=1n<<40n),r|=BigInt(t&h)<<32n,r|=BigInt(n),r}function x(e){let t=0n;for(let n of e)t=t<<8n|BigInt(n);return t}function S(e,t){let n=new Uint8Array(t),r=e;for(let e=t-1;e>=0;e--)n[e]=Number(r&255n),r>>=8n;return n}function C(e,t){let n=Buffer.from(e,`base64url`);if(n.length===t)return n;let r=Buffer.alloc(t);return n.copy(r,t-n.length),r}Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return y}});
2
+ //# sourceMappingURL=crypto-BfDd9DP6.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypto-CDlweUL3.cjs","names":["timingSafeEqual","EAXTagMismatchError","createCipheriv","importPublicKey","createHash","FakeSignatureMismatchError","createECDH","require_primitives","node_crypto","EAX_TAG_SIZE","EAX_BLOCK_SIZE","EAX","key","#key","nStar","#cmac","nonce","hStar","header","ciphertext","aesCtr","plaintext","cStar","tag","i","expected","input","data","tagByte","aesCmac","cipher","iv","aesEcb","block","xorBlock","out","a","b","shiftLeft1","carry","shifted","RB","generateSubkeys","L","K1","K2","n","message","lastBlockComplete","X","lastBlock","lastStart","lastSlice","Mn","FAKE_SIGNATURE_SIZE","IV_ALPHA_SIZE","INIT1_PACKET_TYPE","PACKET_TYPE_MASK","INIT1_MAC","DUMMY_KEY","DUMMY_NONCE","Crypt","identity","level","xBytes","offset","nBytes","y","bytesToBigInt","bigIntToBytes","alphaBytes","alpha","betaBytes","beta","omegaBytes","omega","serverPubKey","sharedSecret","#getSharedSecret","sharedKey","digest","dummy","cacheKey","makeCacheKey","fromServer","packetType","generationID","kn","#cachedKeys","tmpToHash","hash","packetID","unencrypted","fsSub","privJwk","pubJwk","ecdh","dBytes","base64UrlToBytes","yBytes","uncompressed","rawSecret","result","bytes","size","v","value","buf","b64url","padded"],"sources":["../src/crypto/eax.ts","../src/crypto/crypt.ts"],"sourcesContent":["import { createCipheriv, timingSafeEqual } from \"node:crypto\";\nimport { EAXTagMismatchError } from \"../errors.js\";\n\nconst EAX_TAG_SIZE = 8;\nconst EAX_BLOCK_SIZE = 16;\n\n/**\n * AES-EAX AEAD implementation for TS3 (64-bit tag, AES-128).\n * Uses AES-CMAC for authentication and AES-CTR for encryption.\n */\nexport class EAX {\n readonly #key: Uint8Array;\n\n constructor(key: Uint8Array) {\n if (key.length !== 16) throw new Error(\"EAX requires a 16-byte key\");\n this.#key = key;\n }\n\n encrypt(\n nonce: Uint8Array,\n header: Uint8Array,\n plaintext: Uint8Array,\n ): [ciphertext: Uint8Array, tag: Uint8Array] {\n const nStar = this.#cmac(0, nonce);\n const hStar = this.#cmac(1, header);\n\n const ciphertext = aesCtr(this.#key, nStar, plaintext);\n\n const cStar = this.#cmac(2, ciphertext);\n\n const tag = new Uint8Array(EAX_TAG_SIZE);\n for (let i = 0; i < EAX_TAG_SIZE; i++) {\n tag[i] = nStar[i]! ^ hStar[i]! ^ cStar[i]!;\n }\n\n return [ciphertext, tag];\n }\n\n decrypt(\n nonce: Uint8Array,\n header: Uint8Array,\n ciphertext: Uint8Array,\n tag: Uint8Array,\n ): Uint8Array {\n const nStar = this.#cmac(0, nonce);\n const hStar = this.#cmac(1, header);\n const cStar = this.#cmac(2, ciphertext);\n\n const expected = new Uint8Array(EAX_TAG_SIZE);\n for (let i = 0; i < EAX_TAG_SIZE; i++) {\n expected[i] = nStar[i]! ^ hStar[i]! ^ cStar[i]!;\n }\n\n if (!timingSafeEqual(Buffer.from(expected), Buffer.from(tag.slice(0, EAX_TAG_SIZE)))) {\n throw new EAXTagMismatchError();\n }\n\n return aesCtr(this.#key, nStar, ciphertext);\n }\n\n /**\n * AES-CMAC per RFC 4493:\n * input = [0…0 tag] ++ data (one block prefix)\n */\n #cmac(tagByte: number, data: Uint8Array): Uint8Array {\n const input = new Uint8Array(EAX_BLOCK_SIZE + data.length);\n // first block: zeros then tag byte at the last position\n input[EAX_BLOCK_SIZE - 1] = tagByte;\n input.set(data, EAX_BLOCK_SIZE);\n\n return aesCmac(this.#key, input);\n }\n}\n\n// ---- AES-CTR ----------------------------------------------------------------\n\nfunction aesCtr(key: Uint8Array, iv: Uint8Array, data: Uint8Array): Uint8Array {\n const cipher = createCipheriv(\"aes-128-ctr\", Buffer.from(key), Buffer.from(iv));\n return Buffer.concat([cipher.update(Buffer.from(data)), cipher.final()]);\n}\n\n// ---- AES-CMAC (RFC 4493) ----------------------------------------------------\n\nfunction aesEcb(key: Uint8Array, block: Uint8Array): Uint8Array {\n // Node.js does not expose ECB directly; simulate via CTR with zero IV and\n // a zero-input (CTR of 0-block XOR with input = ECB)\n const cipher = createCipheriv(\"aes-128-ecb\", Buffer.from(key), null);\n cipher.setAutoPadding(false);\n return Buffer.concat([cipher.update(Buffer.from(block)), cipher.final()]);\n}\n\nfunction xorBlock(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(EAX_BLOCK_SIZE);\n for (let i = 0; i < EAX_BLOCK_SIZE; i++) out[i] = a[i]! ^ b[i]!;\n return out;\n}\n\nfunction shiftLeft1(b: Uint8Array): Uint8Array {\n const out = new Uint8Array(EAX_BLOCK_SIZE);\n let carry = 0;\n for (let i = EAX_BLOCK_SIZE - 1; i >= 0; i--) {\n const shifted = ((b[i]! << 1) | carry) & 0xff;\n carry = b[i]! >> 7;\n out[i] = shifted;\n }\n return out;\n}\n\nconst RB = new Uint8Array(EAX_BLOCK_SIZE);\nRB[EAX_BLOCK_SIZE - 1] = 0x87;\n\nfunction generateSubkeys(key: Uint8Array): [Uint8Array, Uint8Array] {\n const zero = new Uint8Array(EAX_BLOCK_SIZE);\n const L = aesEcb(key, zero);\n\n let K1 = shiftLeft1(L);\n if ((L[0]! & 0x80) !== 0) K1 = xorBlock(K1, RB);\n\n let K2 = shiftLeft1(K1);\n if ((K1[0]! & 0x80) !== 0) K2 = xorBlock(K2, RB);\n\n return [K1, K2];\n}\n\nexport function aesCmac(key: Uint8Array, message: Uint8Array): Uint8Array {\n const [K1, K2] = generateSubkeys(key);\n\n const n = Math.max(1, Math.ceil(message.length / EAX_BLOCK_SIZE));\n const lastBlockComplete = message.length > 0 && message.length % EAX_BLOCK_SIZE === 0;\n\n let X: Uint8Array = new Uint8Array(EAX_BLOCK_SIZE);\n\n for (let i = 0; i < n - 1; i++) {\n const block = message.slice(i * EAX_BLOCK_SIZE, (i + 1) * EAX_BLOCK_SIZE);\n X = Uint8Array.from(aesEcb(key, xorBlock(X, block)));\n }\n\n const lastBlock = new Uint8Array(EAX_BLOCK_SIZE);\n const lastStart = (n - 1) * EAX_BLOCK_SIZE;\n const lastSlice = message.slice(lastStart);\n lastBlock.set(lastSlice);\n\n let Mn: Uint8Array;\n if (lastBlockComplete) {\n Mn = xorBlock(lastBlock, K1);\n } else {\n if (lastSlice.length < EAX_BLOCK_SIZE) lastBlock[lastSlice.length] = 0x80;\n Mn = xorBlock(lastBlock, K2);\n }\n\n return Uint8Array.from(aesEcb(key, xorBlock(X, Mn)));\n}\n","import { createHash, createECDH } from \"node:crypto\";\nimport { FakeSignatureMismatchError } from \"../errors.js\";\nimport type { Identity } from \"./identity.js\";\nimport { importPublicKey } from \"./identity.js\";\nimport { EAX } from \"./eax.js\";\n\nconst FAKE_SIGNATURE_SIZE = 8;\nconst IV_ALPHA_SIZE = 10;\nconst INIT1_PACKET_TYPE = 8;\nconst PACKET_TYPE_MASK = 0x0f;\n\nconst INIT1_MAC = Buffer.from(\"TS3INIT1\");\n\nexport interface KeyNonce {\n key: Uint8Array;\n nonce: Uint8Array;\n gen: number;\n}\n\n/** Precomputed dummy key/nonce matching the TS3 client pre-crypto placeholder. */\nconst DUMMY_KEY = Buffer.from(\"c:\\\\windows\\\\syste\");\nconst DUMMY_NONCE = Buffer.from(\"m\\\\firewall32.cpl\");\n\nexport class Crypt {\n readonly identity: Identity;\n\n ivStruct: Uint8Array = new Uint8Array(0);\n fakeSignature: Uint8Array = new Uint8Array(FAKE_SIGNATURE_SIZE);\n alphaTmp: Uint8Array = new Uint8Array(0);\n cryptoInitComplete = false;\n\n readonly #cachedKeys = new Map<bigint, KeyNonce>();\n\n constructor(identity: Identity) {\n this.identity = identity;\n }\n\n solveRsaChallenge(data: Uint8Array, offset: number, level: number): Uint8Array {\n if (level < 0 || level > 1_000_000) {\n throw new Error(\"RSA challenge level out of range\");\n }\n\n const xBytes = data.slice(offset, offset + 64);\n const nBytes = data.slice(offset + 64, offset + 128);\n\n let y = bytesToBigInt(xBytes);\n const n = bytesToBigInt(nBytes);\n\n for (let i = 0; i < level; i++) {\n y = (y * y) % n;\n }\n\n return bigIntToBytes(y, 64);\n }\n\n initCrypto(alpha: string, beta: string, omega: string): void {\n const alphaBytes = Buffer.from(alpha, \"base64\");\n const betaBytes = Buffer.from(beta, \"base64\");\n const omegaBytes = Buffer.from(omega, \"base64\");\n\n const serverPubKey = importPublicKey(omegaBytes);\n const sharedSecret = this.#getSharedSecret(serverPubKey);\n\n this.setSharedSecret(alphaBytes, betaBytes, sharedSecret);\n }\n\n setSharedSecret(alpha: Uint8Array, beta: Uint8Array, sharedKey: Uint8Array): void {\n this.ivStruct = new Uint8Array(IV_ALPHA_SIZE + beta.length);\n for (let i = 0; i < IV_ALPHA_SIZE; i++) {\n const a = sharedKey[i];\n const b = alpha[i];\n this.ivStruct[i] = ((a !== undefined ? a : 0) ^ (b !== undefined ? b : 0)) & 0xff;\n }\n for (let i = 0; i < beta.length; i++) {\n const a = sharedKey[IV_ALPHA_SIZE + i];\n const b = beta[i];\n this.ivStruct[IV_ALPHA_SIZE + i] =\n ((a !== undefined ? a : 0) ^ (b !== undefined ? b : 0)) & 0xff;\n }\n\n const digest = createHash(\"sha1\").update(this.ivStruct).digest();\n this.fakeSignature = new Uint8Array(digest.buffer, digest.byteOffset, FAKE_SIGNATURE_SIZE);\n this.cryptoInitComplete = true;\n }\n\n getKeyNonce(\n fromServer: boolean,\n packetID: number,\n generationID: number,\n packetType: number,\n dummy: boolean,\n ): [key: Uint8Array, nonce: Uint8Array] {\n if (dummy) {\n return [Uint8Array.from(DUMMY_KEY), Uint8Array.from(DUMMY_NONCE)];\n }\n\n const cacheKey = makeCacheKey(fromServer, packetType, generationID);\n let kn = this.#cachedKeys.get(cacheKey);\n\n if (kn === undefined) {\n const tmpToHash = new Uint8Array(6 + this.ivStruct.length);\n tmpToHash[0] = fromServer ? 0x30 : 0x31;\n tmpToHash[1] = packetType & PACKET_TYPE_MASK;\n new DataView(tmpToHash.buffer).setUint32(2, generationID, false);\n tmpToHash.set(this.ivStruct, 6);\n\n const hash = createHash(\"sha256\").update(tmpToHash).digest();\n kn = {\n key: Uint8Array.from(hash.slice(0, 16)),\n nonce: Uint8Array.from(hash.slice(16, 32)),\n gen: generationID,\n };\n this.#cachedKeys.set(cacheKey, kn);\n }\n\n const key = Uint8Array.from(kn.key);\n key[0] = (key[0] !== undefined ? key[0] : 0) ^ ((packetID >> 8) & 0xff);\n key[1] = (key[1] !== undefined ? key[1] : 0) ^ (packetID & 0xff);\n\n return [key, kn.nonce];\n }\n\n encrypt(\n packetType: number,\n packetID: number,\n generationID: number,\n header: Uint8Array,\n plaintext: Uint8Array,\n dummy: boolean,\n unencrypted: boolean,\n ): [ciphertext: Uint8Array, mac: Uint8Array] {\n if (packetType === INIT1_PACKET_TYPE) {\n return [plaintext, INIT1_MAC];\n }\n if (unencrypted) {\n return [plaintext, this.fakeSignature];\n }\n\n const [key, nonce] = this.getKeyNonce(false, packetID, generationID, packetType, dummy);\n const eax = new EAX(key);\n return eax.encrypt(nonce, header, plaintext);\n }\n\n decrypt(\n packetType: number,\n packetID: number,\n generationID: number,\n header: Uint8Array,\n ciphertext: Uint8Array,\n tag: Uint8Array,\n dummy: boolean,\n unencrypted: boolean,\n ): Uint8Array {\n if (packetType === INIT1_PACKET_TYPE) {\n return ciphertext;\n }\n if (unencrypted) {\n const fsSub = tag.slice(0, FAKE_SIGNATURE_SIZE);\n if (!Buffer.from(fsSub).equals(Buffer.from(this.fakeSignature))) {\n throw new FakeSignatureMismatchError();\n }\n return ciphertext;\n }\n\n const [key, nonce] = this.getKeyNonce(true, packetID, generationID, packetType, dummy);\n const eax = new EAX(key);\n return eax.decrypt(nonce, header, ciphertext, tag);\n }\n\n #getSharedSecret(serverPubKey: import(\"node:crypto\").KeyObject): Uint8Array {\n const privJwk = this.identity.privateKey.export({ format: \"jwk\" }) as {\n d: string;\n };\n const pubJwk = serverPubKey.export({ format: \"jwk\" }) as {\n x: string;\n y: string;\n };\n\n const ecdh = createECDH(\"prime256v1\");\n const dBytes = Buffer.from(privJwk.d, \"base64url\");\n ecdh.setPrivateKey(dBytes);\n\n const xBytes = base64UrlToBytes(pubJwk.x, 32);\n const yBytes = base64UrlToBytes(pubJwk.y, 32);\n const uncompressed = Buffer.alloc(65);\n uncompressed[0] = 0x04;\n xBytes.copy(uncompressed, 1);\n yBytes.copy(uncompressed, 33);\n\n const rawSecret = ecdh.computeSecret(uncompressed);\n return createHash(\"sha1\").update(rawSecret).digest();\n }\n}\n\n// ---- Helpers ----------------------------------------------------------------\n\nfunction makeCacheKey(fromServer: boolean, packetType: number, generationID: number): bigint {\n let key = 0n;\n if (fromServer) key |= 1n << 40n;\n key |= BigInt(packetType & PACKET_TYPE_MASK) << 32n;\n key |= BigInt(generationID);\n return key;\n}\n\nfunction bytesToBigInt(bytes: Uint8Array): bigint {\n let result = 0n;\n for (const b of bytes) result = (result << 8n) | BigInt(b);\n return result;\n}\n\nfunction bigIntToBytes(value: bigint, size: number): Uint8Array {\n const result = new Uint8Array(size);\n let v = value;\n for (let i = size - 1; i >= 0; i--) {\n result[i] = Number(v & 0xffn);\n v >>= 8n;\n }\n return result;\n}\n\nfunction base64UrlToBytes(b64url: string, size: number): Buffer {\n const buf = Buffer.from(b64url, \"base64url\");\n if (buf.length === size) return buf;\n const padded = Buffer.alloc(size);\n buf.copy(padded, size - buf.length);\n return padded;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"crypto-BfDd9DP6.cjs","names":["timingSafeEqual","EAXTagMismatchError","createCipheriv","importPublicKey","createHash","FakeSignatureMismatchError","createECDH","require_primitives","node_crypto","EAX_TAG_SIZE","EAX_BLOCK_SIZE","EAX","key","#key","nStar","#cmac","nonce","hStar","header","ciphertext","aesCtr","plaintext","cStar","tag","i","expected","input","data","tagByte","aesCmac","cipher","iv","aesEcb","block","xorBlock","out","a","b","shiftLeft1","carry","shifted","RB","generateSubkeys","L","K1","K2","n","message","lastBlockComplete","X","lastBlock","lastStart","lastSlice","Mn","FAKE_SIGNATURE_SIZE","IV_ALPHA_SIZE","INIT1_PACKET_TYPE","PACKET_TYPE_MASK","INIT1_MAC","DUMMY_KEY","DUMMY_NONCE","Crypt","identity","level","xBytes","offset","nBytes","y","bytesToBigInt","bigIntToBytes","alphaBytes","alpha","betaBytes","beta","omegaBytes","omega","serverPubKey","sharedSecret","#getSharedSecret","sharedKey","digest","dummy","cacheKey","makeCacheKey","fromServer","packetType","generationID","kn","#cachedKeys","tmpToHash","hash","packetID","unencrypted","fsSub","privJwk","pubJwk","ecdh","dBytes","base64UrlToBytes","yBytes","uncompressed","rawSecret","result","bytes","size","v","value","buf","b64url","padded"],"sources":["../src/crypto/eax.ts","../src/crypto/crypt.ts"],"sourcesContent":["import { createCipheriv, timingSafeEqual } from \"node:crypto\";\nimport { EAXTagMismatchError } from \"../errors.js\";\n\nconst EAX_TAG_SIZE = 8;\nconst EAX_BLOCK_SIZE = 16;\n\n/**\n * AES-EAX AEAD implementation for TS3 (64-bit tag, AES-128).\n * Uses AES-CMAC for authentication and AES-CTR for encryption.\n */\nexport class EAX {\n readonly #key: Uint8Array;\n\n constructor(key: Uint8Array) {\n if (key.length !== 16) throw new Error(\"EAX requires a 16-byte key\");\n this.#key = key;\n }\n\n encrypt(\n nonce: Uint8Array,\n header: Uint8Array,\n plaintext: Uint8Array,\n ): [ciphertext: Uint8Array, tag: Uint8Array] {\n const nStar = this.#cmac(0, nonce);\n const hStar = this.#cmac(1, header);\n\n const ciphertext = aesCtr(this.#key, nStar, plaintext);\n\n const cStar = this.#cmac(2, ciphertext);\n\n const tag = new Uint8Array(EAX_TAG_SIZE);\n for (let i = 0; i < EAX_TAG_SIZE; i++) {\n tag[i] = nStar[i]! ^ hStar[i]! ^ cStar[i]!;\n }\n\n return [ciphertext, tag];\n }\n\n decrypt(\n nonce: Uint8Array,\n header: Uint8Array,\n ciphertext: Uint8Array,\n tag: Uint8Array,\n ): Uint8Array {\n const nStar = this.#cmac(0, nonce);\n const hStar = this.#cmac(1, header);\n const cStar = this.#cmac(2, ciphertext);\n\n const expected = new Uint8Array(EAX_TAG_SIZE);\n for (let i = 0; i < EAX_TAG_SIZE; i++) {\n expected[i] = nStar[i]! ^ hStar[i]! ^ cStar[i]!;\n }\n\n if (!timingSafeEqual(Buffer.from(expected), Buffer.from(tag.slice(0, EAX_TAG_SIZE)))) {\n throw new EAXTagMismatchError();\n }\n\n return aesCtr(this.#key, nStar, ciphertext);\n }\n\n /**\n * AES-CMAC per RFC 4493:\n * input = [0…0 tag] ++ data (one block prefix)\n */\n #cmac(tagByte: number, data: Uint8Array): Uint8Array {\n const input = new Uint8Array(EAX_BLOCK_SIZE + data.length);\n // first block: zeros then tag byte at the last position\n input[EAX_BLOCK_SIZE - 1] = tagByte;\n input.set(data, EAX_BLOCK_SIZE);\n\n return aesCmac(this.#key, input);\n }\n}\n\n// ---- AES-CTR ----------------------------------------------------------------\n\nfunction aesCtr(key: Uint8Array, iv: Uint8Array, data: Uint8Array): Uint8Array {\n const cipher = createCipheriv(\"aes-128-ctr\", Buffer.from(key), Buffer.from(iv));\n return Buffer.concat([cipher.update(Buffer.from(data)), cipher.final()]);\n}\n\n// ---- AES-CMAC (RFC 4493) ----------------------------------------------------\n\nfunction aesEcb(key: Uint8Array, block: Uint8Array): Uint8Array {\n // Node.js does not expose ECB directly; simulate via CTR with zero IV and\n // a zero-input (CTR of 0-block XOR with input = ECB)\n const cipher = createCipheriv(\"aes-128-ecb\", Buffer.from(key), null);\n cipher.setAutoPadding(false);\n return Buffer.concat([cipher.update(Buffer.from(block)), cipher.final()]);\n}\n\nfunction xorBlock(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(EAX_BLOCK_SIZE);\n for (let i = 0; i < EAX_BLOCK_SIZE; i++) out[i] = a[i]! ^ b[i]!;\n return out;\n}\n\nfunction shiftLeft1(b: Uint8Array): Uint8Array {\n const out = new Uint8Array(EAX_BLOCK_SIZE);\n let carry = 0;\n for (let i = EAX_BLOCK_SIZE - 1; i >= 0; i--) {\n const shifted = ((b[i]! << 1) | carry) & 0xff;\n carry = b[i]! >> 7;\n out[i] = shifted;\n }\n return out;\n}\n\nconst RB = new Uint8Array(EAX_BLOCK_SIZE);\nRB[EAX_BLOCK_SIZE - 1] = 0x87;\n\nfunction generateSubkeys(key: Uint8Array): [Uint8Array, Uint8Array] {\n const zero = new Uint8Array(EAX_BLOCK_SIZE);\n const L = aesEcb(key, zero);\n\n let K1 = shiftLeft1(L);\n if ((L[0]! & 0x80) !== 0) K1 = xorBlock(K1, RB);\n\n let K2 = shiftLeft1(K1);\n if ((K1[0]! & 0x80) !== 0) K2 = xorBlock(K2, RB);\n\n return [K1, K2];\n}\n\nexport function aesCmac(key: Uint8Array, message: Uint8Array): Uint8Array {\n const [K1, K2] = generateSubkeys(key);\n\n const n = Math.max(1, Math.ceil(message.length / EAX_BLOCK_SIZE));\n const lastBlockComplete = message.length > 0 && message.length % EAX_BLOCK_SIZE === 0;\n\n let X: Uint8Array = new Uint8Array(EAX_BLOCK_SIZE);\n\n for (let i = 0; i < n - 1; i++) {\n const block = message.slice(i * EAX_BLOCK_SIZE, (i + 1) * EAX_BLOCK_SIZE);\n X = Uint8Array.from(aesEcb(key, xorBlock(X, block)));\n }\n\n const lastBlock = new Uint8Array(EAX_BLOCK_SIZE);\n const lastStart = (n - 1) * EAX_BLOCK_SIZE;\n const lastSlice = message.slice(lastStart);\n lastBlock.set(lastSlice);\n\n let Mn: Uint8Array;\n if (lastBlockComplete) {\n Mn = xorBlock(lastBlock, K1);\n } else {\n if (lastSlice.length < EAX_BLOCK_SIZE) lastBlock[lastSlice.length] = 0x80;\n Mn = xorBlock(lastBlock, K2);\n }\n\n return Uint8Array.from(aesEcb(key, xorBlock(X, Mn)));\n}\n","import { createHash, createECDH } from \"node:crypto\";\nimport { FakeSignatureMismatchError } from \"../errors.js\";\nimport type { Identity } from \"./identity.js\";\nimport { importPublicKey } from \"./identity.js\";\nimport { EAX } from \"./eax.js\";\n\nconst FAKE_SIGNATURE_SIZE = 8;\nconst IV_ALPHA_SIZE = 10;\nconst INIT1_PACKET_TYPE = 8;\nconst PACKET_TYPE_MASK = 0x0f;\n\nconst INIT1_MAC = Buffer.from(\"TS3INIT1\");\n\nexport interface KeyNonce {\n key: Uint8Array;\n nonce: Uint8Array;\n gen: number;\n}\n\n/** Precomputed dummy key/nonce matching the TS3 client pre-crypto placeholder. */\nconst DUMMY_KEY = Buffer.from(\"c:\\\\windows\\\\syste\");\nconst DUMMY_NONCE = Buffer.from(\"m\\\\firewall32.cpl\");\n\nexport class Crypt {\n readonly identity: Identity;\n\n ivStruct: Uint8Array = new Uint8Array(0);\n fakeSignature: Uint8Array = new Uint8Array(FAKE_SIGNATURE_SIZE);\n alphaTmp: Uint8Array = new Uint8Array(0);\n cryptoInitComplete = false;\n\n readonly #cachedKeys = new Map<bigint, KeyNonce>();\n\n constructor(identity: Identity) {\n this.identity = identity;\n }\n\n solveRsaChallenge(data: Uint8Array, offset: number, level: number): Uint8Array {\n if (level < 0 || level > 1_000_000) {\n throw new Error(\"RSA challenge level out of range\");\n }\n\n const xBytes = data.slice(offset, offset + 64);\n const nBytes = data.slice(offset + 64, offset + 128);\n\n let y = bytesToBigInt(xBytes);\n const n = bytesToBigInt(nBytes);\n\n for (let i = 0; i < level; i++) {\n y = (y * y) % n;\n }\n\n return bigIntToBytes(y, 64);\n }\n\n initCrypto(alpha: string, beta: string, omega: string): void {\n const alphaBytes = Buffer.from(alpha, \"base64\");\n const betaBytes = Buffer.from(beta, \"base64\");\n const omegaBytes = Buffer.from(omega, \"base64\");\n\n const serverPubKey = importPublicKey(omegaBytes);\n const sharedSecret = this.#getSharedSecret(serverPubKey);\n\n this.setSharedSecret(alphaBytes, betaBytes, sharedSecret);\n }\n\n setSharedSecret(alpha: Uint8Array, beta: Uint8Array, sharedKey: Uint8Array): void {\n this.ivStruct = new Uint8Array(IV_ALPHA_SIZE + beta.length);\n for (let i = 0; i < IV_ALPHA_SIZE; i++) {\n const a = sharedKey[i];\n const b = alpha[i];\n this.ivStruct[i] = ((a !== undefined ? a : 0) ^ (b !== undefined ? b : 0)) & 0xff;\n }\n for (let i = 0; i < beta.length; i++) {\n const a = sharedKey[IV_ALPHA_SIZE + i];\n const b = beta[i];\n this.ivStruct[IV_ALPHA_SIZE + i] =\n ((a !== undefined ? a : 0) ^ (b !== undefined ? b : 0)) & 0xff;\n }\n\n const digest = createHash(\"sha1\").update(this.ivStruct).digest();\n this.fakeSignature = new Uint8Array(digest.buffer, digest.byteOffset, FAKE_SIGNATURE_SIZE);\n this.cryptoInitComplete = true;\n }\n\n getKeyNonce(\n fromServer: boolean,\n packetID: number,\n generationID: number,\n packetType: number,\n dummy: boolean,\n ): [key: Uint8Array, nonce: Uint8Array] {\n if (dummy) {\n return [Uint8Array.from(DUMMY_KEY), Uint8Array.from(DUMMY_NONCE)];\n }\n\n const cacheKey = makeCacheKey(fromServer, packetType, generationID);\n let kn = this.#cachedKeys.get(cacheKey);\n\n if (kn === undefined) {\n const tmpToHash = new Uint8Array(6 + this.ivStruct.length);\n tmpToHash[0] = fromServer ? 0x30 : 0x31;\n tmpToHash[1] = packetType & PACKET_TYPE_MASK;\n new DataView(tmpToHash.buffer).setUint32(2, generationID, false);\n tmpToHash.set(this.ivStruct, 6);\n\n const hash = createHash(\"sha256\").update(tmpToHash).digest();\n kn = {\n key: Uint8Array.from(hash.slice(0, 16)),\n nonce: Uint8Array.from(hash.slice(16, 32)),\n gen: generationID,\n };\n this.#cachedKeys.set(cacheKey, kn);\n }\n\n const key = Uint8Array.from(kn.key);\n key[0] = (key[0] !== undefined ? key[0] : 0) ^ ((packetID >> 8) & 0xff);\n key[1] = (key[1] !== undefined ? key[1] : 0) ^ (packetID & 0xff);\n\n return [key, kn.nonce];\n }\n\n encrypt(\n packetType: number,\n packetID: number,\n generationID: number,\n header: Uint8Array,\n plaintext: Uint8Array,\n dummy: boolean,\n unencrypted: boolean,\n ): [ciphertext: Uint8Array, mac: Uint8Array] {\n if (packetType === INIT1_PACKET_TYPE) {\n return [plaintext, INIT1_MAC];\n }\n if (unencrypted) {\n return [plaintext, this.fakeSignature];\n }\n\n const [key, nonce] = this.getKeyNonce(false, packetID, generationID, packetType, dummy);\n const eax = new EAX(key);\n return eax.encrypt(nonce, header, plaintext);\n }\n\n decrypt(\n packetType: number,\n packetID: number,\n generationID: number,\n header: Uint8Array,\n ciphertext: Uint8Array,\n tag: Uint8Array,\n dummy: boolean,\n unencrypted: boolean,\n ): Uint8Array {\n if (packetType === INIT1_PACKET_TYPE) {\n return ciphertext;\n }\n if (unencrypted) {\n const fsSub = tag.slice(0, FAKE_SIGNATURE_SIZE);\n if (!Buffer.from(fsSub).equals(Buffer.from(this.fakeSignature))) {\n throw new FakeSignatureMismatchError();\n }\n return ciphertext;\n }\n\n const [key, nonce] = this.getKeyNonce(true, packetID, generationID, packetType, dummy);\n const eax = new EAX(key);\n return eax.decrypt(nonce, header, ciphertext, tag);\n }\n\n #getSharedSecret(serverPubKey: import(\"node:crypto\").KeyObject): Uint8Array {\n const privJwk = this.identity.privateKey.export({ format: \"jwk\" }) as {\n d: string;\n };\n const pubJwk = serverPubKey.export({ format: \"jwk\" }) as {\n x: string;\n y: string;\n };\n\n const ecdh = createECDH(\"prime256v1\");\n const dBytes = Buffer.from(privJwk.d, \"base64url\");\n ecdh.setPrivateKey(dBytes);\n\n const xBytes = base64UrlToBytes(pubJwk.x, 32);\n const yBytes = base64UrlToBytes(pubJwk.y, 32);\n const uncompressed = Buffer.alloc(65);\n uncompressed[0] = 0x04;\n xBytes.copy(uncompressed, 1);\n yBytes.copy(uncompressed, 33);\n\n const rawSecret = ecdh.computeSecret(uncompressed);\n return createHash(\"sha1\").update(rawSecret).digest();\n }\n}\n\n// ---- Helpers ----------------------------------------------------------------\n\nfunction makeCacheKey(fromServer: boolean, packetType: number, generationID: number): bigint {\n let key = 0n;\n if (fromServer) key |= 1n << 40n;\n key |= BigInt(packetType & PACKET_TYPE_MASK) << 32n;\n key |= BigInt(generationID);\n return key;\n}\n\nfunction bytesToBigInt(bytes: Uint8Array): bigint {\n let result = 0n;\n for (const b of bytes) result = (result << 8n) | BigInt(b);\n return result;\n}\n\nfunction bigIntToBytes(value: bigint, size: number): Uint8Array {\n const result = new Uint8Array(size);\n let v = value;\n for (let i = size - 1; i >= 0; i--) {\n result[i] = Number(v & 0xffn);\n v >>= 8n;\n }\n return result;\n}\n\nfunction base64UrlToBytes(b64url: string, size: number): Buffer {\n const buf = Buffer.from(b64url, \"base64url\");\n if (buf.length === size) return buf;\n const padded = Buffer.alloc(size);\n buf.copy(padded, size - buf.length);\n return padded;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { m as e, v as t, y as n } from "./primitives-xIr6Tjk4.js";
1
+ import { b as e, m as t, y as n } from "./primitives-CdX74Rgu.js";
2
2
  import { createCipheriv as r, createECDH as i, createHash as a, timingSafeEqual as o } from "node:crypto";
3
3
  //#region src/crypto/eax.ts
4
4
  var s = 8, c = 16, l = class {
@@ -12,10 +12,10 @@ var s = 8, c = 16, l = class {
12
12
  for (let e = 0; e < s; e++) c[e] = r[e] ^ i[e] ^ o[e];
13
13
  return [a, c];
14
14
  }
15
- decrypt(e, n, r, i) {
16
- let a = this.#t(0, e), c = this.#t(1, n), l = this.#t(2, r), d = new Uint8Array(s);
15
+ decrypt(e, t, r, i) {
16
+ let a = this.#t(0, e), c = this.#t(1, t), l = this.#t(2, r), d = new Uint8Array(s);
17
17
  for (let e = 0; e < s; e++) d[e] = a[e] ^ c[e] ^ l[e];
18
- if (!o(Buffer.from(d), Buffer.from(i.slice(0, s)))) throw new t();
18
+ if (!o(Buffer.from(d), Buffer.from(i.slice(0, s)))) throw new n();
19
19
  return u(this.#e, a, r);
20
20
  }
21
21
  #t(e, t) {
@@ -81,8 +81,8 @@ var _ = 8, v = 10, y = 8, b = 15, x = Buffer.from("TS3INIT1"), S = Buffer.from("
81
81
  for (let e = 0; e < n; e++) a = a * a % o;
82
82
  return D(a, 64);
83
83
  }
84
- initCrypto(t, n, r) {
85
- let i = Buffer.from(t, "base64"), a = Buffer.from(n, "base64"), o = Buffer.from(r, "base64"), s = e(o), c = this.#t(s);
84
+ initCrypto(e, n, r) {
85
+ let i = Buffer.from(e, "base64"), a = Buffer.from(n, "base64"), o = Buffer.from(r, "base64"), s = t(o), c = this.#t(s);
86
86
  this.setSharedSecret(i, a, c);
87
87
  }
88
88
  setSharedSecret(e, t, n) {
@@ -120,14 +120,14 @@ var _ = 8, v = 10, y = 8, b = 15, x = Buffer.from("TS3INIT1"), S = Buffer.from("
120
120
  let [s, c] = this.getKeyNonce(!1, t, n, e, a);
121
121
  return new l(s).encrypt(c, r, i);
122
122
  }
123
- decrypt(e, t, r, i, a, o, s, c) {
124
- if (e === y) return a;
123
+ decrypt(t, n, r, i, a, o, s, c) {
124
+ if (t === y) return a;
125
125
  if (c) {
126
- let e = o.slice(0, _);
127
- if (!Buffer.from(e).equals(Buffer.from(this.fakeSignature))) throw new n();
126
+ let t = o.slice(0, _);
127
+ if (!Buffer.from(t).equals(Buffer.from(this.fakeSignature))) throw new e();
128
128
  return a;
129
129
  }
130
- let [u, d] = this.getKeyNonce(!0, t, r, e, s);
130
+ let [u, d] = this.getKeyNonce(!0, n, r, t, s);
131
131
  return new l(u).decrypt(d, i, a, o);
132
132
  }
133
133
  #t(e) {
@@ -162,4 +162,4 @@ function O(e, t) {
162
162
  //#endregion
163
163
  export { l as n, g as r, w as t };
164
164
 
165
- //# sourceMappingURL=crypto-Bg02m4ZE.js.map
165
+ //# sourceMappingURL=crypto-DLV3oH5F.js.map