{"version":3,"sources":["../../../packages/core/data/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA4B,MAAM,MAAM,CAAC;AAU5D;;;GAGG;AACH,qBAAa,MAAM;IACf,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAsD;IACtF,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAoD;IAEnF;;;;;OAKG;WACW,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAsBzD;;;;;;OAMG;WACW,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAqC3E;;;;;;OAMG;WACW,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IA6BrE;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAgB5B;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS;IAgBxB;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAkB/B;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;IAqB3B;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAmB7B;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU;IAqBzB;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAW1B;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;IAW3B;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAKhC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU;IAIzB;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAU5B;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAUhC;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;CAG9B","file":"crypto.d.ts","sourcesContent":["import { Observable, Observer, of, throwError } from 'rxjs';\r\nimport { Strings } from '../generated/strings';\r\nimport { Base64ArrayBuffer } from './base64-array-buffer';\r\n\r\n/**\r\n * Unescape non-binary string code\r\n * @param data A value representing original non-binary string code\r\n */\r\ndeclare function unescape(data: string): string;\r\n\r\n/**\r\n * Web Crypto interface class.\r\n * @dynamic\r\n */\r\nexport class Crypto {\r\n    private static algRsaOaepSha1Key: any = { name: 'RSA-OAEP', hash: { name: 'SHA-1' } };\r\n    private static algHmacSha256Key: any = { name: 'HMAC', hash: { name: 'SHA-256' } };\r\n\r\n    /**\r\n     * hash with SHA-256\r\n     * (If it doesn't support web based crypto, encode as base64.)\r\n     * @param data the original data to hash.\r\n     * @return Observable<string> the hash generated.\r\n     */\r\n    public static getSha256(data: string): Observable<string> {\r\n        if (data == null) {\r\n            const message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.ArgumentNullError.message;\r\n            return throwError(() => new Error(message.format('Crypto/getSha256', 'data')));\r\n        }\r\n\r\n        const root = <any>window;\r\n        const isIE = !!root.msCrypto;\r\n        if (isIE && root.msCrypto.subtle) {\r\n            return Crypto.hash256IE(root.msCrypto.subtle, data);\r\n        }\r\n\r\n        if (root.crypto) {\r\n            const subtle = root.crypto.subtle || root.crypto.webkitSubtle;\r\n            if (subtle) {\r\n                return Crypto.hash256WebAPI(subtle, data);\r\n            }\r\n        }\r\n\r\n        return of(window.btoa(data));\r\n    }\r\n\r\n    /**\r\n     * encrypt with RSA/SHA-1\r\n     *\r\n     * @param jwk the JSON Web Key. Single string with JSON.stringify format.\r\n     * @param data the original data to hash.\r\n     * @return Observable<string> the hash generated.\r\n     */\r\n    public static encryptRsaSha1(jwk: string, data: string): Observable<string> {\r\n        const RsaSha1 = 'Crypto/encryptRsaSha1';\r\n        let message = '';\r\n        if (jwk == null) {\r\n            message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.ArgumentNullError.message;\r\n            return throwError(() => new Error(message.format(RsaSha1, 'jwk')));\r\n        }\r\n\r\n        if (data == null) {\r\n            message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.ArgumentNullError.message;\r\n            return throwError(() => new Error(message.format(RsaSha1, 'data')));\r\n        }\r\n\r\n        const root = <any>window;\r\n        const isIE = !!root.msCrypto;\r\n        if (isIE && root.msCrypto.subtle) {\r\n            return Crypto.encryptRsaIE(root.msCrypto.subtle, jwk, data);\r\n        }\r\n\r\n        if (root.crypto) {\r\n            let subtle = root.crypto.subtle;\r\n            if (subtle) {\r\n                const jwkObject = JSON.parse(jwk);\r\n                return Crypto.encryptRsaWebAPI(subtle, jwkObject, data);\r\n            }\r\n\r\n            subtle = root.crypto.webkitSubtle;\r\n            if (subtle) {\r\n                const jwkArray = Crypto.toArrayBufferView(jwk);\r\n                return Crypto.encryptRsaWebAPI(subtle, jwkArray, data);\r\n            }\r\n        }\r\n\r\n        message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.UnknownBrowser.message;\r\n        return throwError(() => new Error(message.format(RsaSha1)));\r\n    }\r\n\r\n    /**\r\n     * sign with HMAC/SHA-256\r\n     *\r\n     * @param key the key (base64 encoded).\r\n     * @param data the original data to hash. (unicode - not utf8)\r\n     * @return Observable<string> the hash generated.\r\n     */\r\n    public static signHmac(key: string, data: string): Observable<string> {\r\n        let message = '';\r\n        if (key == null) {\r\n            message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.ArgumentNullError.message;\r\n            return throwError(() => new Error(message.format('Crypto/signHmac', 'key')));\r\n        }\r\n\r\n        if (data == null) {\r\n            message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.ArgumentNullError.message;\r\n            return throwError(() => new Error(message.format('Crypto/encryptRsaSha1', 'data')));\r\n        }\r\n\r\n        const root = <any>window;\r\n        const isIE = !!root.msCrypto;\r\n        if (isIE && root.msCrypto.subtle) {\r\n            return Crypto.signHmacIE(root.msCrypto.subtle, key, data);\r\n        }\r\n\r\n        if (root.crypto) {\r\n            const subtle = root.crypto.subtle || root.crypto.webkitSubtle;\r\n            if (subtle) {\r\n                return Crypto.signHmacWebAPI(subtle, key, data);\r\n            }\r\n        }\r\n\r\n        message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.UnknownBrowser.message;\r\n        return throwError(() => new Error(message.format('Crypto/signHmac')));\r\n    }\r\n\r\n    /**\r\n     * Hash with SHA-256 for WebAPI.\r\n     *\r\n     * @param subtle the Web API subtle.\r\n     * @param data the original data to hash.\r\n     * @return Observable<string> the hash generated.\r\n     */\r\n    private static hash256WebAPI(subtle: SubtleCrypto, data: string): Observable<string> {\r\n        return new Observable((observer: Observer<string>) => {\r\n            const array = Crypto.toUint8Array(data);\r\n            subtle.digest({ name: 'SHA-256' }, array)\r\n                .then(\r\n                (hash: ArrayBuffer) => {\r\n                    const hexText = Crypto.toHexString(hash);\r\n                    observer.next(hexText);\r\n                    observer.complete();\r\n                },\r\n                (error: any) => {\r\n                    observer.error(error);\r\n                });\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Hash with SHA-256 for IE/Older API.\r\n     *\r\n     * @param subtle the older API subtle.\r\n     * @param data the original data to hash.\r\n     * @return Observable<string> the hash generated.\r\n     */\r\n    private static hash256IE(subtle: any, data: string): Observable<string> {\r\n        return new Observable((observer: Observer<string>) => {\r\n            const array = Crypto.toUint8Array(data);\r\n            const cryptoOp: any = subtle.digest({ name: 'SHA-256' }, array);\r\n            cryptoOp.oncomplete = (event: any) => {\r\n                const hexText = Crypto.toHexString(event.target.result);\r\n                observer.next(hexText);\r\n                observer.complete();\r\n            };\r\n            cryptoOp.onerror = (error: any) => {\r\n                observer.error(error);\r\n            };\r\n            cryptoOp.finish();\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Encrypt with RSA/SHA-1 for WebAPI.\r\n     *\r\n     * @param subtle the Web API subtle.\r\n     * @param jwkObject the JSON Web key object or ArrayBufferView on webkit.\r\n     * @param data the original data to encrypt.\r\n     * @return Observable<string> the encrypted base64 string.\r\n     */\r\n    private static encryptRsaWebAPI(subtle: SubtleCrypto, jwkObject: any, data: string): Observable<string> {\r\n        return new Observable((observer: Observer<string>) => {\r\n            const array = Crypto.toUtf8ArrayBuffer(data);\r\n            subtle.importKey('jwk', jwkObject, Crypto.algRsaOaepSha1Key, false, ['encrypt'])\r\n                .then((publicKey: any) => {\r\n                    return subtle.encrypt(Crypto.algRsaOaepSha1Key, publicKey, <any>array);\r\n                })\r\n                .then(\r\n                (result: ArrayBuffer) => {\r\n                    observer.next(Crypto.createBase64(result));\r\n                    observer.complete();\r\n                },\r\n                (error: any) => {\r\n                    observer.error(error);\r\n                });\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Encrypt with RSA/SHA-1 for IE/Older API.\r\n     *\r\n     * @param subtle the older API subtle.\r\n     * @param jwk the JSON Web key format (Stringfiy).\r\n     * @param data the original data to hash.\r\n     * @return Observable<string> the encrypted base64 string.\r\n     */\r\n    private static encryptRsaIE(subtle: any, jwk: string, data: string): Observable<string> {\r\n        return new Observable((observer: Observer<string>) => {\r\n            const array = Crypto.toUtf8ArrayBuffer(data);\r\n            const onerror = (error: any) => {\r\n                observer.error(error);\r\n            };\r\n            const jwkBytes = Crypto.toArrayBuffer(jwk);\r\n            const importKeyOp: any = subtle.importKey('jwk', jwkBytes, Crypto.algRsaOaepSha1Key, false, ['encrypt']);\r\n            importKeyOp.oncomplete = (importKeyOpOnCompleteEvent: any) => {\r\n                const publicKey: any = importKeyOpOnCompleteEvent.target.result;\r\n                const encryptOp: any = subtle.encrypt(Crypto.algRsaOaepSha1Key, publicKey, array);\r\n                encryptOp.oncomplete = (encryptOpOnCompleteEvent: any) => {\r\n                    observer.next(Crypto.createBase64(encryptOpOnCompleteEvent.target.result));\r\n                    observer.complete();\r\n                };\r\n                encryptOp.onerror = onerror;\r\n            };\r\n            importKeyOp.onerror = onerror;\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Sign with HMAC for WebAPI.\r\n     *\r\n     * @param subtle the Web API subtle.\r\n     * @param key the key.\r\n     * @param data the original data to encrypt.\r\n     * @return Observable<string> the encrypted base64 string.\r\n     */\r\n    private static signHmacWebAPI(subtle: SubtleCrypto, key: string, data: string): Observable<string> {\r\n        return new Observable((observer: Observer<string>) => {\r\n            const array = Crypto.toUtf8ArrayBuffer(data);\r\n            const keyObject = <any>Crypto.toArrayBufferView(window.atob(key));\r\n            subtle.importKey('raw', keyObject, Crypto.algHmacSha256Key, false, ['sign'])\r\n                .then((publicKey: any) => {\r\n                    return subtle.sign(Crypto.algHmacSha256Key, publicKey, <any>array);\r\n                })\r\n                .then(\r\n                (result: ArrayBuffer) => {\r\n                    observer.next(Crypto.createBase64(result));\r\n                    observer.complete();\r\n                },\r\n                (error: any) => {\r\n                    observer.error(error);\r\n                });\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Sign with HMAC for IE/Older API.\r\n     *\r\n     * @param subtle the older API subtle.\r\n     * @param jwk the key.\r\n     * @param data the original data to hash.\r\n     * @return Observable<string> the encrypted base64 string.\r\n     */\r\n    private static signHmacIE(subtle: any, key: string, data: string): Observable<string> {\r\n        return new Observable((observer: Observer<string>) => {\r\n            const array = Crypto.toUtf8ArrayBuffer(data);\r\n            const onerror = (error: any) => {\r\n                observer.error(error);\r\n            };\r\n            const keyBytes = Crypto.toArrayBuffer(window.atob(key));\r\n            const importKeyOp: any = subtle.importKey('raw', keyBytes, Crypto.algHmacSha256Key, false, ['sign']);\r\n            importKeyOp.oncomplete = (importKeyOpEvent: any) => {\r\n                const publicKey: any = importKeyOpEvent.target.result;\r\n                const encryptOp: any = subtle.sign(Crypto.algHmacSha256Key, publicKey, array);\r\n                encryptOp.oncomplete = (encryptOpEvent: any) => {\r\n                    observer.next(Crypto.createBase64(encryptOpEvent.target.result));\r\n                    observer.complete();\r\n                };\r\n                encryptOp.onerror = onerror;\r\n            };\r\n            importKeyOp.onerror = onerror;\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Create hex string from byte raw data.\r\n     *\r\n     * @param bytes the array buffer.\r\n     * @return string the hex string.\r\n     */\r\n    private static toHexString(bytes: ArrayBuffer): string {\r\n        const array = new Uint8Array(bytes);\r\n        let hexText = '';\r\n        for (let i = 0; i < array.length; i++) {\r\n            const hex = array[i].toString(16);\r\n            hexText += (hex.length === 1 ? '0' : '') + hex;\r\n        }\r\n\r\n        return hexText;\r\n    }\r\n\r\n    /**\r\n     * Create Uint8Array from a string.\r\n     *\r\n     * @param data The string data.\r\n     * @return Uint8Array The bytes array.\r\n     */\r\n    private static toUint8Array(data: string): Uint8Array {\r\n        const temp: number[] = [];\r\n        for (let i = 0; i < data.length; i++) {\r\n            const ch = data.charCodeAt(i);\r\n            temp.push((ch & 0x0ff00) >> 8);\r\n            temp.push(ch & 0x0ff);\r\n        }\r\n\r\n        return new Uint8Array(temp);\r\n    }\r\n\r\n    /**\r\n     * Create ArrayBuffer from a string with unicode.\r\n     *\r\n     * @param data The string data.\r\n     * @return ArrayBuffer The bytes array.\r\n     */\r\n    private static toUtf8ArrayBuffer(data: string): ArrayBuffer {\r\n        const utf8 = Crypto.utf8Encode(data);\r\n        return Crypto.toArrayBuffer(utf8);\r\n    }\r\n\r\n    /**\r\n     * Encode utf8 string.\r\n     *\r\n     * @param data the unencoded string.\r\n     */\r\n    private static utf8Encode(data: string): string {\r\n        return unescape(encodeURIComponent(data));\r\n    }\r\n\r\n    /**\r\n     * Create ArrayBuffer from a string with unicode.\r\n     *\r\n     * @param data The string data.\r\n     * @return ArrayBuffer The bytes array.\r\n     */\r\n    private static toArrayBuffer(data: string): ArrayBuffer {\r\n        const buffer = new ArrayBuffer(data.length);\r\n        const view = new Uint8Array(buffer);\r\n        for (let i = 0; i < buffer.byteLength; i++) {\r\n            view[i] = data.charCodeAt(i);\r\n        }\r\n\r\n        return buffer;\r\n    }\r\n\r\n    /**\r\n     * Create ArrayBufferView from a string with unicode.\r\n     *\r\n     * @param data The string data.\r\n     * @return ArrayBuffer The bytes array.\r\n     */\r\n    private static toArrayBufferView(data: string): ArrayBufferView {\r\n        const buffer = new ArrayBuffer(data.length);\r\n        const view = new Uint8Array(buffer);\r\n        for (let i = 0; i < buffer.byteLength; i++) {\r\n            view[i] = data.charCodeAt(i);\r\n        }\r\n\r\n        return view;\r\n    }\r\n\r\n    /**\r\n     * Create base64 from byte data.\r\n     *\r\n     * @param data The byte data.\r\n     * @return string The base64 encoded data.\r\n     */\r\n    private static createBase64(data: ArrayBuffer): string {\r\n        return Base64ArrayBuffer.Encode(data);\r\n    }\r\n}\r\n"]}