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 198x 198x 198x     1x 38x 38x 38x    
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()
}