Skip to content

Latest commit

 

History

History
133 lines (91 loc) · 4.73 KB

README.md

File metadata and controls

133 lines (91 loc) · 4.73 KB

Schnorr Signatures

A javaScript library for signing and verifying Schnorr Signatures.

It can be used for single and multi signatures with and without exposing the public keys individually.

Requirements | Installing | Examples | License | Contributing

npm version license GitHub Workflow Status GitHub issues

npm downloads Libraries.io dependency status for GitHub repo GitHub pull requests

Requirements:

  • Node: >=16.x, <=20.x
  • npm (Node.js package manager) v9.x.x

Installing

Package manager

$ npm install @lorhansohaky/schnorrkel.js

Using yarn:

$ yarn add @lorhansohaky/schnorrkel.js

Git

git clone https://github.com/LorhanSohaky/schnorrkel.js
cd schnorrkel.js
npm install

Examples

Single Signatures

We refer to Single Signatures as ones that have a single signer.

Sign:

import Schnorrkel from '@lorhansohaky/schnorrkel.js/'
import { generateRandomKeys } from '@lorhansohaky/schnorrkel.js/core'

const keyPair = generateRandomKeys()
const privateKey = randomBytes(32) // Buffer
const msg = 'test message'
const {signature, finalPublicNonce} = Schnorrkel.sign(keyPair.privateKey, msg)

Offchain verification:

const publicKey: Buffer = ... (derived from the privateKey)
// signature and finalPublicNonce come from s
const result = Schnorrkel.verify(signature, msg, finalPublicNonce, publicKey)

You can see the full implementation in tests/schnorrkel/sign.test.ts and tests/schnorrkel/verify.test.ts in this repository.

Multisig

Schnorr multisignatures work on the basis n/n - all of the signers need to sign in order for the signature to be valid. Below are all the steps needed to craft a successful multisig.

Public nonces

Public nonces need to be exchanged between signers before they sign. Normally, the Signer should implement this library as define a getPublicNonces method that will call the library and return the nonces. For our test example, we're going to call the schnorrkel library directly:

import Schnorrkel from '@lorhansohaky/schnorrkel.js/'
import { generateRandomKeys } from '@lorhansohaky/schnorrkel.js/core'

const schnorrkel = new Schnorrkel()

const keyPair1 = generateRandomKeys()
const keyPair2 = generateRandomKeys()
const publicNonces1 = schnorrkel.generatePublicNonces(keyPair1.privateKey)
const publicNonces2 = schnorrkel.generatePublicNonces(keyPair2.privateKey)

You can see the full implementation in tests/unsafe-schnorrkel/generatePublicNonces.test.ts in this repository.

sign

After we have them, here is how to sign:

import Schnorrkel from '@lorhansohaky/schnorrkel.js/'
import { generateRandomKeys } from '@lorhansohaky/schnorrkel.js/core'

const schnorrkelOne = new Schnorrkel()
const schnorrkelTwo = new Schnorrkel()

const keyPairOne = generateRandomKeys()
const keyPairTwo = generateRandomKeys()

const publicNoncesOne = schnorrkelOne.generatePublicNonces(keyPairOne.privateKey)
const publicNoncesTwo = schnorrkelTwo.generatePublicNonces(keyPairTwo.privateKey)

const publicKeys = [keyPair1.publicKey, keyPair2.publicKey]
const publicNonces = [publicNoncesOne, publicNoncesTwo]
const combinedPublicKey = schnorrkel.getCombinedPublicKey(publicKeys)

const msg = 'test message'

const signatureOne = schnorrkelOne.multiSigSign(keyPairOne.privateKey, msg, combinedPublicKey, publicNonces)
const signatureTwo = schnorrkelTwo.multiSigSign(keyPairTwo.privateKey, msg, combinedPublicKey, publicNonces)

const signatures = [signatureOne.signature, signatureTwo.signature]
const signaturesSummed = Schnorrkel.sumSigs(signatures)
const result = Schnorrkel.verify(signaturesSummed, msg, signatureTwo.finalPublicNonce, combinedPublicKeyTwo.combinedKey)

You can see the full implementation in tests/schnorrkel/sumSigs.test.ts, tests/unsafe-schnorrkel/multiSigSign.test.ts and tests/schnorrkel/verify.test.ts in this repository.