Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simple isomorphic wrapper ? #56

Closed
sublimator opened this issue May 4, 2023 · 6 comments
Closed

Simple isomorphic wrapper ? #56

sublimator opened this issue May 4, 2023 · 6 comments

Comments

@sublimator
Copy link

For things like ripple library where they are using createHash one needs to create little wrappers to replace existing functions, ala:

const HASH_BYTES = 32

const sha512Half = (() => {
  const isBrowser = typeof window !== 'undefined'

  if (isBrowser) {
    const { sha512 } = require('@noble/hashes/sha512')
    const { bytesToHex, hexToBytes } = require('@noble/hashes/utils')

    return function sha512Half(hex: string): string {
      const digestHalf = sha512(hexToBytes(hex)).slice(0, HASH_BYTES)
      return bytesToHex(digestHalf).toUpperCase()
    }
  } else {
    const crypto = require('crypto')

    return function sha512Half(hex: string): string {
      const hash = crypto.createHash('sha512')
      hash.update(Buffer.from(hex, 'hex'))
      const digestHalf = hash.digest().slice(0, HASH_BYTES)
      return digestHalf.toString('hex').toUpperCase()
    }
  }
})()

to replace:

const HASH_SIZE = 64

function sha512Half(hex: string): string {
  return createHash('sha512')
    .update(Buffer.from(hex, 'hex'))
    .digest('hex')
    .toUpperCase()
    .slice(0, HASH_SIZE)
}

This is annoying, and less than ideal because you have to mess with your webpack resolve.alias rather than rely upon a browser field in package.json.

I think a simple wrapper like this would go along way:

type CreateHashFn = (algo: 'sha512' | 'sha256' | ... ) => {
  update(buffer: Uint8Array): void
  digest(): Uint8Array
}

Are you interested in doing something like this under @noble/ ?

@paulmillr
Copy link
Owner

Hey Nicholas.

I think a simple wrapper like this would go along way:

Not interested, because this (old node.js) approach is not tree-shaking friendly.

We specifically use separate files to ensure sha256 code is not included if you're only using sha512, which helps to reduce bundle size.

@sublimator
Copy link
Author

sublimator commented May 4, 2023 via email

@paulmillr
Copy link
Owner

import { sha256 } from "@noble/hashes/sha256";
import { sha512 } from "@noble/hashes/sha512";
import { sha3_256 } from "@noble/hashes/sha3";


function createHash(name) {
  if (name === 'sha256') return sha256;
  else if (name === 'sha512') return sha512;
  else if (name === 'sha3_256') return sha3_256;
}

@sublimator
Copy link
Author

sublimator commented May 5, 2023

@paulmillr

I want something that doesn't require configuration for each bundler, and would support tree shaking, so it should just expose a browser impl via package.json. I'm not sure the state of "exports" these days in that regard, but potentially that.

I was thinking more along the lines of:

import { sha256 } from "iso-hashes/sha256"

It would be a thin wrapper around @noble/hashes/sha256 for browser and crypto.createHash for node

Interface along these lines:

type ByteEncodedString = string
type Input = Uint8Array | number[] | ByteEncodedString

interface Hash {
  update(bytes: Input): this
  digest(): Uint8Array
}

type HashFn = {
  (input: Input): Uint8Array
  create(): Hash
}

@paulmillr
Copy link
Owner

Yeah, separate files for each hash could work in this case.

@sublimator
Copy link
Author

I'm not sure the state of "exports" these days

Turns out nodeResolution: Node16 is required for TS to honor it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants