# All files / src/encryption sha2Hash.ts

97.22% Statements 35/36
83.33% Branches 10/12
100% Functions 7/7
97.22% Lines 35/36

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
    781x
    1x

    1x

    6x

    14x
    14x

    12x

    2x
    2x
    2x

    1x

    2x

    8x
    4x
    4x
    4x

    8x
    8x
    6x

    2x
    2x
    2x

    1x
    5x
    5x
    1x

    4x

    1x
    187x
    187x
    187x

    1x
    40x
    40x
    40x

     import { sha256, sha512 } from 'sha.js'
    import { getCryptoLib } from './cryptoUtils'

    type NodeCryptoCreateHash = typeof import('crypto').createHash

    export interface Sha2Hash {
      digest(data: Buffer, algorithm?: 'sha256' | 'sha512'): Promise<Buffer>;
    }

    export class NodeCryptoSha2Hash {
      createHash: NodeCryptoCreateHash

      constructor(createHash: NodeCryptoCreateHash) {
        this.createHash = createHash
      }

      async digest(data: Buffer, algorithm = 'sha256'): Promise<Buffer> {
        try {
          const result = this.createHash(algorithm)
            .update(data)
            .digest()
          return Promise.resolve(result)
        } catch (error) {
          console.log(error)
          console.log(`Error performing ${algorithm} digest with Node.js 'crypto.createHash', falling back to JS implementation.`)
          return Promise.resolve(algorithm === 'sha256' ? hashSha256Sync(data) : hashSha512Sync(data))
        }
      }
    }

    export class WebCryptoSha2Hash implements Sha2Hash {
      subtleCrypto: SubtleCrypto

      constructor(subtleCrypto: SubtleCrypto) {
        this.subtleCrypto = subtleCrypto
      }

      async digest(data: Buffer, algorithm = 'sha256'): Promise<Buffer> {
        let algo: string
        if (algorithm === 'sha256') {
          algo = 'SHA-256'
        } else Eif (algorithm === 'sha512') {
          algo = 'SHA-512'
        } else {
          throw new Error(`Unsupported hash algorithm ${algorithm}`)
        }
        try {
          const hash = await this.subtleCrypto.digest(algo, data)
          return Buffer.from(hash)
        } catch (error) {
          console.log(error)
          console.log(`Error performing ${algorithm} digest with WebCrypto, falling back to JS implementation.`)
          return Promise.resolve(algorithm === 'sha256' ? hashSha256Sync(data) : hashSha512Sync(data))
        }
      }
    }

    export async function createSha2Hash(): Promise<Sha2Hash> {
      const cryptoLib = await getCryptoLib()
      if (cryptoLib.name === 'subtleCrypto') {
        return new WebCryptoSha2Hash(cryptoLib.lib)
      } else {
        return new NodeCryptoSha2Hash(cryptoLib.lib.createHash)
      }
    }

    export function hashSha256Sync(data: Buffer) {
      const hash = new sha256()
      hash.update(data)
      return hash.digest()
    }

    export function hashSha512Sync(data: Buffer) {
      const hash = new sha512()
      hash.update(data)
      return hash.digest()
    }