Coder Social home page Coder Social logo

ethereum / js-ethereum-cryptography Goto Github PK

View Code? Open in Web Editor NEW
690.0 20.0 93.0 1.6 MB

Every cryptographic primitive needed to work on Ethereum, for the browser and Node.js

License: MIT License

TypeScript 96.26% JavaScript 3.42% Shell 0.32%
ethereum cryptography typescript keccak scrypt prng sha256 ripemd160 blake2b aes

js-ethereum-cryptography's Introduction

ethereum-cryptography

npm version license

Audited pure JS library containing all Ethereum-related cryptographic primitives.

Included algorithms, implemented with just 5 noble & scure dependencies:

April 2023 update: v2.0 is out, switching noble-secp256k1 to noble-curves, which changes re-exported api of secp256k1 submodule. There have been no other changes.

January 2022 update: v1.0 has been released. We've rewritten the library from scratch and audited it. It became 6x smaller: ~5,000 lines of code instead of ~24,000 (with all deps); 650KB instead of 10.2MB. 5 dependencies by 1 author are now used, instead of 38 by 5 authors.

Check out Upgrading section and an article about the library: A safer, smaller, and faster Ethereum cryptography stack.

Usage

Use NPM / Yarn in node.js / browser:

# NPM
npm install ethereum-cryptography

# Yarn
yarn add ethereum-cryptography

See browser usage for information on using the package with major Javascript bundlers. It is tested with Webpack, Rollup, Parcel and Browserify.

This package has no single entry-point, but submodule for each cryptographic primitive. Read each primitive's section of this document to learn how to use them.

The reason for this is that importing everything from a single file will lead to huge bundles when using this package for the web. This could be avoided through tree-shaking, but the possibility of it not working properly on one of the supported bundlers is too high.

// Hashes
import { sha256 } from "ethereum-cryptography/sha256.js";
import { keccak256 } from "ethereum-cryptography/keccak.js";
import { ripemd160 } from "ethereum-cryptography/ripemd160.js";
import { blake2b } from "ethereum-cryptography/blake2b.js";

// KDFs
import { pbkdf2Sync } from "ethereum-cryptography/pbkdf2.js";
import { scryptSync } from "ethereum-cryptography/scrypt.js";

// Random
import { getRandomBytesSync } from "ethereum-cryptography/random.js";

// AES encryption
import { encrypt } from "ethereum-cryptography/aes.js";

// secp256k1 elliptic curve operations
import { secp256k1 } from "ethereum-cryptography/secp256k1.js";

// BIP32 HD Keygen, BIP39 Mnemonic Phrases
import { HDKey } from "ethereum-cryptography/hdkey.js";
import { generateMnemonic } from "ethereum-cryptography/bip39/index.js";
import { wordlist } from "ethereum-cryptography/bip39/wordlists/english.js";

// utilities
import { hexToBytes, toHex, utf8ToBytes } from "ethereum-cryptography/utils.js";

Hashes: SHA256, keccak-256, RIPEMD160, BLAKE2b

function sha256(msg: Uint8Array): Uint8Array;
function sha512(msg: Uint8Array): Uint8Array;
function keccak256(msg: Uint8Array): Uint8Array;
function ripemd160(msg: Uint8Array): Uint8Array;
function blake2b(msg: Uint8Array, outputLength = 64): Uint8Array;

Exposes following cryptographic hash functions:

  • SHA2 (SHA256, SHA512)
  • keccak-256 variant of SHA3 (also keccak224, keccak384, and keccak512)
  • RIPEMD160
  • BLAKE2b
import { sha256 } from "ethereum-cryptography/sha256.js";
import { sha512 } from "ethereum-cryptography/sha512.js";
import { keccak256, keccak224, keccak384, keccak512 } from "ethereum-cryptography/keccak.js";
import { ripemd160 } from "ethereum-cryptography/ripemd160.js";
import { blake2b } from "ethereum-cryptography/blake2b.js";

sha256(Uint8Array.from([1, 2, 3]))

// Can be used with strings
import { utf8ToBytes } from "ethereum-cryptography/utils.js";
sha256(utf8ToBytes("abc"))

// If you need hex
import { bytesToHex as toHex } from "ethereum-cryptography/utils.js";
toHex(sha256(utf8ToBytes("abc")))

KDFs: PBKDF2, Scrypt

function pbkdf2(password: Uint8Array, salt: Uint8Array, iterations: number, keylen: number, digest: string): Promise<Uint8Array>;
function pbkdf2Sync(password: Uint8Array, salt: Uint8Array, iterations: number, keylen: number, digest: string): Uint8Array;
function scrypt(password: Uint8Array, salt: Uint8Array, N: number, p: number, r: number, dkLen: number, onProgress?: (progress: number) => void): Promise<Uint8Array>;
function scryptSync(password: Uint8Array, salt: Uint8Array, N: number, p: number, r: number, dkLen: number, onProgress?: (progress: number) => void)): Uint8Array;

The pbkdf2 submodule has two functions implementing the PBKDF2 key derivation algorithm in synchronous and asynchronous ways. This algorithm is very slow, and using the synchronous version in the browser is not recommended, as it will block its main thread and hang your UI. The KDF supports sha256 and sha512 digests.

The scrypt submodule has two functions implementing the Scrypt key derivation algorithm in synchronous and asynchronous ways. This algorithm is very slow, and using the synchronous version in the browser is not recommended, as it will block its main thread and hang your UI.

Encoding passwords is a frequent source of errors. Please read these notes before using these submodules.

import { pbkdf2 } from "ethereum-cryptography/pbkdf2.js";
import { utf8ToBytes } from "ethereum-cryptography/utils.js";
// Pass Uint8Array, or convert strings to Uint8Array
console.log(await pbkdf2(utf8ToBytes("password"), utf8ToBytes("salt"), 131072, 32, "sha256"));
import { scrypt } from "ethereum-cryptography/scrypt.js";
import { utf8ToBytes } from "ethereum-cryptography/utils.js";
console.log(await scrypt(utf8ToBytes("password"), utf8ToBytes("salt"), 262144, 8, 1, 32));

CSPRNG (Cryptographically strong pseudorandom number generator)

function getRandomBytes(bytes: number): Promise<Uint8Array>;
function getRandomBytesSync(bytes: number): Uint8Array;

The random submodule has functions to generate cryptographically strong pseudo-random data in synchronous and asynchronous ways.

Backed by crypto.getRandomValues in browser and by crypto.randomBytes in node.js. If backends are somehow not available, the module would throw an error and won't work, as keeping them working would be insecure.

import { getRandomBytesSync } from "ethereum-cryptography/random.js";
console.log(getRandomBytesSync(32));

secp256k1 curve

function getPublicKey(privateKey: Uint8Array, isCompressed = true): Uint8Array;
function sign(msgHash: Uint8Array, privateKey: Uint8Array): { r: bigint; s: bigint; recovery: number };
function verify(signature: Uint8Array, msgHash: Uint8Array, publicKey: Uint8Array): boolean
function getSharedSecret(privateKeyA: Uint8Array, publicKeyB: Uint8Array): Uint8Array;
function utils.randomPrivateKey(): Uint8Array;

The secp256k1 submodule provides a library for elliptic curve operations on the curve secp256k1. For detailed documentation, follow README of noble-curves, which the module uses as a backend.

secp256k1 private keys need to be cryptographically secure random numbers with certain characteristics. If this is not the case, the security of secp256k1 is compromised. We strongly recommend using utils.randomPrivateKey() to generate them.

import { secp256k1 } from "ethereum-cryptography/secp256k1.js";
(async () => {
  // You pass either a hex string, or Uint8Array
  const privateKey = "6b911fd37cdf5c81d4c0adb1ab7fa822ed253ab0ad9aa18d77257c88b29b718e";
  const messageHash = "a33321f98e4ff1c283c76998f14f57447545d339b3db534c6d886decb4209f28";
  const publicKey = secp256k1.getPublicKey(privateKey);
  const signature = secp256k1.sign(messageHash, privateKey);
  const isSigned = secp256k1.verify(signature, messageHash, publicKey);
})();

We're also providing a compatibility layer for users who want to upgrade from tiny-secp256k1 or secp256k1 modules without hassle. Check out secp256k1 compatibility layer.

BIP32 HD Keygen

Hierarchical deterministic (HD) wallets that conform to BIP32 standard. Also available as standalone package scure-bip32.

This module exports a single class HDKey, which should be used like this:

