shifro 0.1.2 → 1.0.0

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/shifro.d.ts DELETED
@@ -1,40 +0,0 @@
1
- //#region lib/process.d.ts
2
- type EncryptionScheme = 'cenc' | 'cbcs';
3
- type TransformSampleParams = {
4
- encryptionScheme?: EncryptionScheme;
5
- data: Uint8Array;
6
- iv: Uint8Array;
7
- timestamp: number;
8
- };
9
- type TransformSampleFn = (params: TransformSampleParams) => Promise<Uint8Array | null>;
10
-
11
- //#endregion
12
- //#region lib/stream.d.ts
13
- interface ProcessStreamOptions {
14
- transformSample: TransformSampleFn;
15
- onProgress?: (bytesProcessed: number) => void;
16
- preventClose?: boolean;
17
- }
18
-
19
- //#endregion
20
- //#region shifro.d.ts
21
- declare const decryptWithKey: (key: Uint8Array, params: TransformSampleParams) => Promise<Uint8Array<ArrayBuffer>>;
22
- type DecryptWithKey = {
23
- key: string;
24
- keyId?: string;
25
- encryptionScheme?: EncryptionScheme;
26
- };
27
- type DecryptWithCallback = {
28
- keyId?: string;
29
- transformSample: (params: TransformSampleParams) => Promise<Uint8Array | null>;
30
- };
31
- type DecryptParams = DecryptWithKey | DecryptWithCallback;
32
- declare const decryptSegment: (segment: Uint8Array, params: DecryptParams) => Promise<Uint8Array<ArrayBufferLike>>;
33
- declare const decryptStream: (readable: ReadableStream, writable: WritableStream, {
34
- preventClose,
35
- onProgress,
36
- ...params
37
- }: DecryptParams & Omit<ProcessStreamOptions, "transformSample">) => Promise<void>;
38
-
39
- //#endregion
40
- export { DecryptParams, ProcessStreamOptions, TransformSampleParams, decryptSegment, decryptStream, decryptWithKey };
package/dist/shifro.js DELETED
@@ -1 +0,0 @@
1
- const e=async({key:e,iv:t,data:n,algorithm:r=`AES-CTR`})=>{let i=r.toUpperCase(),a=await crypto.subtle.importKey(`raw`,e,{name:i},!1,[`decrypt`]),o=await crypto.subtle.decrypt({name:i,counter:t,length:64},a,n);return new Uint8Array(o)},t=e=>{let t=e.buffer,n=new DataView(t,e.byteOffset,e.byteLength);return n},n=(e,t=0,n)=>new Uint8Array(e.buffer,e.byteOffset+t,n);var r=class extends Error{constructor(e,t,n,r){super(r),this.severity=e,this.category=t,this.code=n,this.name=`DataViewReaderError`}},i=class{position=0;constructor(e,n=`BE`){this.dataView=t(e),this.littleEndian=n===`LE`}getDataView(){return this.dataView}hasMoreData(){return this.position<this.dataView.byteLength}getPosition(){return this.position}getLength(){return this.dataView.byteLength}readUint8(){this.checkBounds(1);let e=this.dataView.getUint8(this.position);return this.position+=1,e}readUint16(){this.checkBounds(2);let e=this.dataView.getUint16(this.position,this.littleEndian);return this.position+=2,e}readUint32(){this.checkBounds(4);let e=this.dataView.getUint32(this.position,this.littleEndian);return this.position+=4,e}readInt32(){this.checkBounds(4);let e=this.dataView.getInt32(this.position,this.littleEndian);return this.position+=4,e}readUint64(){let e,t;try{this.littleEndian?(e=this.dataView.getUint32(this.position,!0),t=this.dataView.getUint32(this.position+4,!0)):(t=this.dataView.getUint32(this.position,!1),e=this.dataView.getUint32(this.position+4,!1))}catch{throw this.outOfBounds()}if(t>2097151)throw new r(`CRITICAL`,`MEDIA`,`JS_INTEGER_OVERFLOW`,`64-bit integer overflow`);return this.position+=8,t*2**32+e}readBytes(e){this.checkBounds(e);let t=n(this.dataView,this.position,e);return this.position+=e,t}skip(e){this.checkBounds(e),this.position+=e}rewind(e){if(this.position<e)throw this.outOfBounds();this.position-=e}seek(e){if(e<0||e>this.dataView.byteLength)throw this.outOfBounds();this.position=e}readTerminatedString(){let e=this.position;for(;this.hasMoreData()&&this.dataView.getUint8(this.position)!==0;)this.position++;if(!this.hasMoreData())throw this.outOfBounds();let t=new Uint8Array(this.dataView.buffer,e,this.position-e);return this.position++,new TextDecoder().decode(t)}checkBounds(e){if(this.position+e>this.dataView.byteLength)throw this.outOfBounds()}outOfBounds(){return new r(`CRITICAL`,`MEDIA`,`BUFFER_READ_OUT_OF_BOUNDS`,`Read operation out of bounds`)}};let a=function(e){return e[e.BASIC_BOX=0]=`BASIC_BOX`,e[e.FULL_BOX=1]=`FULL_BOX`,e}({});var o=class e{headers=new Map;boxDefinitions=new Map;done=!1;box(t,n){let r=e.typeFromString(t);return this.headers.set(r,a.BASIC_BOX),this.boxDefinitions.set(r,n),this}fullBox(t,n){let r=e.typeFromString(t);return this.headers.set(r,a.FULL_BOX),this.boxDefinitions.set(r,n),this}stop(){this.done=!0}parse(e,t=!1,n=!1){let r=new i(e);for(this.done=!1;r.hasMoreData()&&!this.done;)this.parseNext(0,r,t,n)}parseNext(t,n,r,o){let s=n.getPosition();if(o&&s+8>n.getLength()){this.done=!0;return}let c=n.readUint32(),l=n.readUint32(),u=e.typeToString(l),d=!1;switch(c){case 0:c=n.getLength()-s;break;case 1:if(o&&n.getPosition()+8>n.getLength()){this.done=!0;return}c=Number(n.readUint64()),d=!0;break}let f=this.boxDefinitions.get(l);if(f){let e=null,p=null;if(this.headers.get(l)===a.FULL_BOX){if(o&&n.getPosition()+4>n.getLength()){this.done=!0;return}let t=n.readUint32();e=t>>>24,p=t&16777215}let m=s+c;if(r&&m>n.getLength()&&(m=n.getLength()),o&&m>n.getLength()){this.done=!0;return}let h=m-n.getPosition(),g=h>0?n.readBytes(h):new Uint8Array,_=new i(g),v={name:u,parser:this,partialOkay:!!r,version:e,flags:p,reader:_,size:c,start:s+t,has64BitSize:d};f(v)}else{let e=Math.min(s+c-n.getPosition(),n.getLength()-n.getPosition());n.skip(e)}}static children(t){let n=e.headerSize(t);for(;t.reader.hasMoreData()&&!t.parser.done;)t.parser.parseNext(t.start+n,t.reader,t.partialOkay)}static sampleDescription(t){let n=e.headerSize(t),r=t.reader.readUint32();for(let e=0;e<r&&(t.parser.parseNext(t.start+n,t.reader,t.partialOkay),!t.parser.done);e++);}static visualSampleEntry(t){let n=e.headerSize(t);for(t.reader.skip(78);t.reader.hasMoreData()&&!t.parser.done;)t.parser.parseNext(t.start+n,t.reader,t.partialOkay)}static audioSampleEntry(t){let n=e.headerSize(t);t.reader.skip(8);let r=t.reader.readUint16();for(t.reader.skip(6),r===2?t.reader.skip(48):t.reader.skip(12),r===1&&t.reader.skip(16);t.reader.hasMoreData()&&!t.parser.done;)t.parser.parseNext(t.start+n,t.reader,t.partialOkay)}static allData(e){return t=>{let n=t.reader.getLength()-t.reader.getPosition();e(t.reader.readBytes(n))}}static typeFromString(e){if(e.length!==4)throw Error(`MP4 box names must be 4 characters long`);let t=0;for(let n of e)t=t<<8|n.charCodeAt(0);return t}static typeToString(e){return String.fromCharCode(e>>24&255,e>>16&255,e>>8&255,e&255)}static headerSize(e){let t=8,n=e.has64BitSize?8:0,r=e.flags===null?0:4;return t+n+r}};const s=(e,t)=>{if(t&&t&1){let t=e.readUint8(),n=e.readUint8(),r=e.readBytes(16)}let n=e.readUint32(),r=[];for(let i=0;i<n;i++){let n=8,i=new Uint8Array(16);i.set(e.readBytes(n));let a={iv:i,subsamples:[]},o=t&&t&2;if(o){let t=e.readUint16();for(let n=0;n<t;n++){let t=e.readUint16(),n=e.readUint32();a.subsamples.push({bytesOfClearData:t,bytesOfEncryptedData:n})}}r.push(a)}return{samples:r}},c=(e,t,n)=>{let r=e.readUint32(),i=[],a=null;t&1&&(a=e.readInt32()),t&4&&e.skip(4);for(let a=0;a<r;a++){let r={};t&256&&(r.duration=e.readUint32()),t&512&&(r.size=e.readUint32()),t&1024&&e.skip(4),t&2048&&(r.compositionTimeOffset=n==0?e.readUint32():e.readInt32()),i.push(r)}return{samples:i,dataOffset:a}},l=(e,t)=>{let n,r,i,a,o=e.readUint32();return t&1&&(i=e.readUint64()),t&2&&(a=e.readUint32()),t&8&&(n=e.readUint32()),t&16&&(r=e.readUint32()),{trackId:o,defaultSampleDuration:n,defaultSampleSize:r,baseDataOffset:i,sampleDescriptionIndex:a}},u=(e,t,n)=>{if(t.length===0)return-1;let r=e.length-t.length+1;for(let i=n;i<r;i++){let n=!0;for(let r=0;r<t.length;r++)if(e[i+r]!==t[r]){n=!1;break}if(n)return i}return-1},d=(e,t,n)=>{let r=new TextEncoder,i=r.encode(t),a=r.encode(n);if(i.length!==a.length)throw Error(`Original and replacement must have the same byte length`);let o=0;do o=u(e,i,0),o!==-1&&e.set(a,o);while(o!==-1)},f=(e,t,n=0)=>{let r=new TextEncoder,i;return i=typeof t==`string`?r.encode(t):typeof t==`number`?new Uint8Array([t]):t,i.length===0?!0:e.length<i.length?!1:u(e,i,n)!==-1},p=(e,t)=>{if(e.length===0)return new Uint8Array;let n=t??e.reduce((e,t)=>e+t.length,0);n=Math.min(n,e.reduce((e,t)=>e+t.length,0));let r=new Uint8Array(n),i=0;for(let t of e){if(i>=n)break;let e=t.subarray(0,Math.min(t.length,n-i));r.set(e,i),i+=e.length}return r},m=(e,t,n=0,r=0,i=e.length)=>{n=Math.max(0,Math.min(n,t.length)),r=Math.max(0,Math.min(r,e.length)),i=Math.min(i,e.length),i<r&&(i=r);let a=Math.min(i-r,t.length-n);return a<=0?0:(t.set(e.subarray(r,r+a),n),a)},h=(e,t,n=0,r)=>{let i=new TextEncoder,a=i.encode(t),o=Math.max(0,Math.min(n,e.length)),s=e.length-o,c=a.length;return typeof r==`number`&&(c=Math.min(c,r)),c=Math.min(c,s),c<=0?0:(e.set(a.subarray(0,c),o),c)},g=e=>Array.from(e).map(e=>e.toString(16).padStart(2,`0`)).join(``),_=e=>{let t=Array.from(e,e=>String.fromCodePoint(e)).join(``);return btoa(t)},v=e=>e.match(/.{1,2}/g)?.map(e=>parseInt(e,16))??[],y=e=>{e.readUint8(),e.readUint8(),e.readUint8(),e.readUint8();let t=g(e.readBytes(16));return{defaultKID:t}},b=e=>{let t=`edef8ba979d64acea3c827dcd51d21ed`,n=e.version??0;if(n!==0&&n!==1)throw Error(`PSSH version can only be 0 or 1`);let r=e.reader.readBytes(16),i=g(r),a=[i.slice(0,8),i.slice(8,12),i.slice(12,16),i.slice(16,20),i.slice(20)].join(`-`),o=e.reader.getDataView(),s=new Uint8Array(o.buffer,o.byteOffset-12,e.size),c=_(s),l=[];if(n>=1){let t=e.reader.readUint32();for(let n=0;n<t;n++)l.push(g(e.reader.readBytes(16)))}let u=e.reader.readUint32(),d=e.reader.readBytes(u),f=i===t;return{version:n,systemId:a,pssh:c,keyIds:l,systemData:d}},x=e=>{try{let t=!1,n=!1;return new o().box(`moov`,()=>{t=!0}).box(`moof`,()=>{n=!0}).parse(e,!0,!0),t&&!n}catch(e){return console.log(e),!1}},S=e=>{let t=null;return new o().box(`moov`,o.children).box(`trak`,o.children).box(`mdia`,o.children).box(`minf`,o.children).box(`stbl`,o.children).fullBox(`stsd`,o.sampleDescription).box(`encv`,o.visualSampleEntry).box(`enca`,o.audioSampleEntry).box(`sinf`,o.children).box(`frma`,e=>{let n=e.reader.readBytes(4);t=new TextDecoder().decode(n)}).parse(e,!0,!0),t},C=async e=>{let t=S(e);if(d(e,`sinf`,`skip`),d(e,`pssh`,`skip`),t)d(e,`encv`,t),d(e,`enca`,t);else{console.warn(`Could not detect original codec, using fallback values`);let t=f(e,`encv`)?`video`:`audio`;t===`video`?d(e,`encv`,`avc1`):d(e,`enca`,`mp4a`)}return e},w=e=>{let t={schemeType:``,defaultKID:``,psshList:[]};return new o().box(`moov`,o.children).box(`trak`,o.children).box(`mdia`,o.children).box(`minf`,o.children).box(`stbl`,o.children).fullBox(`stsd`,o.sampleDescription).fullBox(`pssh`,e=>t.psshList.push(b(e))).box(`encv`,o.visualSampleEntry).box(`enca`,o.audioSampleEntry).box(`sinf`,o.children).box(`schi`,o.children).fullBox(`schm`,e=>{t.schemeType=new TextDecoder().decode(e.reader.readBytes(4))}).fullBox(`tenc`,e=>{let{defaultKID:n}=y(e.reader);t.defaultKID=n}).parse(e,!1,!0),t},T=async(e,t)=>{let n=x(e);if(n)return C(e);let r,i,a,u;if(new o().box(`moof`,o.children).box(`traf`,o.children).fullBox(`tfhd`,e=>{a=l(e.reader,e.flags)}).fullBox(`trun`,e=>{i=c(e.reader,e.flags,e.version)}).fullBox(`senc`,e=>{r=s(e.reader,e.flags)}).parse(e,!0,!0),u=i.dataOffset,r.samples.length!==i.samples.length)throw Error(`sample count mismatch: trun has ${i.samples.length}, senc has ${r.samples.length}`);let d=0,f=0;for(let n=0;n<r.samples.length;n++){let o=r.samples[n],s=i.samples[n],c=i.samples[n].size||a.defaultSampleSize||0;o.subsamples.length||o.subsamples.push({bytesOfClearData:0,bytesOfEncryptedData:c});let l=o.subsamples.some(e=>e.bytesOfEncryptedData>0);if(l){let n=0,r=[];for(let t of o.subsamples){if(n+=t.bytesOfClearData,t.bytesOfEncryptedData>0){let i=e.subarray(u+d+n,u+d+n+t.bytesOfEncryptedData);r.push(i)}n+=t.bytesOfEncryptedData}let i=p(r),a={iv:o.iv,data:i,timestamp:f},s=await t(a);if(s){n=0;let t=0,r=[];for(let i of o.subsamples){if(i.bytesOfClearData>0){let t=e.subarray(u+d+n,u+d+n+i.bytesOfClearData);r.push(t),n+=i.bytesOfClearData}if(i.bytesOfEncryptedData>0){let e=s.subarray(t,t+i.bytesOfEncryptedData);r.push(e),t+=i.bytesOfEncryptedData,n+=i.bytesOfEncryptedData}}let i=p(r);m(i,e,u+d)}}d+=c,f+=s.duration||a.defaultSampleDuration||0}return new o().box(`moof`,o.children).box(`traf`,o.children).box(`senc`,t=>{let n=`skip`,r=t.start+n.length;h(e,n,r)}).parse(e,!0,!0),e},E=e=>{let t=null;new o().box(`moov`,e=>{t=e.start+e.size}).parse(e,!0,!0);let n=t?e.subarray(0,t):null;return{moovEnd:t,init:n}},D=e=>{let t=null,n=null;new o().box(`moof`,e=>{t===null&&(t=e.start)}).box(`mdat`,e=>{n===null&&(n=e.start+e.size)}).parse(e,!0,!0);let r=t!==null&&n!==null,i=r?e.subarray(t,n):null;return{segment:i,moofStart:t,mdatEnd:n}};var O=class{buffer=new Uint8Array;isProcessingInit=!0;scheme=null;processedBytes=0;constructor(e){this.options=e}async transform(e,t){try{this.buffer=p([this.buffer,e]);let n=!0;for(;n;){if(this.isProcessingInit){let{init:e,moovEnd:n}=E(this.buffer);if(!n||this.buffer.length<n)break;if(e&&x(e)){let r=w(e);this.scheme=r.schemeType;let i=await C(e);t.enqueue(i),this.updateProgress(i.byteLength),this.buffer=this.buffer.subarray(n),this.isProcessingInit=!1;continue}}let{moofStart:e,mdatEnd:r,segment:i}=D(this.buffer);if(e===null||r===null||!i||this.buffer.length<r)break;let a=e=>(e.encryptionScheme=this.scheme,this.options.transformSample(e)),o=await T(i,a);t.enqueue(o),this.updateProgress(o.byteLength),this.buffer=this.buffer.subarray(r),n=this.buffer.length>=8}}catch(e){t.error(e)}}async flush(e){this.buffer.length>0&&(e.enqueue(this.buffer),this.updateProgress(this.buffer.byteLength))}updateProgress(e){this.processedBytes+=e,this.options.onProgress&&this.options.onProgress(this.processedBytes)}};const k=async(e,t,{transformSample:n,onProgress:r,preventClose:i})=>{let a=new O({transformSample:n,onProgress:r}),o=new TransformStream({transform:(e,t)=>a.transform(e,t),flush:e=>a.flush(e)});await e.pipeThrough(o).pipeTo(t,{preventClose:i})},A=async(t,n)=>{let r=n.encryptionScheme,i=n.iv,a=n.data;return e(r===`cbcs`?{key:t,iv:i,data:a,algorithm:`AES-CBC`}:{key:t,iv:i,data:a,algorithm:`AES-CTR`})},j=async(e,t)=>{let n=`key`in t,r=new Uint8Array(v(n?t.key:``)),i=async e=>A(r,{encryptionScheme:`encryptionScheme`in t?t.encryptionScheme:void 0,...e}),a=n?i:t.transformSample;return T(e,a)},M=async(e,t,{preventClose:n,onProgress:r,...i})=>{let a=`key`in i,o=new Uint8Array(v(a?i.key:``)),s=async e=>A(o,e),c=a?s:i.transformSample;await k(e,t,{preventClose:n,onProgress:r,transformSample:c})};export{j as decryptSegment,M as decryptStream,A as decryptWithKey};
File without changes