@basmilius/apple-common 0.0.80 → 0.0.82

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.
package/dist/index.js CHANGED
@@ -1,2 +1,1541 @@
1
- var k=Object.defineProperty;var R=(e,r)=>{for(var o in r)k(e,o,{get:r[o],enumerable:!0,configurable:!0,set:(t)=>r[o]=()=>t})};import{v4 as ur}from"uuid";var l={};R(l,{padNonce:()=>w,encrypt:()=>z,decrypt:()=>W,CHACHA20_NONCE_LENGTH:()=>S,CHACHA20_AUTH_TAG_LENGTH:()=>G});import{createCipher as H,createDecipher as Y}from"chacha";var G=16,S=12;function W(e,r,o,t,n){r=w(r);let i=Y(e,r);o&&i.setAAD(o),i.setAuthTag(n);let a=i._update(t);return i._final(),a}function z(e,r,o,t){r=w(r);let n=H(e,r);o&&n.setAAD(o);let i=n._update(t);n._final();let a=n.getAuthTag();return{ciphertext:i,authTag:a}}function w(e){if(e.length>=S)return e;return Buffer.concat([Buffer.alloc(S-e.length,0),e])}var m={};R(m,{generateSharedSecKey:()=>Q,generateKeyPair:()=>J});import D from"tweetnacl";function J(){let e=D.box.keyPair();return{publicKey:e.publicKey,secretKey:e.secretKey}}function Q(e,r){return D.scalarMult(e,r)}import{hkdfSync as Z}from"node:crypto";function f(e){return Buffer.from(Z(e.hash,e.key,e.salt,e.info,e.length))}import oe from"node-dns-sd";import{createInterface as j}from"node:readline";var _=j({input:process.stdin,output:process.stdout});async function ee(e){return await new Promise((r)=>_.question(`${e}: `,r))}async function I(e){return new Promise((r)=>setTimeout(r,e))}class C{#e=[];all(){this.#e=["debug","error","info","net","raw","warn"]}disable(e){if(this.#e.includes(e))this.#e.splice(this.#e.indexOf(e),1)}enable(e){if(!this.#e.includes(e))this.#e.push(e)}isEnabled(e){return this.#e.includes(e)}debug(...e){this.isEnabled("debug")&&console.debug("\x1B[36m[debug]\x1B[39m",...e)}error(...e){this.isEnabled("error")&&console.error("\x1B[31m[error]\x1B[39m",...e)}info(...e){this.isEnabled("info")&&console.info("\x1B[32m[info]\x1B[39m",...e)}net(...e){this.isEnabled("net")&&console.info("\x1B[33m[net]\x1B[39m",...e)}raw(...e){this.isEnabled("raw")&&console.log("\x1B[34m[raw]\x1B[39m",...e)}warn(...e){this.isEnabled("warn")&&console.warn("\x1B[33m[warn]\x1B[39m",...e)}}var c=new C;var K="3939",re=6000,L=1e4,v="_airplay._tcp.local",V="_companion-link._tcp.local",M="_raop._tcp.local";class d{#e;constructor(e){this.#e=e}async find(){return await oe.discover({name:this.#e})}async findUntil(e,r=10,o=1000){while(r>0){let t=await this.find(),n=t.find((i)=>i.fqdn===e);if(n)return n;if(console.log(),console.log(`Device not found, retrying in ${o}ms...`),console.log(t.map((i)=>` ● ${i.fqdn}`).join(`
2
- `)),r--,r===0)throw Error("Device not found after serveral tries, aborting.");await I(o)}}static airplay(){return new d(v)}static companionLink(){return new d(V)}static raop(){return new d(M)}}import{networkInterfaces as te}from"node:os";function x(){let e=te();for(let r of Object.keys(e)){let o=e[r];if(!o)continue;for(let t of o){if(t.internal||t.family!=="IPv4")continue;if(t.address&&t.address!=="127.0.0.1")return t.address}}return null}import{networkInterfaces as se}from"node:os";function F(){let e=se();for(let r of Object.keys(e)){let o=e[r];if(!o)continue;for(let t of o){if(t.internal||t.family!=="IPv4")continue;if(t.mac&&t.mac!=="00:00:00:00:00:00")return t.mac.toUpperCase()}}return"00:00:00:00:00:00"}import{createSocket as ne}from"node:dgram";import{NTP as B}from"@basmilius/apple-encoding";class N{get port(){return this.#t}#e;#t=0;constructor(){this.#e=ne("udp4"),this.#e.on("error",(e)=>this.#s(e)),this.#e.on("message",(e,r)=>this.#n(e,r))}async close(){this.#e.close(),this.#t=0}async listen(){return new Promise((e)=>{this.#e.once("listening",()=>this.#a()),this.#e.bind(0,e)})}async#s(e){c.error("Timing server error",e)}async#a(){let{port:e}=this.#e.address();this.#t=e}async#n(e,r){let o=B.decode(e),t=B.now(),[n,i]=B.parts(t);c.info(`Timing server ntp=${t} receivedSeconds=${n} receivedFraction=${i}`);let a=B.encode({proto:o.proto,type:211,seqno:o.seqno,padding:0,reftime_sec:o.sendtime_sec,reftime_frac:o.sendtime_frac,recvtime_sec:n,recvtime_frac:i,sendtime_sec:n,sendtime_frac:i});this.#e.send(a,r.port,r.address)}}import{EventEmitter as ie}from"node:events";import{Socket as ae}from"node:net";var h=Symbol();class A extends ie{get address(){return this.#e}get port(){return this.#t}get isConnected(){return this.#o==="connected"}get state(){return this.#o}#e;#t;#s;#a=!1;#n=0;#i=3;#u=!0;#l=3000;#f;#r;#o;#c;constructor(e,r){super();this.#e=e,this.#t=r,this.#s={onClose:this.#p.bind(this),onConnect:this.#h.bind(this),onData:this.#g.bind(this),onEnd:this.#P.bind(this),onError:this.#B.bind(this),onTimeout:this.#b.bind(this)},this.#o="disconnected"}async connect(){if(this.#o==="connected")return;if(this.#o==="connecting")throw Error("A connection is already being established.");return this.#u=!0,this.#n=0,this.#d()}async disconnect(){if(this.#f)clearTimeout(this.#f),this.#f=void 0;if(this.#u=!1,!this.#r||this.#o==="disconnected")return;return new Promise((e)=>{this.#o="closing",this.#r.once("close",()=>{this.#m(),e()}),this.#r.end()})}debug(e){return this.#a=e,this}retry(e,r=3000){return this.#i=e,this.#l=r,this}async write(e){if(!this.#r||this.#o!=="connected")throw Error("Cannot write to a disconnected connection.");return new Promise((r,o)=>{this.#r.write(e,(t)=>t?o(t):r())})}async#d(){return new Promise((e,r)=>{this.#o="connecting",this.#c={resolve:e,reject:r},this.#r=new ae,this.#r.setTimeout(L),this.#r.on("close",this.#s.onClose),this.#r.on("connect",this.#s.onConnect),this.#r.on("data",this.#s.onData),this.#r.on("end",this.#s.onEnd),this.#r.on("error",this.#s.onError),this.#r.on("timeout",this.#s.onTimeout),c.net(`Connecting to ${this.#e}:${this.#t}...`),this.#r.connect({host:this.#e,port:this.#t,keepAlive:!0})})}#m(){if(this.#r)this.#r.removeAllListeners(),this.#r.destroy(),this.#r=void 0;this.#o="disconnected",this.#c=void 0}#y(e){if(!this.#u||this.#n>=this.#i){this.#o="failed",this.#c?.reject(e),this.#c=void 0;return}this.#n++,c.net(`Retry attempt ${this.#n} / ${this.#i} in ${this.#l}ms...`);let{resolve:r,reject:o}=this.#c;this.#m(),this.#f=setTimeout(async()=>{this.#f=void 0;try{this.#c={resolve:r,reject:o},await this.#d(),r()}catch(t){}},this.#l)}#p(e){let r=this.#o==="connected";if(this.#o!=="closing")this.#o="disconnected";if(this.emit("close",e),r&&this.#u&&e)this.#y(Error("Connection closed unexpectedly."))}#h(){this.#o="connected",this.#n=0,this.#r.setKeepAlive(!0,1e4),this.#r.setTimeout(0),this.emit("connect"),this.#c?.resolve(),this.#c=void 0}#g(e){if(this.#a){let r=Math.min(e.byteLength,64);c.debug(`Received ${e.byteLength} bytes of data.`),c.debug(`hex=${e.subarray(0,r).toString("hex")}`),c.debug(`ascii=${e.toString("ascii").replace(/[^\x20-\x7E]/g,".").substring(0,r)}`)}this.emit("data",e)}#P(){this.emit("end")}#B(e){if(c.error(`Connection error: ${e.message}`),this.emit("error",e),this.#o==="connecting")this.#y(e);else this.#o="failed"}#b(){c.error("Connection timed out.");let e=Error("Connection timed out.");if(this.emit("timeout"),this.emit("error",e),this.#o==="connecting")this.#y(e);else this.#o="failed",this.#r?.destroy()}}class U extends A{get isEncrypted(){return!!this[h]}[h];async enableEncryption(e,r){this[h]=new E(e,r)}}class E{readKey;readCount;writeKey;writeCount;constructor(e,r){this.readCount=0,this.readKey=e,this.writeCount=0,this.writeKey=r}}import{OPack as ce,TLV8 as s}from"@basmilius/apple-encoding";import{SRP as q,SrpClient as fe}from"fast-srp-hap";import{v4 as ue}from"uuid";import g from"tweetnacl";class O{#e;#t;#s;#a;#n;#i;constructor(e){this.#e="basmilius/apple-protocols",this.#t=Buffer.from(ue().toUpperCase()),this.#s=e}async start(){let e=g.sign.keyPair();this.#a=Buffer.from(e.publicKey),this.#n=Buffer.from(e.secretKey)}async pin(e){let r=await this.m1(),o=await this.m2(r,await e()),t=await this.m3(o),n=await this.m4(t),i=await this.m5(n),a=await this.m6(n,i);if(!a)throw Error("Pairing failed, could not get accessory keys.");return a}async transient(){let e=await this.m1([[s.Value.Flags,s.Flags.TransientPairing]]),r=await this.m2(e),o=await this.m3(r),t=await this.m4(o),n=f({hash:"sha512",key:t.sharedSecret,length:32,salt:Buffer.from("Control-Salt"),info:Buffer.from("Control-Read-Encryption-Key")}),i=f({hash:"sha512",key:t.sharedSecret,length:32,salt:Buffer.from("Control-Salt"),info:Buffer.from("Control-Write-Encryption-Key")});return{pairingId:this.#t,sharedSecret:t.sharedSecret,accessoryToControllerKey:n,controllerToAccessoryKey:i}}async m1(e=[]){let r=await this.#s("m1",s.encode([[s.Value.Method,s.Method.PairSetup],[s.Value.State,s.State.M1],...e])),o=b(r),t=o.get(s.Value.PublicKey),n=o.get(s.Value.Salt);return{publicKey:t,salt:n}}async m2(e,r=K){let o=await q.genKey(32);this.#i=new fe(q.params.hap,e.salt,Buffer.from("Pair-Setup"),Buffer.from(r),o,!0),this.#i.setB(e.publicKey);let t=this.#i.computeA(),n=this.#i.computeM1();return{publicKey:t,proof:n}}async m3(e){let r=await this.#s("m3",s.encode([[s.Value.State,s.State.M3],[s.Value.PublicKey,e.publicKey],[s.Value.Proof,e.proof]]));return{serverProof:b(r).get(s.Value.Proof)}}async m4(e){return this.#i.checkM2(e.serverProof),{sharedSecret:this.#i.computeK()}}async m5(e){let r=f({hash:"sha512",key:e.sharedSecret,length:32,salt:Buffer.from("Pair-Setup-Controller-Sign-Salt","utf8"),info:Buffer.from("Pair-Setup-Controller-Sign-Info","utf8")}),o=f({hash:"sha512",key:e.sharedSecret,length:32,salt:Buffer.from("Pair-Setup-Encrypt-Salt","utf8"),info:Buffer.from("Pair-Setup-Encrypt-Info","utf8")}),t=Buffer.concat([r,this.#t,this.#a]),n=g.sign.detached(t,this.#n),i=s.encode([[s.Value.Identifier,this.#t],[s.Value.PublicKey,this.#a],[s.Value.Signature,Buffer.from(n)],[s.Value.Name,Buffer.from(ce.encode({name:this.#e}))]]),{authTag:a,ciphertext:y}=l.encrypt(o,Buffer.from("PS-Msg05"),null,i),u=Buffer.concat([y,a]),p=await this.#s("m5",s.encode([[s.Value.State,s.State.M5],[s.Value.EncryptedData,u]])),P=b(p).get(s.Value.EncryptedData),X=P.subarray(0,-16);return{authTag:P.subarray(-16),data:X,sessionKey:o}}async m6(e,r){let o=l.decrypt(r.sessionKey,Buffer.from("PS-Msg06"),null,r.data,r.authTag),t=s.decode(o),n=t.get(s.Value.Identifier),i=t.get(s.Value.PublicKey),a=t.get(s.Value.Signature),y=f({hash:"sha512",key:e.sharedSecret,length:32,salt:Buffer.from("Pair-Setup-Accessory-Sign-Salt"),info:Buffer.from("Pair-Setup-Accessory-Sign-Info")}),u=Buffer.concat([y,n,i]);if(!g.sign.detached.verify(u,a,i))throw Error("Invalid accessory signature.");return{accessoryIdentifier:n.toString(),accessoryLongTermPublicKey:i,pairingId:this.#t,publicKey:this.#a,secretKey:this.#n}}}class ${#e;#t;constructor(e){this.#e=m.generateKeyPair(),this.#t=e}async start(e){let r=await this.#s(),o=await this.#a(e.accessoryIdentifier,e.accessoryLongTermPublicKey,r);return await this.#n(e.pairingId,e.secretKey,o),await this.#i(o,e.pairingId)}async#s(){let e=await this.#t("m1",s.encode([[s.Value.State,s.State.M1],[s.Value.PublicKey,Buffer.from(this.#e.publicKey)]])),r=b(e),o=r.get(s.Value.PublicKey);return{encryptedData:r.get(s.Value.EncryptedData),serverPublicKey:o}}async#a(e,r,o){let t=Buffer.from(m.generateSharedSecKey(this.#e.secretKey,o.serverPublicKey)),n=f({hash:"sha512",key:t,length:32,salt:Buffer.from("Pair-Verify-Encrypt-Salt"),info:Buffer.from("Pair-Verify-Encrypt-Info")}),i=o.encryptedData.subarray(0,-16),a=o.encryptedData.subarray(-16),y=l.decrypt(n,Buffer.from("PV-Msg02"),null,i,a),u=s.decode(y),p=u.get(s.Value.Identifier),T=u.get(s.Value.Signature);if(p.toString()!==e)throw Error(`Invalid accessory identifier. Expected ${p.toString()} to be ${e}.`);let P=Buffer.concat([o.serverPublicKey,p,this.#e.publicKey]);if(!g.sign.detached.verify(P,T,r))throw Error("Invalid accessory signature.");return{serverEphemeralPublicKey:o.serverPublicKey,sessionKey:n,sharedSecret:t}}async#n(e,r,o){let t=Buffer.concat([this.#e.publicKey,e,o.serverEphemeralPublicKey]),n=Buffer.from(g.sign.detached(t,r)),i=s.encode([[s.Value.Identifier,e],[s.Value.Signature,n]]),{authTag:a,ciphertext:y}=l.encrypt(o.sessionKey,Buffer.from("PV-Msg03"),null,i),u=Buffer.concat([y,a]);return await this.#t("m3",s.encode([[s.Value.State,s.State.M3],[s.Value.EncryptedData,u]])),{}}async#i(e,r){return{accessoryToControllerKey:Buffer.alloc(0),controllerToAccessoryKey:Buffer.alloc(0),pairingId:r,sharedSecret:e.sharedSecret}}}function b(e){let r=s.decode(e);if(r.has(s.Value.Error))s.bail(r);return c.raw("Decoded TLV",r),r}function le(e){let r=Buffer.alloc(2);return r.writeUInt16BE(e,0),r}function ye(e){let[r,o]=de(e),t=Buffer.alloc(8);return t.writeUInt32LE(o,0),t.writeUInt32LE(r,4),t}function de(e){if(e<=-1||e>9007199254740991)throw Error("Number out of range.");if(Math.floor(e)!==e)throw Error("Number is not an integer.");let t=0,n=e&4294967295,i=n<0?(e&2147483647)+2147483648:n;if(e>4294967295)t=(e-i)/4294967296;return[t,i]}export{I as waitFor,ur as uuid,ye as uint53ToLE,le as uint16ToBE,c as reporter,ee as prompt,f as hkdf,F as getMacAddress,x as getLocalIP,_ as cli,N as TimingServer,M as RAOP_SERVICE,re as HTTP_TIMEOUT,E as EncryptionState,U as EncryptionAwareConnection,h as ENCRYPTION,d as Discovery,m as Curve25519,A as Connection,l as Chacha20,V as COMPANION_LINK_SERVICE,$ as AccessoryVerify,O as AccessoryPair,K as AIRPLAY_TRANSIENT_PIN,v as AIRPLAY_SERVICE};
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, {
5
+ get: all[name],
6
+ enumerable: true,
7
+ configurable: true,
8
+ set: (newValue) => all[name] = () => newValue
9
+ });
10
+ };
11
+
12
+ // src/index.ts
13
+ import {
14
+ v4
15
+ } from "uuid";
16
+
17
+ // src/crypto/chacha20.ts
18
+ var exports_chacha20 = {};
19
+ __export(exports_chacha20, {
20
+ padNonce: () => padNonce,
21
+ encrypt: () => encrypt,
22
+ decrypt: () => decrypt,
23
+ CHACHA20_NONCE_LENGTH: () => CHACHA20_NONCE_LENGTH,
24
+ CHACHA20_AUTH_TAG_LENGTH: () => CHACHA20_AUTH_TAG_LENGTH
25
+ });
26
+
27
+ // ../../node_modules/@stablelib/int/lib/int.js
28
+ var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
29
+
30
+ // ../../node_modules/@stablelib/binary/lib/binary.js
31
+ function writeUint32LE(value, out = new Uint8Array(4), offset = 0) {
32
+ out[offset + 0] = value >>> 0;
33
+ out[offset + 1] = value >>> 8;
34
+ out[offset + 2] = value >>> 16;
35
+ out[offset + 3] = value >>> 24;
36
+ return out;
37
+ }
38
+ function writeUint64LE(value, out = new Uint8Array(8), offset = 0) {
39
+ writeUint32LE(value >>> 0, out, offset);
40
+ writeUint32LE(value / 4294967296 >>> 0, out, offset + 4);
41
+ return out;
42
+ }
43
+
44
+ // ../../node_modules/@stablelib/wipe/lib/wipe.js
45
+ function wipe(array) {
46
+ for (let i = 0;i < array.length; i++) {
47
+ array[i] = 0;
48
+ }
49
+ return array;
50
+ }
51
+
52
+ // ../../node_modules/@stablelib/chacha/lib/chacha.js
53
+ var ROUNDS = 20;
54
+ function core(out, input, key) {
55
+ let j0 = 1634760805;
56
+ let j1 = 857760878;
57
+ let j2 = 2036477234;
58
+ let j3 = 1797285236;
59
+ let j4 = key[3] << 24 | key[2] << 16 | key[1] << 8 | key[0];
60
+ let j5 = key[7] << 24 | key[6] << 16 | key[5] << 8 | key[4];
61
+ let j6 = key[11] << 24 | key[10] << 16 | key[9] << 8 | key[8];
62
+ let j7 = key[15] << 24 | key[14] << 16 | key[13] << 8 | key[12];
63
+ let j8 = key[19] << 24 | key[18] << 16 | key[17] << 8 | key[16];
64
+ let j9 = key[23] << 24 | key[22] << 16 | key[21] << 8 | key[20];
65
+ let j10 = key[27] << 24 | key[26] << 16 | key[25] << 8 | key[24];
66
+ let j11 = key[31] << 24 | key[30] << 16 | key[29] << 8 | key[28];
67
+ let j12 = input[3] << 24 | input[2] << 16 | input[1] << 8 | input[0];
68
+ let j13 = input[7] << 24 | input[6] << 16 | input[5] << 8 | input[4];
69
+ let j14 = input[11] << 24 | input[10] << 16 | input[9] << 8 | input[8];
70
+ let j15 = input[15] << 24 | input[14] << 16 | input[13] << 8 | input[12];
71
+ let x0 = j0;
72
+ let x1 = j1;
73
+ let x2 = j2;
74
+ let x3 = j3;
75
+ let x4 = j4;
76
+ let x5 = j5;
77
+ let x6 = j6;
78
+ let x7 = j7;
79
+ let x8 = j8;
80
+ let x9 = j9;
81
+ let x10 = j10;
82
+ let x11 = j11;
83
+ let x12 = j12;
84
+ let x13 = j13;
85
+ let x14 = j14;
86
+ let x15 = j15;
87
+ for (let i = 0;i < ROUNDS; i += 2) {
88
+ x0 = x0 + x4 | 0;
89
+ x12 ^= x0;
90
+ x12 = x12 >>> 32 - 16 | x12 << 16;
91
+ x8 = x8 + x12 | 0;
92
+ x4 ^= x8;
93
+ x4 = x4 >>> 32 - 12 | x4 << 12;
94
+ x1 = x1 + x5 | 0;
95
+ x13 ^= x1;
96
+ x13 = x13 >>> 32 - 16 | x13 << 16;
97
+ x9 = x9 + x13 | 0;
98
+ x5 ^= x9;
99
+ x5 = x5 >>> 32 - 12 | x5 << 12;
100
+ x2 = x2 + x6 | 0;
101
+ x14 ^= x2;
102
+ x14 = x14 >>> 32 - 16 | x14 << 16;
103
+ x10 = x10 + x14 | 0;
104
+ x6 ^= x10;
105
+ x6 = x6 >>> 32 - 12 | x6 << 12;
106
+ x3 = x3 + x7 | 0;
107
+ x15 ^= x3;
108
+ x15 = x15 >>> 32 - 16 | x15 << 16;
109
+ x11 = x11 + x15 | 0;
110
+ x7 ^= x11;
111
+ x7 = x7 >>> 32 - 12 | x7 << 12;
112
+ x2 = x2 + x6 | 0;
113
+ x14 ^= x2;
114
+ x14 = x14 >>> 32 - 8 | x14 << 8;
115
+ x10 = x10 + x14 | 0;
116
+ x6 ^= x10;
117
+ x6 = x6 >>> 32 - 7 | x6 << 7;
118
+ x3 = x3 + x7 | 0;
119
+ x15 ^= x3;
120
+ x15 = x15 >>> 32 - 8 | x15 << 8;
121
+ x11 = x11 + x15 | 0;
122
+ x7 ^= x11;
123
+ x7 = x7 >>> 32 - 7 | x7 << 7;
124
+ x1 = x1 + x5 | 0;
125
+ x13 ^= x1;
126
+ x13 = x13 >>> 32 - 8 | x13 << 8;
127
+ x9 = x9 + x13 | 0;
128
+ x5 ^= x9;
129
+ x5 = x5 >>> 32 - 7 | x5 << 7;
130
+ x0 = x0 + x4 | 0;
131
+ x12 ^= x0;
132
+ x12 = x12 >>> 32 - 8 | x12 << 8;
133
+ x8 = x8 + x12 | 0;
134
+ x4 ^= x8;
135
+ x4 = x4 >>> 32 - 7 | x4 << 7;
136
+ x0 = x0 + x5 | 0;
137
+ x15 ^= x0;
138
+ x15 = x15 >>> 32 - 16 | x15 << 16;
139
+ x10 = x10 + x15 | 0;
140
+ x5 ^= x10;
141
+ x5 = x5 >>> 32 - 12 | x5 << 12;
142
+ x1 = x1 + x6 | 0;
143
+ x12 ^= x1;
144
+ x12 = x12 >>> 32 - 16 | x12 << 16;
145
+ x11 = x11 + x12 | 0;
146
+ x6 ^= x11;
147
+ x6 = x6 >>> 32 - 12 | x6 << 12;
148
+ x2 = x2 + x7 | 0;
149
+ x13 ^= x2;
150
+ x13 = x13 >>> 32 - 16 | x13 << 16;
151
+ x8 = x8 + x13 | 0;
152
+ x7 ^= x8;
153
+ x7 = x7 >>> 32 - 12 | x7 << 12;
154
+ x3 = x3 + x4 | 0;
155
+ x14 ^= x3;
156
+ x14 = x14 >>> 32 - 16 | x14 << 16;
157
+ x9 = x9 + x14 | 0;
158
+ x4 ^= x9;
159
+ x4 = x4 >>> 32 - 12 | x4 << 12;
160
+ x2 = x2 + x7 | 0;
161
+ x13 ^= x2;
162
+ x13 = x13 >>> 32 - 8 | x13 << 8;
163
+ x8 = x8 + x13 | 0;
164
+ x7 ^= x8;
165
+ x7 = x7 >>> 32 - 7 | x7 << 7;
166
+ x3 = x3 + x4 | 0;
167
+ x14 ^= x3;
168
+ x14 = x14 >>> 32 - 8 | x14 << 8;
169
+ x9 = x9 + x14 | 0;
170
+ x4 ^= x9;
171
+ x4 = x4 >>> 32 - 7 | x4 << 7;
172
+ x1 = x1 + x6 | 0;
173
+ x12 ^= x1;
174
+ x12 = x12 >>> 32 - 8 | x12 << 8;
175
+ x11 = x11 + x12 | 0;
176
+ x6 ^= x11;
177
+ x6 = x6 >>> 32 - 7 | x6 << 7;
178
+ x0 = x0 + x5 | 0;
179
+ x15 ^= x0;
180
+ x15 = x15 >>> 32 - 8 | x15 << 8;
181
+ x10 = x10 + x15 | 0;
182
+ x5 ^= x10;
183
+ x5 = x5 >>> 32 - 7 | x5 << 7;
184
+ }
185
+ writeUint32LE(x0 + j0 | 0, out, 0);
186
+ writeUint32LE(x1 + j1 | 0, out, 4);
187
+ writeUint32LE(x2 + j2 | 0, out, 8);
188
+ writeUint32LE(x3 + j3 | 0, out, 12);
189
+ writeUint32LE(x4 + j4 | 0, out, 16);
190
+ writeUint32LE(x5 + j5 | 0, out, 20);
191
+ writeUint32LE(x6 + j6 | 0, out, 24);
192
+ writeUint32LE(x7 + j7 | 0, out, 28);
193
+ writeUint32LE(x8 + j8 | 0, out, 32);
194
+ writeUint32LE(x9 + j9 | 0, out, 36);
195
+ writeUint32LE(x10 + j10 | 0, out, 40);
196
+ writeUint32LE(x11 + j11 | 0, out, 44);
197
+ writeUint32LE(x12 + j12 | 0, out, 48);
198
+ writeUint32LE(x13 + j13 | 0, out, 52);
199
+ writeUint32LE(x14 + j14 | 0, out, 56);
200
+ writeUint32LE(x15 + j15 | 0, out, 60);
201
+ }
202
+ function streamXOR(key, nonce, src, dst, nonceInplaceCounterLength = 0) {
203
+ if (key.length !== 32) {
204
+ throw new Error("ChaCha: key size must be 32 bytes");
205
+ }
206
+ if (dst.length < src.length) {
207
+ throw new Error("ChaCha: destination is shorter than source");
208
+ }
209
+ let nc;
210
+ let counterLength;
211
+ if (nonceInplaceCounterLength === 0) {
212
+ if (nonce.length !== 8 && nonce.length !== 12) {
213
+ throw new Error("ChaCha nonce must be 8 or 12 bytes");
214
+ }
215
+ nc = new Uint8Array(16);
216
+ counterLength = nc.length - nonce.length;
217
+ nc.set(nonce, counterLength);
218
+ } else {
219
+ if (nonce.length !== 16) {
220
+ throw new Error("ChaCha nonce with counter must be 16 bytes");
221
+ }
222
+ nc = nonce;
223
+ counterLength = nonceInplaceCounterLength;
224
+ }
225
+ const block = new Uint8Array(64);
226
+ for (let i = 0;i < src.length; i += 64) {
227
+ core(block, nc, key);
228
+ for (let j = i;j < i + 64 && j < src.length; j++) {
229
+ dst[j] = src[j] ^ block[j - i];
230
+ }
231
+ incrementCounter(nc, 0, counterLength);
232
+ }
233
+ wipe(block);
234
+ if (nonceInplaceCounterLength === 0) {
235
+ wipe(nc);
236
+ }
237
+ return dst;
238
+ }
239
+ function stream(key, nonce, dst, nonceInplaceCounterLength = 0) {
240
+ wipe(dst);
241
+ return streamXOR(key, nonce, dst, dst, nonceInplaceCounterLength);
242
+ }
243
+ function incrementCounter(counter, pos, len) {
244
+ let carry = 1;
245
+ while (len--) {
246
+ carry = carry + (counter[pos] & 255) | 0;
247
+ counter[pos] = carry & 255;
248
+ carry >>>= 8;
249
+ pos++;
250
+ }
251
+ if (carry > 0) {
252
+ throw new Error("ChaCha: counter overflow");
253
+ }
254
+ }
255
+
256
+ // ../../node_modules/@stablelib/constant-time/lib/constant-time.js
257
+ function compare(a, b) {
258
+ if (a.length !== b.length) {
259
+ return 0;
260
+ }
261
+ let result = 0;
262
+ for (let i = 0;i < a.length; i++) {
263
+ result |= a[i] ^ b[i];
264
+ }
265
+ return 1 & result - 1 >>> 8;
266
+ }
267
+ function equal(a, b) {
268
+ if (a.length === 0 || b.length === 0) {
269
+ return false;
270
+ }
271
+ return compare(a, b) !== 0;
272
+ }
273
+
274
+ // ../../node_modules/@stablelib/poly1305/lib/poly1305.js
275
+ var DIGEST_LENGTH = 16;
276
+
277
+ class Poly1305 {
278
+ digestLength = DIGEST_LENGTH;
279
+ _buffer = new Uint8Array(16);
280
+ _r = new Uint16Array(10);
281
+ _h = new Uint16Array(10);
282
+ _pad = new Uint16Array(8);
283
+ _leftover = 0;
284
+ _fin = 0;
285
+ _finished = false;
286
+ constructor(key) {
287
+ let t0 = key[0] | key[1] << 8;
288
+ this._r[0] = t0 & 8191;
289
+ let t1 = key[2] | key[3] << 8;
290
+ this._r[1] = (t0 >>> 13 | t1 << 3) & 8191;
291
+ let t2 = key[4] | key[5] << 8;
292
+ this._r[2] = (t1 >>> 10 | t2 << 6) & 7939;
293
+ let t3 = key[6] | key[7] << 8;
294
+ this._r[3] = (t2 >>> 7 | t3 << 9) & 8191;
295
+ let t4 = key[8] | key[9] << 8;
296
+ this._r[4] = (t3 >>> 4 | t4 << 12) & 255;
297
+ this._r[5] = t4 >>> 1 & 8190;
298
+ let t5 = key[10] | key[11] << 8;
299
+ this._r[6] = (t4 >>> 14 | t5 << 2) & 8191;
300
+ let t6 = key[12] | key[13] << 8;
301
+ this._r[7] = (t5 >>> 11 | t6 << 5) & 8065;
302
+ let t7 = key[14] | key[15] << 8;
303
+ this._r[8] = (t6 >>> 8 | t7 << 8) & 8191;
304
+ this._r[9] = t7 >>> 5 & 127;
305
+ this._pad[0] = key[16] | key[17] << 8;
306
+ this._pad[1] = key[18] | key[19] << 8;
307
+ this._pad[2] = key[20] | key[21] << 8;
308
+ this._pad[3] = key[22] | key[23] << 8;
309
+ this._pad[4] = key[24] | key[25] << 8;
310
+ this._pad[5] = key[26] | key[27] << 8;
311
+ this._pad[6] = key[28] | key[29] << 8;
312
+ this._pad[7] = key[30] | key[31] << 8;
313
+ }
314
+ _blocks(m, mpos, bytes) {
315
+ let hibit = this._fin ? 0 : 1 << 11;
316
+ let h0 = this._h[0], h1 = this._h[1], h2 = this._h[2], h3 = this._h[3], h4 = this._h[4], h5 = this._h[5], h6 = this._h[6], h7 = this._h[7], h8 = this._h[8], h9 = this._h[9];
317
+ let r0 = this._r[0], r1 = this._r[1], r2 = this._r[2], r3 = this._r[3], r4 = this._r[4], r5 = this._r[5], r6 = this._r[6], r7 = this._r[7], r8 = this._r[8], r9 = this._r[9];
318
+ while (bytes >= 16) {
319
+ let t0 = m[mpos + 0] | m[mpos + 1] << 8;
320
+ h0 += t0 & 8191;
321
+ let t1 = m[mpos + 2] | m[mpos + 3] << 8;
322
+ h1 += (t0 >>> 13 | t1 << 3) & 8191;
323
+ let t2 = m[mpos + 4] | m[mpos + 5] << 8;
324
+ h2 += (t1 >>> 10 | t2 << 6) & 8191;
325
+ let t3 = m[mpos + 6] | m[mpos + 7] << 8;
326
+ h3 += (t2 >>> 7 | t3 << 9) & 8191;
327
+ let t4 = m[mpos + 8] | m[mpos + 9] << 8;
328
+ h4 += (t3 >>> 4 | t4 << 12) & 8191;
329
+ h5 += t4 >>> 1 & 8191;
330
+ let t5 = m[mpos + 10] | m[mpos + 11] << 8;
331
+ h6 += (t4 >>> 14 | t5 << 2) & 8191;
332
+ let t6 = m[mpos + 12] | m[mpos + 13] << 8;
333
+ h7 += (t5 >>> 11 | t6 << 5) & 8191;
334
+ let t7 = m[mpos + 14] | m[mpos + 15] << 8;
335
+ h8 += (t6 >>> 8 | t7 << 8) & 8191;
336
+ h9 += t7 >>> 5 | hibit;
337
+ let c = 0;
338
+ let d0 = c;
339
+ d0 += h0 * r0;
340
+ d0 += h1 * (5 * r9);
341
+ d0 += h2 * (5 * r8);
342
+ d0 += h3 * (5 * r7);
343
+ d0 += h4 * (5 * r6);
344
+ c = d0 >>> 13;
345
+ d0 &= 8191;
346
+ d0 += h5 * (5 * r5);
347
+ d0 += h6 * (5 * r4);
348
+ d0 += h7 * (5 * r3);
349
+ d0 += h8 * (5 * r2);
350
+ d0 += h9 * (5 * r1);
351
+ c += d0 >>> 13;
352
+ d0 &= 8191;
353
+ let d1 = c;
354
+ d1 += h0 * r1;
355
+ d1 += h1 * r0;
356
+ d1 += h2 * (5 * r9);
357
+ d1 += h3 * (5 * r8);
358
+ d1 += h4 * (5 * r7);
359
+ c = d1 >>> 13;
360
+ d1 &= 8191;
361
+ d1 += h5 * (5 * r6);
362
+ d1 += h6 * (5 * r5);
363
+ d1 += h7 * (5 * r4);
364
+ d1 += h8 * (5 * r3);
365
+ d1 += h9 * (5 * r2);
366
+ c += d1 >>> 13;
367
+ d1 &= 8191;
368
+ let d2 = c;
369
+ d2 += h0 * r2;
370
+ d2 += h1 * r1;
371
+ d2 += h2 * r0;
372
+ d2 += h3 * (5 * r9);
373
+ d2 += h4 * (5 * r8);
374
+ c = d2 >>> 13;
375
+ d2 &= 8191;
376
+ d2 += h5 * (5 * r7);
377
+ d2 += h6 * (5 * r6);
378
+ d2 += h7 * (5 * r5);
379
+ d2 += h8 * (5 * r4);
380
+ d2 += h9 * (5 * r3);
381
+ c += d2 >>> 13;
382
+ d2 &= 8191;
383
+ let d3 = c;
384
+ d3 += h0 * r3;
385
+ d3 += h1 * r2;
386
+ d3 += h2 * r1;
387
+ d3 += h3 * r0;
388
+ d3 += h4 * (5 * r9);
389
+ c = d3 >>> 13;
390
+ d3 &= 8191;
391
+ d3 += h5 * (5 * r8);
392
+ d3 += h6 * (5 * r7);
393
+ d3 += h7 * (5 * r6);
394
+ d3 += h8 * (5 * r5);
395
+ d3 += h9 * (5 * r4);
396
+ c += d3 >>> 13;
397
+ d3 &= 8191;
398
+ let d4 = c;
399
+ d4 += h0 * r4;
400
+ d4 += h1 * r3;
401
+ d4 += h2 * r2;
402
+ d4 += h3 * r1;
403
+ d4 += h4 * r0;
404
+ c = d4 >>> 13;
405
+ d4 &= 8191;
406
+ d4 += h5 * (5 * r9);
407
+ d4 += h6 * (5 * r8);
408
+ d4 += h7 * (5 * r7);
409
+ d4 += h8 * (5 * r6);
410
+ d4 += h9 * (5 * r5);
411
+ c += d4 >>> 13;
412
+ d4 &= 8191;
413
+ let d5 = c;
414
+ d5 += h0 * r5;
415
+ d5 += h1 * r4;
416
+ d5 += h2 * r3;
417
+ d5 += h3 * r2;
418
+ d5 += h4 * r1;
419
+ c = d5 >>> 13;
420
+ d5 &= 8191;
421
+ d5 += h5 * r0;
422
+ d5 += h6 * (5 * r9);
423
+ d5 += h7 * (5 * r8);
424
+ d5 += h8 * (5 * r7);
425
+ d5 += h9 * (5 * r6);
426
+ c += d5 >>> 13;
427
+ d5 &= 8191;
428
+ let d6 = c;
429
+ d6 += h0 * r6;
430
+ d6 += h1 * r5;
431
+ d6 += h2 * r4;
432
+ d6 += h3 * r3;
433
+ d6 += h4 * r2;
434
+ c = d6 >>> 13;
435
+ d6 &= 8191;
436
+ d6 += h5 * r1;
437
+ d6 += h6 * r0;
438
+ d6 += h7 * (5 * r9);
439
+ d6 += h8 * (5 * r8);
440
+ d6 += h9 * (5 * r7);
441
+ c += d6 >>> 13;
442
+ d6 &= 8191;
443
+ let d7 = c;
444
+ d7 += h0 * r7;
445
+ d7 += h1 * r6;
446
+ d7 += h2 * r5;
447
+ d7 += h3 * r4;
448
+ d7 += h4 * r3;
449
+ c = d7 >>> 13;
450
+ d7 &= 8191;
451
+ d7 += h5 * r2;
452
+ d7 += h6 * r1;
453
+ d7 += h7 * r0;
454
+ d7 += h8 * (5 * r9);
455
+ d7 += h9 * (5 * r8);
456
+ c += d7 >>> 13;
457
+ d7 &= 8191;
458
+ let d8 = c;
459
+ d8 += h0 * r8;
460
+ d8 += h1 * r7;
461
+ d8 += h2 * r6;
462
+ d8 += h3 * r5;
463
+ d8 += h4 * r4;
464
+ c = d8 >>> 13;
465
+ d8 &= 8191;
466
+ d8 += h5 * r3;
467
+ d8 += h6 * r2;
468
+ d8 += h7 * r1;
469
+ d8 += h8 * r0;
470
+ d8 += h9 * (5 * r9);
471
+ c += d8 >>> 13;
472
+ d8 &= 8191;
473
+ let d9 = c;
474
+ d9 += h0 * r9;
475
+ d9 += h1 * r8;
476
+ d9 += h2 * r7;
477
+ d9 += h3 * r6;
478
+ d9 += h4 * r5;
479
+ c = d9 >>> 13;
480
+ d9 &= 8191;
481
+ d9 += h5 * r4;
482
+ d9 += h6 * r3;
483
+ d9 += h7 * r2;
484
+ d9 += h8 * r1;
485
+ d9 += h9 * r0;
486
+ c += d9 >>> 13;
487
+ d9 &= 8191;
488
+ c = (c << 2) + c | 0;
489
+ c = c + d0 | 0;
490
+ d0 = c & 8191;
491
+ c = c >>> 13;
492
+ d1 += c;
493
+ h0 = d0;
494
+ h1 = d1;
495
+ h2 = d2;
496
+ h3 = d3;
497
+ h4 = d4;
498
+ h5 = d5;
499
+ h6 = d6;
500
+ h7 = d7;
501
+ h8 = d8;
502
+ h9 = d9;
503
+ mpos += 16;
504
+ bytes -= 16;
505
+ }
506
+ this._h[0] = h0;
507
+ this._h[1] = h1;
508
+ this._h[2] = h2;
509
+ this._h[3] = h3;
510
+ this._h[4] = h4;
511
+ this._h[5] = h5;
512
+ this._h[6] = h6;
513
+ this._h[7] = h7;
514
+ this._h[8] = h8;
515
+ this._h[9] = h9;
516
+ }
517
+ finish(mac, macpos = 0) {
518
+ const g = new Uint16Array(10);
519
+ let c;
520
+ let mask;
521
+ let f;
522
+ let i;
523
+ if (this._leftover) {
524
+ i = this._leftover;
525
+ this._buffer[i++] = 1;
526
+ for (;i < 16; i++) {
527
+ this._buffer[i] = 0;
528
+ }
529
+ this._fin = 1;
530
+ this._blocks(this._buffer, 0, 16);
531
+ }
532
+ c = this._h[1] >>> 13;
533
+ this._h[1] &= 8191;
534
+ for (i = 2;i < 10; i++) {
535
+ this._h[i] += c;
536
+ c = this._h[i] >>> 13;
537
+ this._h[i] &= 8191;
538
+ }
539
+ this._h[0] += c * 5;
540
+ c = this._h[0] >>> 13;
541
+ this._h[0] &= 8191;
542
+ this._h[1] += c;
543
+ c = this._h[1] >>> 13;
544
+ this._h[1] &= 8191;
545
+ this._h[2] += c;
546
+ g[0] = this._h[0] + 5;
547
+ c = g[0] >>> 13;
548
+ g[0] &= 8191;
549
+ for (i = 1;i < 10; i++) {
550
+ g[i] = this._h[i] + c;
551
+ c = g[i] >>> 13;
552
+ g[i] &= 8191;
553
+ }
554
+ g[9] -= 1 << 13;
555
+ mask = (c ^ 1) - 1;
556
+ for (i = 0;i < 10; i++) {
557
+ g[i] &= mask;
558
+ }
559
+ mask = ~mask;
560
+ for (i = 0;i < 10; i++) {
561
+ this._h[i] = this._h[i] & mask | g[i];
562
+ }
563
+ this._h[0] = (this._h[0] | this._h[1] << 13) & 65535;
564
+ this._h[1] = (this._h[1] >>> 3 | this._h[2] << 10) & 65535;
565
+ this._h[2] = (this._h[2] >>> 6 | this._h[3] << 7) & 65535;
566
+ this._h[3] = (this._h[3] >>> 9 | this._h[4] << 4) & 65535;
567
+ this._h[4] = (this._h[4] >>> 12 | this._h[5] << 1 | this._h[6] << 14) & 65535;
568
+ this._h[5] = (this._h[6] >>> 2 | this._h[7] << 11) & 65535;
569
+ this._h[6] = (this._h[7] >>> 5 | this._h[8] << 8) & 65535;
570
+ this._h[7] = (this._h[8] >>> 8 | this._h[9] << 5) & 65535;
571
+ f = this._h[0] + this._pad[0];
572
+ this._h[0] = f & 65535;
573
+ for (i = 1;i < 8; i++) {
574
+ f = (this._h[i] + this._pad[i] | 0) + (f >>> 16) | 0;
575
+ this._h[i] = f & 65535;
576
+ }
577
+ mac[macpos + 0] = this._h[0] >>> 0;
578
+ mac[macpos + 1] = this._h[0] >>> 8;
579
+ mac[macpos + 2] = this._h[1] >>> 0;
580
+ mac[macpos + 3] = this._h[1] >>> 8;
581
+ mac[macpos + 4] = this._h[2] >>> 0;
582
+ mac[macpos + 5] = this._h[2] >>> 8;
583
+ mac[macpos + 6] = this._h[3] >>> 0;
584
+ mac[macpos + 7] = this._h[3] >>> 8;
585
+ mac[macpos + 8] = this._h[4] >>> 0;
586
+ mac[macpos + 9] = this._h[4] >>> 8;
587
+ mac[macpos + 10] = this._h[5] >>> 0;
588
+ mac[macpos + 11] = this._h[5] >>> 8;
589
+ mac[macpos + 12] = this._h[6] >>> 0;
590
+ mac[macpos + 13] = this._h[6] >>> 8;
591
+ mac[macpos + 14] = this._h[7] >>> 0;
592
+ mac[macpos + 15] = this._h[7] >>> 8;
593
+ this._finished = true;
594
+ return this;
595
+ }
596
+ update(m) {
597
+ let mpos = 0;
598
+ let bytes = m.length;
599
+ let want;
600
+ if (this._leftover) {
601
+ want = 16 - this._leftover;
602
+ if (want > bytes) {
603
+ want = bytes;
604
+ }
605
+ for (let i = 0;i < want; i++) {
606
+ this._buffer[this._leftover + i] = m[mpos + i];
607
+ }
608
+ bytes -= want;
609
+ mpos += want;
610
+ this._leftover += want;
611
+ if (this._leftover < 16) {
612
+ return this;
613
+ }
614
+ this._blocks(this._buffer, 0, 16);
615
+ this._leftover = 0;
616
+ }
617
+ if (bytes >= 16) {
618
+ want = bytes - bytes % 16;
619
+ this._blocks(m, mpos, want);
620
+ mpos += want;
621
+ bytes -= want;
622
+ }
623
+ if (bytes) {
624
+ for (let i = 0;i < bytes; i++) {
625
+ this._buffer[this._leftover + i] = m[mpos + i];
626
+ }
627
+ this._leftover += bytes;
628
+ }
629
+ return this;
630
+ }
631
+ digest() {
632
+ if (this._finished) {
633
+ throw new Error("Poly1305 was finished");
634
+ }
635
+ let mac = new Uint8Array(16);
636
+ this.finish(mac);
637
+ return mac;
638
+ }
639
+ clean() {
640
+ wipe(this._buffer);
641
+ wipe(this._r);
642
+ wipe(this._h);
643
+ wipe(this._pad);
644
+ this._leftover = 0;
645
+ this._fin = 0;
646
+ this._finished = true;
647
+ return this;
648
+ }
649
+ }
650
+
651
+ // ../../node_modules/@stablelib/chacha20poly1305/lib/chacha20poly1305.js
652
+ var KEY_LENGTH = 32;
653
+ var NONCE_LENGTH = 12;
654
+ var TAG_LENGTH = 16;
655
+ var ZEROS = new Uint8Array(16);
656
+
657
+ class ChaCha20Poly1305 {
658
+ nonceLength = NONCE_LENGTH;
659
+ tagLength = TAG_LENGTH;
660
+ _key;
661
+ constructor(key) {
662
+ if (key.length !== KEY_LENGTH) {
663
+ throw new Error("ChaCha20Poly1305 needs 32-byte key");
664
+ }
665
+ this._key = new Uint8Array(key);
666
+ }
667
+ seal(nonce, plaintext, associatedData, dst) {
668
+ if (nonce.length > 16) {
669
+ throw new Error("ChaCha20Poly1305: incorrect nonce length");
670
+ }
671
+ const counter = new Uint8Array(16);
672
+ counter.set(nonce, counter.length - nonce.length);
673
+ const authKey = new Uint8Array(32);
674
+ stream(this._key, counter, authKey, 4);
675
+ const resultLength = plaintext.length + this.tagLength;
676
+ let result;
677
+ if (dst) {
678
+ if (dst.length !== resultLength) {
679
+ throw new Error("ChaCha20Poly1305: incorrect destination length");
680
+ }
681
+ result = dst;
682
+ } else {
683
+ result = new Uint8Array(resultLength);
684
+ }
685
+ streamXOR(this._key, counter, plaintext, result, 4);
686
+ this._authenticate(result.subarray(result.length - this.tagLength, result.length), authKey, result.subarray(0, result.length - this.tagLength), associatedData);
687
+ wipe(counter);
688
+ return result;
689
+ }
690
+ open(nonce, sealed, associatedData, dst) {
691
+ if (nonce.length > 16) {
692
+ throw new Error("ChaCha20Poly1305: incorrect nonce length");
693
+ }
694
+ if (sealed.length < this.tagLength) {
695
+ return null;
696
+ }
697
+ const counter = new Uint8Array(16);
698
+ counter.set(nonce, counter.length - nonce.length);
699
+ const authKey = new Uint8Array(32);
700
+ stream(this._key, counter, authKey, 4);
701
+ const calculatedTag = new Uint8Array(this.tagLength);
702
+ this._authenticate(calculatedTag, authKey, sealed.subarray(0, sealed.length - this.tagLength), associatedData);
703
+ if (!equal(calculatedTag, sealed.subarray(sealed.length - this.tagLength, sealed.length))) {
704
+ return null;
705
+ }
706
+ const resultLength = sealed.length - this.tagLength;
707
+ let result;
708
+ if (dst) {
709
+ if (dst.length !== resultLength) {
710
+ throw new Error("ChaCha20Poly1305: incorrect destination length");
711
+ }
712
+ result = dst;
713
+ } else {
714
+ result = new Uint8Array(resultLength);
715
+ }
716
+ streamXOR(this._key, counter, sealed.subarray(0, sealed.length - this.tagLength), result, 4);
717
+ wipe(counter);
718
+ return result;
719
+ }
720
+ clean() {
721
+ wipe(this._key);
722
+ return this;
723
+ }
724
+ _authenticate(tagOut, authKey, ciphertext, associatedData) {
725
+ const h = new Poly1305(authKey);
726
+ if (associatedData) {
727
+ h.update(associatedData);
728
+ if (associatedData.length % 16 > 0) {
729
+ h.update(ZEROS.subarray(associatedData.length % 16));
730
+ }
731
+ }
732
+ h.update(ciphertext);
733
+ if (ciphertext.length % 16 > 0) {
734
+ h.update(ZEROS.subarray(ciphertext.length % 16));
735
+ }
736
+ const length = new Uint8Array(8);
737
+ if (associatedData) {
738
+ writeUint64LE(associatedData.length, length);
739
+ }
740
+ h.update(length);
741
+ writeUint64LE(ciphertext.length, length);
742
+ h.update(length);
743
+ const tag = h.digest();
744
+ for (let i = 0;i < tag.length; i++) {
745
+ tagOut[i] = tag[i];
746
+ }
747
+ h.clean();
748
+ wipe(tag);
749
+ wipe(length);
750
+ }
751
+ }
752
+
753
+ // src/crypto/chacha20.ts
754
+ var CHACHA20_AUTH_TAG_LENGTH = 16;
755
+ var CHACHA20_NONCE_LENGTH = 12;
756
+ function decrypt(key, nonce, aad, ciphertext, authTag) {
757
+ nonce = padNonce(nonce);
758
+ const chacha = new ChaCha20Poly1305(key);
759
+ const sealed = Buffer.concat([ciphertext, authTag]);
760
+ const plaintext = chacha.open(nonce, sealed, aad ?? undefined);
761
+ if (!plaintext) {
762
+ throw new Error("Decryption failed: authentication tag mismatch");
763
+ }
764
+ return Buffer.from(plaintext);
765
+ }
766
+ function encrypt(key, nonce, aad, plaintext) {
767
+ nonce = padNonce(nonce);
768
+ const chacha = new ChaCha20Poly1305(key);
769
+ const sealed = chacha.seal(nonce, plaintext, aad ?? undefined);
770
+ const ciphertext = Buffer.from(sealed.subarray(0, sealed.length - CHACHA20_AUTH_TAG_LENGTH));
771
+ const authTag = Buffer.from(sealed.subarray(sealed.length - CHACHA20_AUTH_TAG_LENGTH));
772
+ return {
773
+ ciphertext,
774
+ authTag
775
+ };
776
+ }
777
+ function padNonce(nonce) {
778
+ if (nonce.length >= CHACHA20_NONCE_LENGTH) {
779
+ return nonce;
780
+ }
781
+ return Buffer.concat([
782
+ Buffer.alloc(CHACHA20_NONCE_LENGTH - nonce.length, 0),
783
+ nonce
784
+ ]);
785
+ }
786
+ // src/crypto/curve25519.ts
787
+ var exports_curve25519 = {};
788
+ __export(exports_curve25519, {
789
+ generateSharedSecKey: () => generateSharedSecKey,
790
+ generateKeyPair: () => generateKeyPair
791
+ });
792
+ import tweetnacl from "tweetnacl";
793
+ function generateKeyPair() {
794
+ const keyPair = tweetnacl.box.keyPair();
795
+ return {
796
+ publicKey: keyPair.publicKey,
797
+ secretKey: keyPair.secretKey
798
+ };
799
+ }
800
+ function generateSharedSecKey(priKey, pubKey) {
801
+ return tweetnacl.scalarMult(priKey, pubKey);
802
+ }
803
+ // src/crypto/hkdf.ts
804
+ import { hkdfSync } from "node:crypto";
805
+ function hkdf_default(options) {
806
+ return Buffer.from(hkdfSync(options.hash, options.key, options.salt, options.info, options.length));
807
+ }
808
+ // src/discovery/discovery.ts
809
+ import mdns from "node-dns-sd";
810
+
811
+ // src/cli.ts
812
+ import { createInterface } from "node:readline";
813
+ var cli = createInterface({
814
+ input: process.stdin,
815
+ output: process.stdout
816
+ });
817
+ async function prompt(message) {
818
+ return await new Promise((resolve) => cli.question(`${message}: `, resolve));
819
+ }
820
+ async function waitFor(ms) {
821
+ return new Promise((resolve) => setTimeout(resolve, ms));
822
+ }
823
+
824
+ class Reporter {
825
+ #enabled = [];
826
+ all() {
827
+ this.#enabled = ["debug", "error", "info", "net", "raw", "warn"];
828
+ }
829
+ disable(group) {
830
+ if (this.#enabled.includes(group)) {
831
+ this.#enabled.splice(this.#enabled.indexOf(group), 1);
832
+ }
833
+ }
834
+ enable(group) {
835
+ if (!this.#enabled.includes(group)) {
836
+ this.#enabled.push(group);
837
+ }
838
+ }
839
+ isEnabled(group) {
840
+ return this.#enabled.includes(group);
841
+ }
842
+ debug(...data) {
843
+ this.isEnabled("debug") && console.debug(`\x1B[36m[debug]\x1B[39m`, ...data);
844
+ }
845
+ error(...data) {
846
+ this.isEnabled("error") && console.error(`\x1B[31m[error]\x1B[39m`, ...data);
847
+ }
848
+ info(...data) {
849
+ this.isEnabled("info") && console.info(`\x1B[32m[info]\x1B[39m`, ...data);
850
+ }
851
+ net(...data) {
852
+ this.isEnabled("net") && console.info(`\x1B[33m[net]\x1B[39m`, ...data);
853
+ }
854
+ raw(...data) {
855
+ this.isEnabled("raw") && console.log(`\x1B[34m[raw]\x1B[39m`, ...data);
856
+ }
857
+ warn(...data) {
858
+ this.isEnabled("warn") && console.warn(`\x1B[33m[warn]\x1B[39m`, ...data);
859
+ }
860
+ }
861
+ var reporter = new Reporter;
862
+
863
+ // src/const.ts
864
+ var AIRPLAY_TRANSIENT_PIN = "3939";
865
+ var HTTP_TIMEOUT = 6000;
866
+ var SOCKET_TIMEOUT = 1e4;
867
+ var AIRPLAY_SERVICE = "_airplay._tcp.local";
868
+ var COMPANION_LINK_SERVICE = "_companion-link._tcp.local";
869
+ var RAOP_SERVICE = "_raop._tcp.local";
870
+
871
+ // src/discovery/discovery.ts
872
+ class Discovery {
873
+ #service;
874
+ constructor(service) {
875
+ this.#service = service;
876
+ }
877
+ async find() {
878
+ return await mdns.discover({
879
+ name: this.#service
880
+ });
881
+ }
882
+ async findUntil(fqdn, tries = 10, timeout = 1000) {
883
+ while (tries > 0) {
884
+ const devices = await this.find();
885
+ const device = devices.find((device2) => device2.fqdn === fqdn);
886
+ if (device) {
887
+ return device;
888
+ }
889
+ console.log();
890
+ console.log(`Device not found, retrying in ${timeout}ms...`);
891
+ console.log(devices.map((d) => ` ● ${d.fqdn}`).join(`
892
+ `));
893
+ tries--;
894
+ if (tries === 0) {
895
+ throw new Error("Device not found after serveral tries, aborting.");
896
+ }
897
+ await waitFor(timeout);
898
+ }
899
+ }
900
+ static airplay() {
901
+ return new Discovery(AIRPLAY_SERVICE);
902
+ }
903
+ static companionLink() {
904
+ return new Discovery(COMPANION_LINK_SERVICE);
905
+ }
906
+ static raop() {
907
+ return new Discovery(RAOP_SERVICE);
908
+ }
909
+ }
910
+ // src/net/getLocalIP.ts
911
+ import { networkInterfaces } from "node:os";
912
+ function getLocalIP_default() {
913
+ const interfaces = networkInterfaces();
914
+ for (const name of Object.keys(interfaces)) {
915
+ const iface = interfaces[name];
916
+ if (!iface) {
917
+ continue;
918
+ }
919
+ for (const net of iface) {
920
+ if (net.internal || net.family !== "IPv4") {
921
+ continue;
922
+ }
923
+ if (net.address && net.address !== "127.0.0.1") {
924
+ return net.address;
925
+ }
926
+ }
927
+ }
928
+ return null;
929
+ }
930
+ // src/net/getMacAddress.ts
931
+ import { networkInterfaces as networkInterfaces2 } from "node:os";
932
+ function getMacAddress_default() {
933
+ const interfaces = networkInterfaces2();
934
+ for (const name of Object.keys(interfaces)) {
935
+ const iface = interfaces[name];
936
+ if (!iface) {
937
+ continue;
938
+ }
939
+ for (const net of iface) {
940
+ if (net.internal || net.family !== "IPv4") {
941
+ continue;
942
+ }
943
+ if (net.mac && net.mac !== "00:00:00:00:00:00") {
944
+ return net.mac.toUpperCase();
945
+ }
946
+ }
947
+ }
948
+ return "00:00:00:00:00:00";
949
+ }
950
+ // src/net/timing.ts
951
+ import { createSocket } from "node:dgram";
952
+ import { NTP } from "@basmilius/apple-encoding";
953
+ class timing_default {
954
+ get port() {
955
+ return this.#port;
956
+ }
957
+ #socket;
958
+ #port = 0;
959
+ constructor() {
960
+ this.#socket = createSocket("udp4");
961
+ this.#socket.on("error", (err) => this.#onError(err));
962
+ this.#socket.on("message", (data, info) => this.#onMessage(data, info));
963
+ }
964
+ async close() {
965
+ this.#socket.close();
966
+ this.#port = 0;
967
+ }
968
+ async listen() {
969
+ return new Promise((resolve) => {
970
+ this.#socket.once("listening", () => this.#onListening());
971
+ this.#socket.bind(0, resolve);
972
+ });
973
+ }
974
+ async#onError(err) {
975
+ reporter.error("Timing server error", err);
976
+ }
977
+ async#onListening() {
978
+ const { port } = this.#socket.address();
979
+ this.#port = port;
980
+ }
981
+ async#onMessage(data, info) {
982
+ const request = NTP.decode(data);
983
+ const ntp = NTP.now();
984
+ const [receivedSeconds, receivedFraction] = NTP.parts(ntp);
985
+ reporter.info(`Timing server ntp=${ntp} receivedSeconds=${receivedSeconds} receivedFraction=${receivedFraction}`);
986
+ const response = NTP.encode({
987
+ proto: request.proto,
988
+ type: 83 | 128,
989
+ seqno: request.seqno,
990
+ padding: 0,
991
+ reftime_sec: request.sendtime_sec,
992
+ reftime_frac: request.sendtime_frac,
993
+ recvtime_sec: receivedSeconds,
994
+ recvtime_frac: receivedFraction,
995
+ sendtime_sec: receivedSeconds,
996
+ sendtime_frac: receivedFraction
997
+ });
998
+ this.#socket.send(response, info.port, info.address);
999
+ }
1000
+ }
1001
+ // src/connection.ts
1002
+ import { EventEmitter } from "node:events";
1003
+ import { Socket as Socket2 } from "node:net";
1004
+
1005
+ // src/symbols.ts
1006
+ var ENCRYPTION = Symbol();
1007
+
1008
+ // src/connection.ts
1009
+ class Connection extends EventEmitter {
1010
+ get address() {
1011
+ return this.#address;
1012
+ }
1013
+ get port() {
1014
+ return this.#port;
1015
+ }
1016
+ get isConnected() {
1017
+ return this.#state === "connected";
1018
+ }
1019
+ get state() {
1020
+ return this.#state;
1021
+ }
1022
+ #address;
1023
+ #port;
1024
+ #bindings;
1025
+ #debug = false;
1026
+ #retryAttempt = 0;
1027
+ #retryAttempts = 3;
1028
+ #retryEnabled = true;
1029
+ #retryInterval = 3000;
1030
+ #retryTimeout;
1031
+ #socket;
1032
+ #state;
1033
+ #connectPromise;
1034
+ constructor(address, port) {
1035
+ super();
1036
+ this.#address = address;
1037
+ this.#port = port;
1038
+ this.#bindings = {
1039
+ onClose: this.#onClose.bind(this),
1040
+ onConnect: this.#onConnect.bind(this),
1041
+ onData: this.#onData.bind(this),
1042
+ onEnd: this.#onEnd.bind(this),
1043
+ onError: this.#onError.bind(this),
1044
+ onTimeout: this.#onTimeout.bind(this)
1045
+ };
1046
+ this.#state = "disconnected";
1047
+ }
1048
+ async connect() {
1049
+ if (this.#state === "connected") {
1050
+ return;
1051
+ }
1052
+ if (this.#state === "connecting") {
1053
+ throw new Error("A connection is already being established.");
1054
+ }
1055
+ this.#retryEnabled = true;
1056
+ this.#retryAttempt = 0;
1057
+ return this.#attemptConnect();
1058
+ }
1059
+ async disconnect() {
1060
+ if (this.#retryTimeout) {
1061
+ clearTimeout(this.#retryTimeout);
1062
+ this.#retryTimeout = undefined;
1063
+ }
1064
+ this.#retryEnabled = false;
1065
+ if (!this.#socket || this.#state === "disconnected") {
1066
+ return;
1067
+ }
1068
+ return new Promise((resolve) => {
1069
+ this.#state = "closing";
1070
+ this.#socket.once("close", () => {
1071
+ this.#cleanup();
1072
+ resolve();
1073
+ });
1074
+ this.#socket.end();
1075
+ });
1076
+ }
1077
+ debug(enabled) {
1078
+ this.#debug = enabled;
1079
+ return this;
1080
+ }
1081
+ retry(attempts, interval = 3000) {
1082
+ this.#retryAttempts = attempts;
1083
+ this.#retryInterval = interval;
1084
+ return this;
1085
+ }
1086
+ async write(data) {
1087
+ if (!this.#socket || this.#state !== "connected") {
1088
+ throw new Error("Cannot write to a disconnected connection.");
1089
+ }
1090
+ return new Promise((resolve, reject) => {
1091
+ this.#socket.write(data, (err) => err ? reject(err) : resolve());
1092
+ });
1093
+ }
1094
+ async#attemptConnect() {
1095
+ return new Promise((resolve, reject) => {
1096
+ this.#state = "connecting";
1097
+ this.#connectPromise = { resolve, reject };
1098
+ this.#socket = new Socket2;
1099
+ this.#socket.setTimeout(SOCKET_TIMEOUT);
1100
+ this.#socket.on("close", this.#bindings.onClose);
1101
+ this.#socket.on("connect", this.#bindings.onConnect);
1102
+ this.#socket.on("data", this.#bindings.onData);
1103
+ this.#socket.on("end", this.#bindings.onEnd);
1104
+ this.#socket.on("error", this.#bindings.onError);
1105
+ this.#socket.on("timeout", this.#bindings.onTimeout);
1106
+ reporter.net(`Connecting to ${this.#address}:${this.#port}...`);
1107
+ this.#socket.connect({
1108
+ host: this.#address,
1109
+ port: this.#port,
1110
+ keepAlive: true
1111
+ });
1112
+ });
1113
+ }
1114
+ #cleanup() {
1115
+ if (this.#socket) {
1116
+ this.#socket.removeAllListeners();
1117
+ this.#socket.destroy();
1118
+ this.#socket = undefined;
1119
+ }
1120
+ this.#state = "disconnected";
1121
+ this.#connectPromise = undefined;
1122
+ }
1123
+ #scheduleRetry(err) {
1124
+ if (!this.#retryEnabled || this.#retryAttempt >= this.#retryAttempts) {
1125
+ this.#state = "failed";
1126
+ this.#connectPromise?.reject(err);
1127
+ this.#connectPromise = undefined;
1128
+ return;
1129
+ }
1130
+ this.#retryAttempt++;
1131
+ reporter.net(`Retry attempt ${this.#retryAttempt} / ${this.#retryAttempts} in ${this.#retryInterval}ms...`);
1132
+ const { resolve, reject } = this.#connectPromise;
1133
+ this.#cleanup();
1134
+ this.#retryTimeout = setTimeout(async () => {
1135
+ this.#retryTimeout = undefined;
1136
+ try {
1137
+ this.#connectPromise = { resolve, reject };
1138
+ await this.#attemptConnect();
1139
+ resolve();
1140
+ } catch (retryErr) {}
1141
+ }, this.#retryInterval);
1142
+ }
1143
+ #onClose(hadError) {
1144
+ const wasConnected = this.#state === "connected";
1145
+ if (this.#state !== "closing") {
1146
+ this.#state = "disconnected";
1147
+ reporter.net(`Connection closed (${hadError ? "with error" : "normally"}).`);
1148
+ }
1149
+ this.emit("close", hadError);
1150
+ if (wasConnected && this.#retryEnabled && hadError) {
1151
+ this.#scheduleRetry(new Error("Connection closed unexpectedly."));
1152
+ }
1153
+ }
1154
+ #onConnect() {
1155
+ this.#state = "connected";
1156
+ this.#retryAttempt = 0;
1157
+ this.#socket.setKeepAlive(true, 1e4);
1158
+ this.#socket.setTimeout(0);
1159
+ this.emit("connect");
1160
+ this.#connectPromise?.resolve();
1161
+ this.#connectPromise = undefined;
1162
+ }
1163
+ #onData(data) {
1164
+ if (this.#debug) {
1165
+ const cutoff = Math.min(data.byteLength, 64);
1166
+ reporter.debug(`Received ${data.byteLength} bytes of data.`);
1167
+ reporter.debug(`hex=${data.subarray(0, cutoff).toString("hex")}`);
1168
+ reporter.debug(`ascii=${data.toString("ascii").replace(/[^\x20-\x7E]/g, ".").substring(0, cutoff)}`);
1169
+ }
1170
+ this.emit("data", data);
1171
+ }
1172
+ #onEnd() {
1173
+ this.emit("end");
1174
+ }
1175
+ #onError(err) {
1176
+ reporter.error(`Connection error: ${err.message}`);
1177
+ this.emit("error", err);
1178
+ if (this.#state === "connecting") {
1179
+ this.#scheduleRetry(err);
1180
+ } else {
1181
+ this.#state = "failed";
1182
+ }
1183
+ }
1184
+ #onTimeout() {
1185
+ reporter.error("Connection timed out.");
1186
+ const err = new Error("Connection timed out.");
1187
+ this.emit("timeout");
1188
+ this.emit("error", err);
1189
+ if (this.#state === "connecting") {
1190
+ this.#scheduleRetry(err);
1191
+ } else {
1192
+ this.#state = "failed";
1193
+ this.#socket?.destroy();
1194
+ }
1195
+ }
1196
+ }
1197
+
1198
+ class EncryptionAwareConnection extends Connection {
1199
+ get isEncrypted() {
1200
+ return !!this[ENCRYPTION];
1201
+ }
1202
+ [ENCRYPTION];
1203
+ async enableEncryption(readKey, writeKey) {
1204
+ this[ENCRYPTION] = new EncryptionState(readKey, writeKey);
1205
+ }
1206
+ }
1207
+
1208
+ class EncryptionState {
1209
+ readKey;
1210
+ readCount;
1211
+ writeKey;
1212
+ writeCount;
1213
+ constructor(readKey, writeKey) {
1214
+ this.readCount = 0;
1215
+ this.readKey = readKey;
1216
+ this.writeCount = 0;
1217
+ this.writeKey = writeKey;
1218
+ }
1219
+ }
1220
+ // src/pairing.ts
1221
+ import { OPack, TLV8 } from "@basmilius/apple-encoding";
1222
+ import { SRP, SrpClient } from "fast-srp-hap";
1223
+ import { v4 as uuid } from "uuid";
1224
+ import tweetnacl2 from "tweetnacl";
1225
+
1226
+ class AccessoryPair {
1227
+ #name;
1228
+ #pairingId;
1229
+ #requestHandler;
1230
+ #publicKey;
1231
+ #secretKey;
1232
+ #srp;
1233
+ constructor(requestHandler) {
1234
+ this.#name = "basmilius/apple-protocols";
1235
+ this.#pairingId = Buffer.from(uuid().toUpperCase());
1236
+ this.#requestHandler = requestHandler;
1237
+ }
1238
+ async start() {
1239
+ const keyPair = tweetnacl2.sign.keyPair();
1240
+ this.#publicKey = Buffer.from(keyPair.publicKey);
1241
+ this.#secretKey = Buffer.from(keyPair.secretKey);
1242
+ }
1243
+ async pin(askPin) {
1244
+ const m1 = await this.m1();
1245
+ const m2 = await this.m2(m1, await askPin());
1246
+ const m3 = await this.m3(m2);
1247
+ const m4 = await this.m4(m3);
1248
+ const m5 = await this.m5(m4);
1249
+ const m6 = await this.m6(m4, m5);
1250
+ if (!m6) {
1251
+ throw new Error("Pairing failed, could not get accessory keys.");
1252
+ }
1253
+ return m6;
1254
+ }
1255
+ async transient() {
1256
+ const m1 = await this.m1([[TLV8.Value.Flags, TLV8.Flags.TransientPairing]]);
1257
+ const m2 = await this.m2(m1);
1258
+ const m3 = await this.m3(m2);
1259
+ const m4 = await this.m4(m3);
1260
+ const accessoryToControllerKey = hkdf_default({
1261
+ hash: "sha512",
1262
+ key: m4.sharedSecret,
1263
+ length: 32,
1264
+ salt: Buffer.from("Control-Salt"),
1265
+ info: Buffer.from("Control-Read-Encryption-Key")
1266
+ });
1267
+ const controllerToAccessoryKey = hkdf_default({
1268
+ hash: "sha512",
1269
+ key: m4.sharedSecret,
1270
+ length: 32,
1271
+ salt: Buffer.from("Control-Salt"),
1272
+ info: Buffer.from("Control-Write-Encryption-Key")
1273
+ });
1274
+ return {
1275
+ pairingId: this.#pairingId,
1276
+ sharedSecret: m4.sharedSecret,
1277
+ accessoryToControllerKey,
1278
+ controllerToAccessoryKey
1279
+ };
1280
+ }
1281
+ async m1(additionalTlv = []) {
1282
+ const response = await this.#requestHandler("m1", TLV8.encode([
1283
+ [TLV8.Value.Method, TLV8.Method.PairSetup],
1284
+ [TLV8.Value.State, TLV8.State.M1],
1285
+ ...additionalTlv
1286
+ ]));
1287
+ const data = tlv(response);
1288
+ const publicKey = data.get(TLV8.Value.PublicKey);
1289
+ const salt = data.get(TLV8.Value.Salt);
1290
+ return { publicKey, salt };
1291
+ }
1292
+ async m2(m1, pin = AIRPLAY_TRANSIENT_PIN) {
1293
+ const srpKey = await SRP.genKey(32);
1294
+ this.#srp = new SrpClient(SRP.params.hap, m1.salt, Buffer.from("Pair-Setup"), Buffer.from(pin), srpKey, true);
1295
+ this.#srp.setB(m1.publicKey);
1296
+ const publicKey = this.#srp.computeA();
1297
+ const proof = this.#srp.computeM1();
1298
+ return { publicKey, proof };
1299
+ }
1300
+ async m3(m2) {
1301
+ const response = await this.#requestHandler("m3", TLV8.encode([
1302
+ [TLV8.Value.State, TLV8.State.M3],
1303
+ [TLV8.Value.PublicKey, m2.publicKey],
1304
+ [TLV8.Value.Proof, m2.proof]
1305
+ ]));
1306
+ const data = tlv(response);
1307
+ const serverProof = data.get(TLV8.Value.Proof);
1308
+ return { serverProof };
1309
+ }
1310
+ async m4(m3) {
1311
+ this.#srp.checkM2(m3.serverProof);
1312
+ const sharedSecret = this.#srp.computeK();
1313
+ return { sharedSecret };
1314
+ }
1315
+ async m5(m4) {
1316
+ const iosDeviceX = hkdf_default({
1317
+ hash: "sha512",
1318
+ key: m4.sharedSecret,
1319
+ length: 32,
1320
+ salt: Buffer.from("Pair-Setup-Controller-Sign-Salt", "utf8"),
1321
+ info: Buffer.from("Pair-Setup-Controller-Sign-Info", "utf8")
1322
+ });
1323
+ const sessionKey = hkdf_default({
1324
+ hash: "sha512",
1325
+ key: m4.sharedSecret,
1326
+ length: 32,
1327
+ salt: Buffer.from("Pair-Setup-Encrypt-Salt", "utf8"),
1328
+ info: Buffer.from("Pair-Setup-Encrypt-Info", "utf8")
1329
+ });
1330
+ const deviceInfo = Buffer.concat([
1331
+ iosDeviceX,
1332
+ this.#pairingId,
1333
+ this.#publicKey
1334
+ ]);
1335
+ const signature = tweetnacl2.sign.detached(deviceInfo, this.#secretKey);
1336
+ const innerTlv = TLV8.encode([
1337
+ [TLV8.Value.Identifier, this.#pairingId],
1338
+ [TLV8.Value.PublicKey, this.#publicKey],
1339
+ [TLV8.Value.Signature, Buffer.from(signature)],
1340
+ [TLV8.Value.Name, Buffer.from(OPack.encode({
1341
+ name: this.#name
1342
+ }))]
1343
+ ]);
1344
+ const { authTag, ciphertext } = exports_chacha20.encrypt(sessionKey, Buffer.from("PS-Msg05"), null, innerTlv);
1345
+ const encrypted = Buffer.concat([ciphertext, authTag]);
1346
+ const response = await this.#requestHandler("m5", TLV8.encode([
1347
+ [TLV8.Value.State, TLV8.State.M5],
1348
+ [TLV8.Value.EncryptedData, encrypted]
1349
+ ]));
1350
+ const data = tlv(response);
1351
+ const encryptedDataRaw = data.get(TLV8.Value.EncryptedData);
1352
+ const encryptedData = encryptedDataRaw.subarray(0, -16);
1353
+ const encryptedTag = encryptedDataRaw.subarray(-16);
1354
+ return {
1355
+ authTag: encryptedTag,
1356
+ data: encryptedData,
1357
+ sessionKey
1358
+ };
1359
+ }
1360
+ async m6(m4, m5) {
1361
+ const data = exports_chacha20.decrypt(m5.sessionKey, Buffer.from("PS-Msg06"), null, m5.data, m5.authTag);
1362
+ const tlv = TLV8.decode(data);
1363
+ const accessoryIdentifier = tlv.get(TLV8.Value.Identifier);
1364
+ const accessoryLongTermPublicKey = tlv.get(TLV8.Value.PublicKey);
1365
+ const accessorySignature = tlv.get(TLV8.Value.Signature);
1366
+ const accessoryX = hkdf_default({
1367
+ hash: "sha512",
1368
+ key: m4.sharedSecret,
1369
+ length: 32,
1370
+ salt: Buffer.from("Pair-Setup-Accessory-Sign-Salt"),
1371
+ info: Buffer.from("Pair-Setup-Accessory-Sign-Info")
1372
+ });
1373
+ const accessoryInfo = Buffer.concat([
1374
+ accessoryX,
1375
+ accessoryIdentifier,
1376
+ accessoryLongTermPublicKey
1377
+ ]);
1378
+ if (!tweetnacl2.sign.detached.verify(accessoryInfo, accessorySignature, accessoryLongTermPublicKey)) {
1379
+ throw new Error("Invalid accessory signature.");
1380
+ }
1381
+ return {
1382
+ accessoryIdentifier: accessoryIdentifier.toString(),
1383
+ accessoryLongTermPublicKey,
1384
+ pairingId: this.#pairingId,
1385
+ publicKey: this.#publicKey,
1386
+ secretKey: this.#secretKey
1387
+ };
1388
+ }
1389
+ }
1390
+
1391
+ class AccessoryVerify {
1392
+ #ephemeralKeyPair;
1393
+ #requestHandler;
1394
+ constructor(requestHandler) {
1395
+ this.#ephemeralKeyPair = exports_curve25519.generateKeyPair();
1396
+ this.#requestHandler = requestHandler;
1397
+ }
1398
+ async start(credentials) {
1399
+ const m1 = await this.#m1();
1400
+ const m2 = await this.#m2(credentials.accessoryIdentifier, credentials.accessoryLongTermPublicKey, m1);
1401
+ await this.#m3(credentials.pairingId, credentials.secretKey, m2);
1402
+ return await this.#m4(m2, credentials.pairingId);
1403
+ }
1404
+ async#m1() {
1405
+ const response = await this.#requestHandler("m1", TLV8.encode([
1406
+ [TLV8.Value.State, TLV8.State.M1],
1407
+ [TLV8.Value.PublicKey, Buffer.from(this.#ephemeralKeyPair.publicKey)]
1408
+ ]));
1409
+ const data = tlv(response);
1410
+ const serverPublicKey = data.get(TLV8.Value.PublicKey);
1411
+ const encryptedData = data.get(TLV8.Value.EncryptedData);
1412
+ return {
1413
+ encryptedData,
1414
+ serverPublicKey
1415
+ };
1416
+ }
1417
+ async#m2(localAccessoryIdentifier, longTermPublicKey, m1) {
1418
+ const sharedSecret = Buffer.from(exports_curve25519.generateSharedSecKey(this.#ephemeralKeyPair.secretKey, m1.serverPublicKey));
1419
+ const sessionKey = hkdf_default({
1420
+ hash: "sha512",
1421
+ key: sharedSecret,
1422
+ length: 32,
1423
+ salt: Buffer.from("Pair-Verify-Encrypt-Salt"),
1424
+ info: Buffer.from("Pair-Verify-Encrypt-Info")
1425
+ });
1426
+ const encryptedData = m1.encryptedData.subarray(0, -16);
1427
+ const encryptedTag = m1.encryptedData.subarray(-16);
1428
+ const data = exports_chacha20.decrypt(sessionKey, Buffer.from("PV-Msg02"), null, encryptedData, encryptedTag);
1429
+ const tlv = TLV8.decode(data);
1430
+ const accessoryIdentifier = tlv.get(TLV8.Value.Identifier);
1431
+ const accessorySignature = tlv.get(TLV8.Value.Signature);
1432
+ if (accessoryIdentifier.toString() !== localAccessoryIdentifier) {
1433
+ throw new Error(`Invalid accessory identifier. Expected ${accessoryIdentifier.toString()} to be ${localAccessoryIdentifier}.`);
1434
+ }
1435
+ const accessoryInfo = Buffer.concat([
1436
+ m1.serverPublicKey,
1437
+ accessoryIdentifier,
1438
+ this.#ephemeralKeyPair.publicKey
1439
+ ]);
1440
+ if (!tweetnacl2.sign.detached.verify(accessoryInfo, accessorySignature, longTermPublicKey)) {
1441
+ throw new Error("Invalid accessory signature.");
1442
+ }
1443
+ return {
1444
+ serverEphemeralPublicKey: m1.serverPublicKey,
1445
+ sessionKey,
1446
+ sharedSecret
1447
+ };
1448
+ }
1449
+ async#m3(pairingId, secretKey, m2) {
1450
+ const iosDeviceInfo = Buffer.concat([
1451
+ this.#ephemeralKeyPair.publicKey,
1452
+ pairingId,
1453
+ m2.serverEphemeralPublicKey
1454
+ ]);
1455
+ const iosDeviceSignature = Buffer.from(tweetnacl2.sign.detached(iosDeviceInfo, secretKey));
1456
+ const innerTlv = TLV8.encode([
1457
+ [TLV8.Value.Identifier, pairingId],
1458
+ [TLV8.Value.Signature, iosDeviceSignature]
1459
+ ]);
1460
+ const { authTag, ciphertext } = exports_chacha20.encrypt(m2.sessionKey, Buffer.from("PV-Msg03"), null, innerTlv);
1461
+ const encrypted = Buffer.concat([ciphertext, authTag]);
1462
+ await this.#requestHandler("m3", TLV8.encode([
1463
+ [TLV8.Value.State, TLV8.State.M3],
1464
+ [TLV8.Value.EncryptedData, encrypted]
1465
+ ]));
1466
+ return {};
1467
+ }
1468
+ async#m4(m2, pairingId) {
1469
+ return {
1470
+ accessoryToControllerKey: Buffer.alloc(0),
1471
+ controllerToAccessoryKey: Buffer.alloc(0),
1472
+ pairingId,
1473
+ sharedSecret: m2.sharedSecret
1474
+ };
1475
+ }
1476
+ }
1477
+ function tlv(buffer) {
1478
+ const data = TLV8.decode(buffer);
1479
+ if (data.has(TLV8.Value.Error)) {
1480
+ TLV8.bail(data);
1481
+ }
1482
+ reporter.raw("Decoded TLV", data);
1483
+ return data;
1484
+ }
1485
+ // src/utils.ts
1486
+ function uint16ToBE(value) {
1487
+ const buffer = Buffer.alloc(2);
1488
+ buffer.writeUInt16BE(value, 0);
1489
+ return buffer;
1490
+ }
1491
+ function uint53ToLE(value) {
1492
+ const [upper, lower] = splitUInt53(value);
1493
+ const buffer = Buffer.alloc(8);
1494
+ buffer.writeUInt32LE(lower, 0);
1495
+ buffer.writeUInt32LE(upper, 4);
1496
+ return buffer;
1497
+ }
1498
+ function splitUInt53(number) {
1499
+ const MAX_UINT32 = 4294967295;
1500
+ const MAX_INT53 = 9007199254740991;
1501
+ if (number <= -1 || number > MAX_INT53) {
1502
+ throw new Error("Number out of range.");
1503
+ }
1504
+ if (Math.floor(number) !== number) {
1505
+ throw new Error("Number is not an integer.");
1506
+ }
1507
+ let upper = 0;
1508
+ const signbit = number & 4294967295;
1509
+ const lower = signbit < 0 ? (number & 2147483647) + 2147483648 : signbit;
1510
+ if (number > MAX_UINT32) {
1511
+ upper = (number - lower) / (MAX_UINT32 + 1);
1512
+ }
1513
+ return [upper, lower];
1514
+ }
1515
+ export {
1516
+ waitFor,
1517
+ v4 as uuid,
1518
+ uint53ToLE,
1519
+ uint16ToBE,
1520
+ reporter,
1521
+ prompt,
1522
+ hkdf_default as hkdf,
1523
+ getMacAddress_default as getMacAddress,
1524
+ getLocalIP_default as getLocalIP,
1525
+ cli,
1526
+ timing_default as TimingServer,
1527
+ RAOP_SERVICE,
1528
+ HTTP_TIMEOUT,
1529
+ EncryptionState,
1530
+ EncryptionAwareConnection,
1531
+ ENCRYPTION,
1532
+ Discovery,
1533
+ exports_curve25519 as Curve25519,
1534
+ Connection,
1535
+ exports_chacha20 as Chacha20,
1536
+ COMPANION_LINK_SERVICE,
1537
+ AccessoryVerify,
1538
+ AccessoryPair,
1539
+ AIRPLAY_TRANSIENT_PIN,
1540
+ AIRPLAY_SERVICE
1541
+ };