isomorphic-secp256k1

A universal JavaScript package for various ECC operations on the secp256k1 curve

Usage no npm install needed!

<script type="module">
  import isomorphicSecp256k1 from 'https://cdn.skypack.dev/isomorphic-secp256k1';
</script>

README

secp256k1 logo

isomorphic-secp256k1

An Isomorphic / Universal JavaScript elliptic curve digital signature package for the secp256k1 curve.

Features

This package has taken the bitcoin core library libsec256k1 and compiled it to a portable stand alone web assembly (Wasm) file that can be readily consumed by JavaScript.

The repository for how to achieve this can be found here.

Motivation

The Bitcoin core library,ย  libsec256k1,ย has developed strategies to mitigate various side channel attacks such asย ย differential power analysis and timing attacks for ECC signature generation. So, making the assumption that the integrity of the library is preserved after compilation of C to Wasm, this package should relay the same security ๐Ÿ”’ benefits as libsec256k1.

Additional considerations

Unlike JavaScript, Wasm operations are not subjected to garbage collection ๐Ÿ—‘๏ธ, GC ยน. This is appropriate for cryptography as GC analysis, ๐Ÿ“ˆ GCA may be used to infer users private keys through homomorphic models.

Support

Note - For testing you will need the Node.js web crypto.

Setup

$ npm i isomorphic-secp256k1

Security

For an indepth security analysis of web assembly please see: Everything Old is New Again: Binary Security of WebAssembly.

API

Table of contents

function generate_key_pair

Generate a cryptographically random secp256k1 public key and private key pair.

Returns: key_pair โ€” Random cryptographic key pair.

Examples

Ways to import.

import { generate_key_pair } from 'isomorphic-secp256k1'
import generate_key_pair from 'isomorphic-secp256k1/public/generate_key_pair.js'

Ways to require.

const { generate_key_pair } = require('isomorphic-secp256k1')
const generate_key_pair = require('isomorphic-secp256k1/public/generate_key_pair.js')

Usage generate_key_pair.

import { generate_key_pair } from 'isomorphic-secp256k1'
generate_key_pair()

function get_public_key

Given a valid secp256k1 private key return the corresponding public key.

Parameter Type Description
arg object Argument.
arg.private_key Uint8Array secp256k1 private key.

Returns: Uint8Array โ€” Compressed EC public key.

Examples

Ways to import.

import { get_public_key } from 'isomorphic-secp256k1'
import get_public_key from 'isomorphic-secp256k1/public/get_public_key.js'

Ways to require.

const { get_public_key } = require('isomorphic-secp256k1')
const get_public_key = require('isomorphic-secp256k1/public/get_public_key.js')

Usage get_public_key.

import { get_public_key } from 'isomorphic-secp256k1'

const private_key = new Uint8Array(32).fill(2)
get_public_key({ private_key })

function sha256

An isomorphic sha256 message digest function.

Parameter Type Description
data Uint8Array Binary array data to digest.

Returns: Uint8Array โ€” The message digest.


function sign_hash

Generate a secp256k1 DER signature.

Parameter Type Description
arg object Argument.
arg.hex string sha256 hash to sign.
arg.private_key Uint8Array secp256k1 private key.

Returns: Uint8Array โ€” DER encoded signature.

Examples

Ways to import.

import { sign_hash } from 'isomorphic-secp256k1'
import sign_hash from 'isomorphic-secp256k1/public/sign_hash.js'

Ways to require.

const { sign_hash } = require('isomorphic-secp256k1')
const sign_hash = require('isomorphic-secp256k1/public/sign_hash.js')

Usage sign_hash.

import { sign_hash } from 'isomorphic-secp256k1'
import crypto from 'crypto'

const private_key_hex =
  '7df0eecb35a6dc2d1faf741ac458258be61c78f57ec29a12ffd8b2cbf73f65d2'

sign_hash({
  private_key: new Uint8Array(
    private_key_hex.match(/.{2}/gm).map(i => `0x${i}`)
  ),
  hex: crypto.createHash('sha256').update('hello').digest()
}).then(console.log)

A 70 byte Uint8Array DER encoded signature will be logged.


function verify_signature

Verify a secp256k1 DER ecncoded EC signature.

Parameter Type Description
arg object Argument.
arg.hash Uint8Array The 32 byte message digest that was signed.
arg.der_signature Uint8Array 70 byte DER encoded signature to validate.
arg.public_key Uint8Array Compressed 33 byte public key.

Returns: boolean โ€” Will be true & false for valid & invalid signatures respectively.

Examples

Ways to import.

import { verify_signature } from 'isomorphic-secp256k1'
import verify_signature from 'isomorphic-secp256k1/public/verify_signature.js'

Ways to require.

const { verify_signature } = require('isomorphic-secp256k1')
const verify_signature = require('isomorphic-secp256k1/public/verify_signature.js')

Usage verify_signature.

import { verify_signature } from 'isomorphic-secp256k1'

const der_hex =
  '3044022017ab3c02fadd943ae25e4ce94fb9144942bd18ff9a8f6ed17593986014e302d10220044d1889af00d60db8bbe0b33bbce04bf62ff3e95c5af2861317243516b785f3'
const public_key_hex =
  '02c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf'
const hash_hex =
  '9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50'

verify_signature({
  der_signature: new Uint8Array(Buffer.from(der_hex, 'hex')),
  public_key: new Uint8Array(Buffer.from(public_key_hex, 'hex')),
  hash: new Uint8Array(Buffer.from(hash_hex, 'hex'))
}).then(console.log)

True will be logged if the signature was valid.


type key_pair

An asymmetric key pair for the secp256k1 curve.

Type: object

Parameter Type Description
private_key Uint8Array 32 byte key.
public_key Uint8Array 33 byte compressed key.