UNPKG

@simplito/privmx-webendpoint

Version:

PrivMX Web Endpoint library

1 lines 9.26 kB
(()=>{"use strict";var e={320(e,t){async function r(e,t){return e instanceof CryptoKey?e:crypto.subtle.importKey("raw",e,{name:"AES-GCM"},!1,[t])}Object.defineProperty(t,"__esModule",{value:!0}),t.encryptWithAES256GCM=async function(e,t,n,s){try{const i=await r(e,"encrypt"),a=await crypto.subtle.encrypt({name:"AES-GCM",iv:t,additionalData:s,tagLength:128},i,n);return{success:!0,data:new Uint8Array(a)}}catch(e){return{success:!1,error:"EncryptionFailed"}}},t.decryptWithAES256GCM=async function(e,t,n,s){try{const i=await r(e,"decrypt"),a=await crypto.subtle.decrypt({name:"AES-GCM",iv:t,additionalData:s,tagLength:128},i,n);return{success:!0,data:new Uint8Array(a)}}catch(e){return{success:!1,error:"DecryptionFailed"}}},t.isEncryptionSuccess=function(e){return e.success},t.isDecryptionSuccess=function(e){return e.success}},928(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.KeyStore=void 0,t.KeyStore=class{_keys=new Map;_encryptionKeyId=void 0;setKeys(e){this._keys.clear(),this._encryptionKeyId=void 0;for(const t of e){const e=new Uint8Array(t.key);this.assertKeyBytes(e),this._keys.set(t.keyId,{keyId:t.keyId,cryptoKey:crypto.subtle.importKey("raw",e,{name:"AES-GCM"},!1,["encrypt","decrypt"]),type:t.type}),0===t.type&&(this._encryptionKeyId=t.keyId)}}async getKey(e){const t=this._keys.get(e);return t?t.cryptoKey:void 0}hasKey(e){return this._keys.has(e)}async getEncriptionKey(){if(!this._encryptionKeyId)throw new Error("No encryption key set.");return this._keys.get(this._encryptionKeyId).cryptoKey}getEncryptionKeyId(){if(!this._encryptionKeyId)throw new Error("No encryption key set.");return this._encryptionKeyId}assertKeyBytes(e){if(32!==e.length)throw new Error(`Invalid key length: ${e.length}`)}}},251(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.Utils=void 0;class r{static generateNumericId(){return Math.round(1e15*Math.random())}static getRandomString(e){return[...Array(e)].map((()=>Math.floor(16*Math.random()).toString(16))).join("")}static async encryptSymmetric(e,t,r){let n;n="string"==typeof e?(new TextEncoder).encode(e):e;const s=await crypto.subtle.importKey("raw",Buffer.from(t,"base64"),{name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),i=await crypto.subtle.encrypt({name:"AES-GCM",iv:Buffer.from(r,"base64")},s,n);return{ciphertext:Buffer.from(i),iv:r}}static async decryptSymmetricBuffer(e,t,r){const n=await crypto.subtle.importKey("raw",r,{name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),s=await crypto.subtle.decrypt({name:"AES-GCM",iv:t},n,e);return Buffer.from(s)}static async decryptSymmetric(e,t,r){const n=await crypto.subtle.importKey("raw",Buffer.from(r,"base64"),{name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),s=await crypto.subtle.decrypt({name:"AES-GCM",iv:Buffer.from(t,"base64")},n,Buffer.from(e,"base64"));return(new TextDecoder).decode(s)}static genKey(){return Buffer.from(crypto.getRandomValues(new Uint8Array(32))).toString("base64")}static genIv(){return Buffer.from(crypto.getRandomValues(new Uint8Array(12))).toString("base64")}static genIvAsBuffer(){return crypto.getRandomValues(new Uint8Array(12))}static base64abc=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"];static base64codes=[255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,62,255,255,255,63,52,53,54,55,56,57,58,59,60,61,255,255,255,0,255,255,255,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,255,255,255,255,255,255,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51];static bytesToBase64(e){let t,n="",s=e.length;for(t=2;t<s;t+=3)n+=r.base64abc[e[t-2]>>2],n+=r.base64abc[(3&e[t-2])<<4|e[t-1]>>4],n+=r.base64abc[(15&e[t-1])<<2|e[t]>>6],n+=r.base64abc[63&e[t]];return t===s+1&&(n+=r.base64abc[e[t-2]>>2],n+=r.base64abc[(3&e[t-2])<<4],n+="=="),t===s&&(n+=r.base64abc[e[t-2]>>2],n+=r.base64abc[(3&e[t-2])<<4|e[t-1]>>4],n+=r.base64abc[(15&e[t-1])<<2],n+="="),n}static isBitOn(e,t){return Boolean(e&1<<t)}static getBits(e,t,r){const n=Math.pow(2,r)-1,s=t/8,i=t%=8;return e[s]>>i&n}static numAsOneByteUint(e){if(e>255)throw new Error("Out of bounds value");const t=new Uint8Array(1);return t[0]=e,t}static oneByteUint8AsNum(e){if(e[0]>255)throw new Error("Out of bounds value");return e[0]}}t.Utils=r},247(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.LocalAudioLevelMeter=void 0,t.LocalAudioLevelMeter=class{track;onLevel;static RMS_VALUE_OF_SILENCE=-99;ctx;node;source;keepAliveGain;stopped=!1;constructor(e,t){this.track=e,this.onLevel=t}async init(e){const t=[];try{const e=this.track.getSettings?.();"number"==typeof e?.sampleRate&&t.push(e.sampleRate)}catch{}let r;t.push(void 0);for(const n of t){if(this.stopped)throw new Error("LocalAudioLevelMeter stopped during init");try{this.ctx=n?new AudioContext({sampleRate:n}):new AudioContext,await this.ctx.audioWorklet.addModule(e);try{await this.ctx.resume()}catch{}this.source=this.ctx.createMediaStreamSource(new MediaStream([this.track])),this.node=new AudioWorkletNode(this.ctx,"rms-processor"),this.node.port.onmessage=e=>this.onLevel(e.data.rmsDb),this.keepAliveGain=this.ctx.createGain(),this.keepAliveGain.gain.value=0,this.source.connect(this.node),this.node.connect(this.keepAliveGain),this.keepAliveGain.connect(this.ctx.destination),r=void 0;break}catch(e){r=e;try{this.ctx?.close()}catch{}}}if(r)throw r}stop(){this.stopped=!0;try{this.node?.port?.close()}catch{}try{this.source?.disconnect()}catch{}try{this.node?.disconnect()}catch{}try{this.keepAliveGain?.disconnect()}catch{}try{this.ctx?.close()}catch{}}}}},t={};function r(n){var s=t[n];if(void 0!==s)return s.exports;var i=t[n]={exports:{}};return e[n](i,i.exports,r),i.exports}(()=>{const e=r(251),t=r(320),n=r(928),s=r(247),i=new Map,a=new Map;let o=s.LocalAudioLevelMeter.RMS_VALUE_OF_SILENCE,c=s.LocalAudioLevelMeter.RMS_VALUE_OF_SILENCE,y=Date.now();class d{keyStore;constructor(e){this.keyStore=e}getHeaderSizeByType(e){return"key"===e?10:"delta"===e?3:"empty"===e?1:0}async encryptFrame(r,n,s){const i="video"===n?this.getHeaderSizeByType(r.type):1,a=new Uint8Array(r.data,0,i),c=new Uint8Array(r.data,i),y=e.Utils.genIvAsBuffer(),d=this.keyStore.getEncryptionKeyId(),p=await this.keyStore.getEncriptionKey(),u=await(0,t.encryptWithAES256GCM)(p,y,c,a);if(!(0,t.isEncryptionSuccess)(u))throw new Error("Cannot encrypt frame");const h=(new TextEncoder).encode(d),l=a.byteLength,f=l+u.data.byteLength,w=f+y.byteLength,m=w+1,b=m+h.byteLength,g=b+1,A=new ArrayBuffer(g+1),S=new Uint8Array(A);S.set(a),S.set(new Uint8Array(u.data),l),S.set(y,f),S.set(e.Utils.numAsOneByteUint(y.byteLength),w),S.set(h,m),S.set(e.Utils.numAsOneByteUint(h.byteLength),b),S.set(e.Utils.numAsOneByteUint(o+100),g),r.data=A,s.enqueue(r)}async decryptFrame(e,r,n,s,i){const a="video"===r?this.getHeaderSizeByType(e.type):1,o=e.data;if(o.byteLength<a+5)return void n.enqueue(e);const d=new Uint8Array(o,0,a),p=o.byteLength-1;c=new Uint8Array(o,p,1)[0]-100;const u=Date.now();y+100<u&&(y=u,self.postMessage({type:"rms",rms:c,receiverId:s,publisherId:i}));const l=p-1,f=new Uint8Array(o,l,1)[0],w=l-f,m=(new TextDecoder).decode(new Uint8Array(o,w,f)),b=w-1,g=new Uint8Array(o,b,1)[0],A=b-g,S=new Uint8Array(o,A,g),v=a,k=A-a,M=o.slice(v,v+k);try{if(!this.keyStore.hasKey(m))return void n.enqueue(e);const r=await this.keyStore.getKey(m),s=await(0,t.decryptWithAES256GCM)(r,S,M,d);if(!(0,t.isDecryptionSuccess)(s))return void n.enqueue(e);const i=s.data,a=new ArrayBuffer(d.byteLength+i.byteLength),o=new Uint8Array(a);o.set(d),o.set(new Uint8Array(i),d.byteLength),e.data=a,n.enqueue(e)}catch(t){h(t),n.enqueue(e)}}}self.keyStore=new n.KeyStore;const p=()=>self.keyStore;function u(e,t,r,n,s){let a;if(JSON.stringify({operation:t,context:e}),"encode"===t)a=function(e,t){const r=new d(e);return new TransformStream({async transform(e,n){await r.encryptFrame(e,t,n)}})}(e.keyStore,r),n.pipeThrough(a).pipeTo(s);else if("decode"===t){a=function(e,t){const r=new d(e.keyStore);return new TransformStream({async transform(n,s){await r.decryptFrame(n,t,s,e.id,e.publisherId)}})}(e,r);const t=n.pipeThrough(a).pipeTo(s).catch((e=>{String(e).includes("Destination stream closed")||console.error("pipeline error",e)}));e.id&&i.set(e.id,{pipeline:t})}}function h(e){self.postMessage({type:"error",data:e})}self.onmessage=async e=>{const{operation:t,kind:r}=e.data;if("initialize"===t);else if("init-pipeline"===t)a.set(e.data.id,{ready:!1}),self.postMessage({operation:"init-pipeline",id:e.data.id});else if("encode"===t||"decode"===t){const{readableStream:n,writableStream:s,id:i,publisherId:a}=e.data;u({keyStore:p(),id:i,publisherId:a},t,r,n,s)}else if("setKeys"===t){const t=e.data;p().setKeys(t.keys)}else"rms"===t&&(o=Math.round(e.data.rms))},self.RTCTransformEvent&&(self.onrtctransform=e=>{const t=e.transformer,r=t.options;if(!r)return void h("onrtctransform: options is undefined");const{operation:n,kind:s,id:i,publisherId:a}=r;u({keyStore:p(),id:i,publisherId:a},n,s,t.readable,t.writable)})})()})();