import { HDKey } from "ethereum-cryptography/hdkey.js";
const hdkey1 = HDKey.fromMasterSeed(seed);
const hdkey2 = HDKey.fromExtendedKey(base58key);
const hdkey3 = HDKey.fromJSON({ xpriv: string });

// props
[hdkey1.depth, hdkey1.index, hdkey1.chainCode];
console.log(hdkey2.privateKey, hdkey2.publicKey);
console.log(hdkey3.derive("m/0/2147483647'/1"));
const sig = hdkey3.sign(hash);
hdkey3.verify(hash, sig);

Note: chainCode property is essentially a private part of a secret "master" key, it should be guarded from unauthorized access.

The full API is:

class HDKey {
  public static HARDENED_OFFSET: number;
  public static fromMasterSeed(seed: Uint8Array, versions: Versions): HDKey;
  public static fromExtendedKey(base58key: string, versions: Versions): HDKey;
  public static fromJSON(json: { xpriv: string }): HDKey;

  readonly versions: Versions;
  readonly depth: number = 0;
  readonly index: number = 0;
  readonly chainCode: Uint8Array | null = null;
  readonly parentFingerprint: number = 0;

  get fingerprint(): number;
  get identifier(): Uint8Array | undefined;
  get pubKeyHash(): Uint8Array | undefined;
  get privateKey(): Uint8Array | null;
  get publicKey(): Uint8Array | null;
  get privateExtendedKey(): string;
  get publicExtendedKey(): string;

  derive(path: string): HDKey;
  deriveChild(index: number): HDKey;
  sign(hash: Uint8Array): Uint8Array;
  verify(hash: Uint8Array, signature: Uint8Array): boolean;
  wipePrivateData(): this;
}

interface Versions {
  private: number;
  public: number;
}

The hdkey submodule provides a library for keys derivation according to BIP32.

It has almost the exact same API than the version 1.x of hdkey from cryptocoinjs, but it's backed by this package's primitives, and has built-in TypeScript types. Its only difference is that it has to be used with a named import. The implementation is loosely based on hdkey, which has MIT License.

BIP39 Mnemonic Seed Phrase

function generateMnemonic(wordlist: string[], strength: number = 128): string;
function mnemonicToEntropy(mnemonic: string, wordlist: string[]): Uint8Array;
function entropyToMnemonic(entropy: Uint8Array, wordlist: string[]): string;
function validateMnemonic(mnemonic: string, wordlist: string[]): boolean;
async function mnemonicToSeed(mnemonic: string, passphrase: string = ""): Promise<Uint8Array>;
function mnemonicToSeedSync(mnemonic: string, passphrase: string = ""): Uint8Array;

The bip39 submodule provides functions to generate, validate and use seed recovery phrases according to BIP39.

Also available as standalone package scure-bip39.

import { generateMnemonic } from "ethereum-cryptography/bip39/index.js";
import { wordlist } from "ethereum-cryptography/bip39/wordlists/english.js";
console.log(generateMnemonic(wordlist));

This submodule also contains the word lists defined by BIP39 for Czech, English, French, Italian, Japanese, Korean, Simplified and Traditional Chinese, and Spanish. These are not imported by default, as that would increase bundle sizes too much. Instead, you should import and use them explicitly.

The word lists are exported as a wordlist variable in each of these submodules:

  • ethereum-cryptography/bip39/wordlists/czech.js
  • ethereum-cryptography/bip39/wordlists/english.js
  • ethereum-cryptography/bip39/wordlists/french.js
  • ethereum-cryptography/bip39/wordlists/italian.js
  • ethereum-cryptography/bip39/wordlists/japanese.js
  • ethereum-cryptography/bip39/wordlists/korean.js
  • ethereum-cryptography/bip39/wordlists/portuguese.js
  • ethereum-cryptography/bip39/wordlists/simplified-chinese.js
  • ethereum-cryptography/bip39/wordlists/spanish.js
  • ethereum-cryptography/bip39/wordlists/traditional-chinese.js

AES Encryption

function encrypt(msg: Uint8Array, key: Uint8Array, iv: Uint8Array, mode = "aes-128-ctr", pkcs7PaddingEnabled = true): Promise<Uint8Array>;
function decrypt(cypherText: Uint8Array, key: Uint8Array, iv: Uint8Array, mode = "aes-128-ctr", pkcs7PaddingEnabled = true): Promise<Uint8Array>;

