# All files / src/crypt decrypter.js

42.62% Statements 26/61
17.86% Branches 5/28
20% Functions 2/10
43.33% Lines 26/60

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    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
    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
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    1011x
    1x
    1x

    1x
    1x

    1x

    1x

    1x

    1x
    282x
    141x
    141x
    141x
    141x

    141x
    141x
    141x
    141x
    141x

    141x

    1x

    1x

    1x

    1x

    1x

    1x
     import AESCrypto from './aes-crypto';
    import FastAESKey from './fast-aes-key';
    import AESDecryptor from './aes-decryptor';

    import { ErrorTypes, ErrorDetails } from '../errors';
    import { logger } from '../utils/logger';

    import Event from '../events';

    import { getSelfScope } from '../utils/get-self-scope';

    // see https://stackoverflow.com/a/11237259/589493
    const global = getSelfScope(); // safeguard for code that might run both on worker and main thread

    class Decrypter {
      constructor (observer, config, { removePKCS7Padding = true } = {}) {
        this.logEnabled = true;
        this.observer = observer;
        this.config = config;
        this.removePKCS7Padding = removePKCS7Padding;
        // built in decryptor expects PKCS7 padding
        Eif (removePKCS7Padding) {
          try {
            const browserCrypto = global.crypto;
            Eif (browserCrypto) {
              this.subtle = browserCrypto.subtle || browserCrypto.webkitSubtle;
            }
          } catch (e) {}
        }
        this.disableWebCrypto = !this.subtle;
      }

      isSync () {
        return (this.disableWebCrypto && this.config.enableSoftwareAES);
      }

      decrypt (data, key, iv, callback) {
        if (this.disableWebCrypto && this.config.enableSoftwareAES) {
          if (this.logEnabled) {
            logger.log('JS AES decrypt');
            this.logEnabled = false;
          }
          let decryptor = this.decryptor;
          if (!decryptor) {
            this.decryptor = decryptor = new AESDecryptor();
          }

          decryptor.expandKey(key);
          callback(decryptor.decrypt(data, 0, iv, this.removePKCS7Padding));
        } else {
          if (this.logEnabled) {
            logger.log('WebCrypto AES decrypt');
            this.logEnabled = false;
          }
          const subtle = this.subtle;
          if (this.key !== key) {
            this.key = key;
            this.fastAesKey = new FastAESKey(subtle, key);
          }

          this.fastAesKey.expandKey()
            .then((aesKey) => {
              // decrypt using web crypto
              let crypto = new AESCrypto(subtle, iv);
              crypto.decrypt(data, aesKey)
                .catch((err) => {
                  this.onWebCryptoError(err, data, key, iv, callback);
                })
                .then((result) => {
                  callback(result);
                });
            })
            .catch((err) => {
              this.onWebCryptoError(err, data, key, iv, callback);
            });
        }
      }

      onWebCryptoError (err, data, key, iv, callback) {
        if (this.config.enableSoftwareAES) {
          logger.log('WebCrypto Error, disable WebCrypto API');
          this.disableWebCrypto = true;
          this.logEnabled = true;
          this.decrypt(data, key, iv, callback);
        } else {
          logger.error(`decrypting error : ${err.message}`);
          this.observer.trigger(Event.ERROR, { type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_DECRYPT_ERROR, fatal: true, reason: err.message });
        }
      }

      destroy () {
        let decryptor = this.decryptor;
        if (decryptor) {
          decryptor.destroy();
          this.decryptor = undefined;
        }
      }
    }

    export default Decrypter;