import { createHash , webcrypto } from "crypto" ; import { WritableStream } from "stream/web" ; import { DOMException } from "@miniflare/core" ; import { viewToBuffer } from "@miniflare/shared" ; import { assertsInRequest , bufferSourceToArray , buildNotBufferSourceError , isBufferSource , } from "./helpers" ; const supportedDigests = [ "sha-1" , "sha-256" , "sha-384" , "sha-512" , "md5" ] ; export class DigestStream extends WritableStream < BufferSource > { readonly digest : Promise < ArrayBuffer > ; constructor ( algorithm ) { let name = typeof algorithm === "string" ? algorithm : algorithm ?. name ; if ( ! ( name && supportedDigests . includes ( name . toLowerCase ( ) ) ) ) { throw new DOMException ( "Unrecognized name." , "NotSupportedError" ) ; } name = name . replace ( "-" , "" ) ; let digestResolve ; const digest = new Promise < ArrayBuffer > ( ( r ) => ( digestResolve = r ) ) ; const hash = createHash ( name ) ; super ( { write ( chunk ) { if ( isBufferSource ( chunk ) ) { hash . update ( bufferSourceToArray ( chunk ) ) ; } else { throw new TypeError ( buildNotBufferSourceError ( chunk ) ) ; } } , close ( ) { digestResolve ( viewToBuffer ( hash . digest ( ) ) ) ; } , } ) ; this . digest = digest ; } } function digest ( algorithm , data ) { const name = typeof algorithm === "string" ? algorithm : algorithm ?. name ; if ( name ?. toLowerCase ( ) == "md5" ) { if ( data instanceof ArrayBuffer ) data = new Uint8Array ( data ) ; const hash = createHash ( "md5" ) . update ( data as any ) ; return Promise . resolve ( viewToBuffer ( hash . digest ( ) ) ) ; } return webcrypto . subtle . digest ( algorithm , data ) ; } export function createCrypto ( blockGlobalRandom = false ) { const getRandomValues = assertsInRequest ( webcrypto . getRandomValues , blockGlobalRandom ) ; const generateKey = assertsInRequest ( webcrypto . subtle . generateKey , blockGlobalRandom ) ; const subtle = new Proxy ( webcrypto . subtle , { get ( target , propertyKey , receiver ) { if ( propertyKey === "digest" ) return digest ; if ( propertyKey === "generateKey" ) return generateKey ; return Reflect . get ( target , propertyKey , receiver ) ; } , } ) ; return new Proxy ( webcrypto , { get ( target , propertyKey , receiver ) { if ( propertyKey === "getRandomValues" ) return getRandomValues ; if ( propertyKey === "subtle" ) return subtle ; if ( propertyKey === "DigestStream" ) return DigestStream ; return Reflect . get ( target , propertyKey , receiver ) ; } , } ) ; }