The aes submodule contains encryption and decryption functions implementing the Advanced Encryption Standard algorithm.

Encrypting with passwords

AES is not supposed to be used directly with a password. Doing that will compromise your users' security.

The key parameters in this submodule are meant to be strong cryptographic keys. If you want to obtain such a key from a password, please use a key derivation function like pbkdf2 or scrypt.

Operation modes

This submodule works with different block cipher modes of operation. If you are using this module in a new application, we recommend using the default.

While this module may work with any mode supported by OpenSSL, we only test it with aes-128-ctr, aes-128-cbc, and aes-256-cbc. If you use another module a warning will be printed in the console.

We only recommend using aes-128-cbc and aes-256-cbc to decrypt already encrypted data.

Padding plaintext messages

Some operation modes require the plaintext message to be a multiple of 16. If that isn't the case, your message has to be padded.

By default, this module automatically pads your messages according to PKCS#7. Note that this padding scheme always adds at least 1 byte of padding. If you are unsure what anything of this means, we strongly recommend you to use the defaults.

If you need to encrypt without padding or want to use another padding scheme, you can disable PKCS#7 padding by passing false as the last argument and handling padding yourself. Note that if you do this and your operation mode requires padding, encrypt will throw if your plaintext message isn't a multiple of 16.

This option is only present to enable the decryption of already encrypted data. To encrypt new data, we recommend using the default.

How to use the IV parameter

The iv parameter of the encrypt function must be unique, or the security of the encryption algorithm can be compromised.

You can generate a new iv using the random module.

Note that to decrypt a value, you have to provide the same iv used to encrypt it.

How to handle errors with this module

Sensitive information can be leaked via error messages when using this module. To avoid this, you should make sure that the errors you return don't contain the exact reason for the error. Instead, errors must report general encryption/decryption failures.

Note that implementing this can mean catching all errors that can be thrown when calling on of this module's functions, and just throwing a new generic exception.

Example usage

import { encrypt } from "ethereum-cryptography/aes.js";
import { hexToBytes, utf8ToBytes } from "ethereum-cryptography/utils.js";

console.log(
  encrypt(
    utf8ToBytes("message"),
    hexToBytes("2b7e151628aed2a6abf7158809cf4f3c"),
    hexToBytes("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")
  )
);

Browser usage

Rollup setup

Using this library with Rollup requires the following plugins:

These can be used by setting your plugins array like this:

  plugins: [
    commonjs(),
    resolve({
      browser: true,
      preferBuiltins: false,
    }),
  ]

Legacy secp256k1 compatibility layer

Warning: use secp256k1 instead. This module is only for users who upgraded from ethereum-cryptography v0.1. It could be removed in the future.

The API of secp256k1-compat is the same as secp256k1-node:

import { createPrivateKeySync, ecdsaSign } from "ethereum-cryptography/secp256k1-compat";
const msgHash = Uint8Array.from(
  "82ff40c0a986c6a5cfad4ddf4c3aa6996f1a7837f9c398e17e5de5cbd5a12b28",
  "hex"
);
const privateKey = createPrivateKeySync();
console.log(Uint8Array.from(ecdsaSign(msgHash, privateKey).signature));

Missing cryptographic primitives

This package intentionally excludes the cryptographic primitives necessary to implement the following EIPs:

Feel free to open an issue if you want this decision to be reconsidered, or if you found another primitive that is missing.

Upgrading

Upgrading from 1.0 to 2.0:

  1. secp256k1 module was changed massively: before, it was using noble-secp256k1 1.7; now it uses safer noble-curves. Please refer to upgrading section from curves README. Main changes to keep in mind: a) sign now returns Signature instance b) recoverPublicKey got moved onto a Signature instance
  2. node.js 14 and older support was dropped. Upgrade to node.js 16 or later.

Upgrading from 0.1 to 1.0: Same functionality, all old APIs remain the same except for the breaking changes:

  1. We return Uint8Array from all methods that worked with Buffer before. Buffer has never been supported in browsers, while Uint8Arrays are supported natively in both browsers and node.js.
  2. We target runtimes with bigint support, which is Chrome 67+, Edge 79+, Firefox 68+, Safari 14+, node.js 10+. If you need to support older runtimes, use [email protected]
  3. If you've used secp256k1, rename it to secp256k1-compat
import { sha256 } from "ethereum-cryptography/sha256.js";

