OverviewFilesCommitsIssuesDocsReleasesPeers

mirall-cli / node_modules / bare-crypto / lib / hash.js

103 lines · javascript ref:
const { Transform } = require('bare-stream')
const assert = require('bare-assert')
const binding = require('../binding')
const constants = require('./constants')

const {
  hash: { RIPEMD160 }
} = constants

class CryptoDigest {
  constructor(algorithm) {
    this._handle = binding.digestInit(algorithm)
  }

  update(data) {
    if (this._handle === null) {
      throw new Error('Digest has already been finalized')
    }

    binding.digestUpdate(this._handle, data.buffer, data.byteOffset, data.byteLength)
  }

  final() {
    if (this._handle === null) {
      throw new Error('Digest has already been finalized')
    }

    const result = Buffer.from(binding.digestFinal(this._handle))
    this._handle = null
    return result
  }
}

class CryptoRIPEMD160Digest {
  constructor() {
    this._handle = binding.ripemd160Init()
  }

  update(data) {
    if (this._handle === null) {
      throw new Error('Digest has already been finalized')
    }

    binding.ripemd160Update(this._handle, data.buffer, data.byteOffset, data.byteLength)
  }

  final() {
    if (this._handle === null) {
      throw new Error('Digest has already been finalized')
    }

    const result = Buffer.from(binding.ripemd160Final(this._handle))
    this._handle = null
    return result
  }
}

module.exports = class CryptoHash extends Transform {
  constructor(algorithm, opts = {}) {
    super(opts)

    algorithm = constants.toHash(algorithm)

    switch (algorithm) {
      case RIPEMD160:
        this._digest = new CryptoRIPEMD160Digest()
        break

      default:
        this._digest = new CryptoDigest(algorithm)
        break
    }
  }

  update(data, encoding = 'utf8') {
    if (typeof data === 'string') data = Buffer.from(data, encoding)

    assert(ArrayBuffer.isView(data))

    this._digest.update(data)

    return this
  }

  digest(encoding) {
    const digest = this._digest.final()

    return encoding && encoding !== 'buffer' ? digest.toString(encoding) : digest
  }

  _transform(data, encoding, cb) {
    this.update(data)

    cb(null)
  }

  _flush(cb) {
    this.push(this.digest())

    cb(null)
  }
}