// Old usage
const hasho = sha256(Buffer.from("string", "utf8")).toString("hex");

// New usage
import { toHex } from "ethereum-cryptography/utils.js";
const hashn = toHex(sha256("string"));

// If you have `Buffer` module and want to preserve it:
const hashb = Buffer.from(sha256("string"));
const hashbo = hashb.toString("hex");

Security

Audited by Cure53 on Jan 5, 2022. Check out the audit PDF & URL.

License

ethereum-cryptography is released under The MIT License (MIT)

Copyright (c) 2021 Patricio Palladino, Paul Miller, ethereum-cryptography contributors

See LICENSE file.

hdkey is loosely based on hdkey, which had MIT License

Copyright (c) 2018 cryptocoinjs

js-ethereum-cryptography's People

Contributors

1997roylee avatar alcuadrado avatar dependabot[bot] avatar fvictorio avatar igorshadurin avatar legobeat avatar omahs avatar paulmillr avatar suipotryot avatar xiaoxianboy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

js-ethereum-cryptography's Issues

Expose scrypt `onProgress`

Scrypt has optional onProgress method. Very useful for progress bars. How could we expose it? Perhaps a new alternative signature that mirrors noble-hashes? ({N, r, p, onProgress} hash). BTW, Swift built-in uses {N, r, p} hash, not function arguments.

Convert string to Uint8Array using sha256

sha256, showed here in the documentation:

const hashn = toHex(sha256("string"));

is not working properly, because sha256 is not accepting string as type, only Uint8Array.

These is the log error message:
_assert.ts:10 Uncaught (in promise) TypeError: Expected Uint8Array
at Object.bytes (_assert.ts:10:41)
at utils.js:49:27
at transfer (Transfer.jsx:22:31)
at HTMLUnknownElement.callCallback2 (react-dom.development.js:4164:14)
at Object.invokeGuardedCallbackDev (react-dom.d

and the code in the package from npm:
export declare const sha256: (msg: Uint8Array) => Uint8Array;

Question on expected time for browser computation

When running MetaMask and attempting to create a bulk group of secp256k1 addresses, my browser is spending a lot of time computing the comb10MulTo (10 seconds on 123 addresses / ~50% total runtime) that is downstream of the getPublicKey used in the ethereum-cryptography package.

Apologies if this is the wrong place to ask but is this expected when doing this sort of computation? Running the program outside of the browser is near instant. Feel free to close this issue if it is not intended to be opened here.

CallTrace for reference:
Screen Shot 2021-11-16 at 10 24 34 PM

Library does not work on the FE side

Hey, I'm trying to get this lib working on the client side with React, Vite, Javascript & pnpm.
The library was added with pnpm i ethereum-cryptography.

A utils file looks like this:

import { keccak256 } from "ethereum-cryptography/keccak";
import { utf8ToBytes, toHex } from "ethereum-cryptography/utils";
import secp from "ethereum-cryptography/secp256k1";

//...

/**
 * @returns {string} random private key as hex string
 */
function randomPrivateKey() {
    return pipe(
        secp.utils.randomPrivateKey(),
        toHex
    )
}

export {
    //...
    randomPrivateKey,
}

I use the function randomPrivateKey inside of a react component and it fails with:

Uncaught TypeError: Cannot read properties of undefined (reading 'utils')
    at randomPrivateKey (utils.js:68:14)
    at onGenerate (KeyGen.jsx:7:24)

A project that demonstrates this issue can be found here.


Sorry to bother you but I can't find solutions online. Am I missing some configuration to get this to work, or is it not possible altogether?

Same methods are working diferent in client and server sides

I pretend to send a signature from the client and recover the public key from the server-side but is not working, just for a test I did the code above and I found, or at least I presume that, an issue...

if I implement this routine in my client app, works fine, but if I do the same thing on my server side it returns an error:

Routine:
const [signature, rec] = await secp.sign(hashMessage, privateKey, { recovered: true })
const signatureHex = bytesToHex(signature)
const recoveredKey = secp.recoverPublicKey(hashMessage, signatureHex, rec);

Error:
throw new TypeError('hexToBytes: expected string, got ' + typeof hex);
^
TypeError: hexToBytes: expected string, got object

Missing crypto module when building the project using ncc and Webpack

Hi everyone, this may or may not be an issue with js-ethereum-cryptography itself but rather an issue with @vercel/ncc and webpack builds. I'm posting it here anyways in case anyone has any ideas on what is going on.

Issue
I have a project that is using a dependency that is dependent on the keccak file from [email protected]. I then bunde my project into a single JS file using the ncc build command from this project, which uses Webpack internally.

Now the issue is that ncc transforms this code to the code below as ncc can't find the crypto package for some reason:

/***/ 84310:
/***/ ((module) => {

function webpackEmptyContext(req) {
	var e = new Error("Cannot find module '" + req + "'");
	e.code = 'MODULE_NOT_FOUND';
	throw e;
}
webpackEmptyContext.keys = () => ([]);
webpackEmptyContext.resolve = webpackEmptyContext;
webpackEmptyContext.id = 84310;
module.exports = webpackEmptyContext;
/***/ }),

This leads to my project crashing with this error when I try run it:

Error: Cannot find module 'crypto'
    at Object.webpackEmptyContext (/Users/christophersastropranoto/Documents/external-adapters-js/packages/sources/layer2-sequencer-health/bundle/index.js:183577:10)
    at /Users/christophersastropranoto/Documents/external-adapters-js/packages/sources/layer2-sequencer-health/bundle/index.js:83270:43
    at Object.78777 (/Users/christophersastropranoto/Documents/external-adapters-js/packages/sources/layer2-sequencer-health/bundle/index.js:83273:3)
    at __nccwpck_require__ (/Users/christophersastropranoto/Documents/external-adapters-js/packages/sources/layer2-sequencer-health/bundle/index.js:183842:43)
    at Object.35681 (/Users/christophersastropranoto/Documents/external-adapters-js/packages/sources/layer2-sequencer-health/bundle/index.js:83194:17)
    at __nccwpck_require__ (/Users/christophersastropranoto/Documents/external-adapters-js/packages/sources/layer2-sequencer-health/bundle/index.js:183842:43)
    at Object.30038 (/Users/christophersastropranoto/Documents/external-adapters-js/packages/sources/layer2-sequencer-health/bundle/index.js:169615:16)
    at __nccwpck_require__ (/Users/christophersastropranoto/Documents/external-adapters-js/packages/sources/layer2-sequencer-health/bundle/index.js:183842:43)
    at Object.55944 (/Users/christophersastropranoto/Documents/external-adapters-js/packages/sources/layer2-sequencer-health/bundle/index.js:168123:14)
    at __nccwpck_require__ (/Users/christophersastropranoto/Documents/external-adapters-js/packages/sources/layer2-sequencer-health/bundle/index.js:183842:43) {
  code: 'MODULE_NOT_FOUND'
}

I've confirmed that this issue is also happening when I try to build the ethereum-cryptography package by itself.

Steps to repro

Run from the root of the ethereum-cryptography repository.

  1. Add @vercel/ncc package yarn add @vercel/ncc
  2. Build the keccak.ts file. ncc build keccak.js -o bundle/index.js
  3. This should have created a new directory named bundle in the root folder with an index.js file. Inspect the generated index.js file and find the code below
exports.crypto = (() => {
    const webCrypto = typeof self === "object" && "crypto" in self ? self.crypto : undefined;
    const nodeRequire =  true &&
        __nccwpck_require__(387).bind(module); ------>. The node ID might be different
    return {
        node: nodeRequire && !webCrypto ? nodeRequire("crypto") : undefined,
        web: webCrypto
    };
})();
  1. The module with ID 387 resolves to the code below
/***/ 387:
/***/ ((module) => {

function webpackEmptyContext(req) {
	var e = new Error("Cannot find module '" + req + "'");
	e.code = 'MODULE_NOT_FOUND';
	throw e;
}
webpackEmptyContext.keys = () => ([]);
webpackEmptyContext.resolve = webpackEmptyContext;
webpackEmptyContext.id = 387;
module.exports = webpackEmptyContext;

Expected Behavior

Running ncc build does not generate a webpackEmptyContext function when looking for the crypto module.

Versions

@vercel/ncc: 0.34.0

Any suggestions on what to check are appreciated! Thanks in advance.

Release 2.1.3

Would be much appreciated with a release incorporating these changes merged since last release 2.1.2:

Given the pinning on specific versions of dependencies, defaulting users to the latest versions of noble packages without need of forcing resolutions etc seems good.

Related: #93

Error: recovery id invalid at Signature.recoverPublicKey

// Client

function signMessage(message, privateKey){
  const msgHash = keccak256(utf8ToBytes(message));
  const signature = secp256k1.sign(msgHash, privateKey); 
  console.log('signature', signature); // {r: 1234.., s:5677.., recovery: 1}
  return signature.toCompactHex();
}

The client sends the signature in hex format.

// Server

  const msgHash = keccak256(utf8ToBytes(String(amount)));
  const sig = secp256k1.Signature.fromCompact(signature);
  console.log("sig", sig); // {r: 1234.., s:5677.., recovery: undefined}
  const publicKey = sig.recoverPublicKey(msgHash).toRawBytes();

To recover the publicKey, after applying fromCompact function, the signature recovery property becomes undefined (expecting 1) and recoverPublicKey() throw error: recovery id invalid.

In this scenario I solved the problem in the server by adding the recovery bit.

 const sig = secp256k1.Signature.fromCompact(signature).addRecoveryBit(1);

I'm really not sure if this is a problem or if the way I'm sending signatures from client to server is correct. This is my first time using the library and I'm trying to learn more about it. Can someone tell me what's going on?

By the way, I would be happy if someone could share some documentations about the library. I couldn't find it.

Implement transparent builds

Provenance allows to transparently build the package on github servers and provide public log.

It's already done for js-e-c dependencies. Example: https://www.npmjs.com/package/@scure/bip32, see the bottom part of the page.

To enable provenance, we need:

  • Add github CI configuration file (I can do this) such as this one
  • Generate NPM publish token on npmjs.org
  • Add the publish token as NPM_PUBLISH_TOKEN secret env variable to github repository settings

https://github.blog/2023-04-19-introducing-npm-package-provenance/

Remove 0x prefix in hexToBytes

When I saw hexToBytes I expected it to work on 0x-prefixed strings, but found that it doesn't parse them as expected.

Current results:

> e.hexToBytes('0xab')
Uint8Array(2) [ 0, 171 ]
> e.hexToBytes('ab')
Uint8Array(1) [ 171 ]

What are your thoughts on removing the 0x prefix automatically?

Feel free to crib some code

This isn't really an issue so much as an FYI.

I wrote https://github.com/Zoltu/ethereum-crypto which is a native implementation of all of the Ethereum crypto mechanisms that are not available natively in web crypto. It comes with some caveats (see readme) but it is CC0 so you are free to crib the code with no attribution if you like.

The big sell of that library is that it is a single package that has everything you need for Ethereum crypto in it, and it uses native (browser) constructs/types only. This package on the other hand brings in ~32 transitive dependencies and uses NodeJS primitives (e.g., Buffer) in its types and non-native big numbers (bn.js instead of bigint).


I can appreciate that this library makes more sense for some people in some situations, but I wanted to put it out there that if you are targeting modern browsers (bigint supported), then @zoltu/ethereum-crypto may be a better option, or at least one worth investigating or cribbing code from.


For the authors of this library, I encourage you to steal any of the work I have done as I want to see the Ethereum ecosystem succeed far more than I want credit for anything.

Include ESM version of code in the package

Using ethereum-cryptography with a SvelteKit app, I ran into some issues due to current bugs in the treatment of CommonJS modules by either SvelteKit or Vite. While this is a bug in those tools, it would be avoided if the package included ESM modules. What do you think about including that? It looks like it would also play well with ESM modules in Node.js.

keccak fails on alpine linux

On alpine linux (node:12-alpine docker image),ethereumjs-tx fails to sign transaction because the keccak function fails on alpine linux. It seems only a specific case for alpine linux. works well on ubuntu.

cryptocoinjs/keccak#15

Migration plan discussion

I'm creating this issue to start discussing the migration plan.

The main things to understand and plan upon are:

  • Which are the typical Ethereum development setups that use native dependencies. e.g. Truffle 4, Truffle 5, Embark, Buidler, etc

  • Which libraries from those setups use native dependencies.

  • Which versions of those are used in each of the setups.

  • For each version: is releasing a patch version enough, or is it pinned/bundled by some of its consumers? If pinned/bundled, how do we work around this?

Feel free to add anything relevant to the list.

Build fails when project depends on this package

When using version 2.1.0. build failed

Module not found: Error: Package path ./keccak is not exported from package /opt/atlassian/pipelines/agent/build/node_modules/@toruslabs/base-controllers/node_modules/ethereum-cryptography (see exports field in /opt/atlassian/pipelines/agent/build/node_modules/@toruslabs/base-controllers/node_modules/ethereum-cryptography/package.json)

Do we have support for base64 encoding in util package?

I checked the util package and don't find the base64 util, I guess this is a common feature that we can support.
For example, when we use AES to encode something to hex, then commonly we use base64 to encode the string and store in disk.
If you add this feature, I guess that will help a lot of people, thank you

Switch to more secure & faster secp256k1 library, shave-off 90kb

Hi! I've created noble-secp256k1 one year ago. The goal was to create an extremely simple zero-dependency library. With all the optimizations, even though it's just <1kloc, it's actually faster than elliptic — which you're using right now:

noble#sign x 3,952 ops/sec
elliptic#sign x 1,808 ops/sec
noble#verify x 851 ops/sec
elliptic#verify x 812 ops/sec

The reasoning behind the creation was that more and more dependencies are used in all kinds of projects, and there is a huge need in reducing the number — because any dep could get hacked, and it becomes complex to verify the source code by hand. Check out the blog post: https://paulmillr.com/posts/noble-secp256k1-fast-ecc/

  • noble secp is 10kb minified, while your current elliptic + bn.js is ~100kb, you'll save 90kb — which is a lot
  • noble was audited by Cure53. Elliptic was not audited, so noble should be considered more secure
  • elliptic does not seem to be maintained. Elliptic recently had terrible private key leak (CVE-2020-28498)
  • you'll receive faster signatures and verification

I strongly recommend switching to noble. I can prepare a pull request.

The keccak package sometimes causes segfaults on Node v14

I'm sorry my reproduction steps are so horrible... but I just haven't been able to figure out how to reliably trigger the error.

To reproduce:

  1. git clone https://github.com/trufflesuite/ganache-core.git
  2. cd ganache-core
  3. git checkout 8a4fb09c970d2ded061c1b1e1fd912cd7ae0229a
  4. nvm use 14
  5. npm ci
  6. npm test (you may have to run this many times until you trigger the segfault)

You should see something like:

Segmentation fault (core dumped)
npm ERR! code 139
npm ERR! path /home/david/work/ganache-core
npm ERR! command failed
npm ERR! command sh -c mocha --check-leaks --recursive "./test/local"

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/david/.npm/_logs/2020-10-07T15_21_43_948Z-debug.log

(The debug log isn't helpful)

I've somewhat "fixed" this in ganache-core by patching keccak so it never loads the native modules.

To reproduce my workaround:

  1. git checkout c26ba24ebf24d1c09b328a76baf0cf43e82fba04
  2. npm ci (if you are using npm 7.0.0-rc.0 you'll need to also run npm run postinstall)
  3. npm test (run it as many times as you'd like; it doesn't crash anymore... I ran the tests for over an hour via while npm test; do :; done without a crash)

Here is the patch, if you're curious: https://github.com/trufflesuite/ganache-core/blob/c26ba24ebf24d1c09b328a76baf0cf43e82fba04/patches/keccak%2B3.0.1.patch#L1-L11

The biggest issue with my workaround is that patch-package isn't safe to use in published npm modules. :-(

I've also opened the issue in keccak, but I figured it might be faster/easier to update this package to do something like const keccak = require("keccack/js"); (untested) than it would be to get keccak to find and fix this in the native code.

Note: removing nyc from the test command reduces the likelihood of the crash, however, it does still occur when running with mocha only.

Add AES-GCM or ChaCha20Poly1305

aes is pretty bad. I know it's there for compatibility, but we should be also exposing GCM (+50-100 loc):

  • CBC Padding is easy to misuse. CTR or GCM should be preferred to it
  • GCM is better than CTR/CBC+HMAC (can be parallel; harder to misuse)
  • GCM has AAD
  • GCM is the only mode included in TLS v1.3. They've dropped all CTR/CBC ciphers!
  • If ETH non-wallet apps are using encryption, they should definitely be using GCM, not CTR/CBC

Add BLS12-381 operations

We already depend on noble-curves, which has bls12-381.

It would be great to expose the curve and its basic operations: getPublicKey, sign, verify, pairing

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.