Git Product home page Git Product logo

ecc's Introduction

secp256k1

Golang native implementation of the secp256k1 elliptic curve

LICENSE Go version Go Report card Go Reference

Features

  • Based on Golang's native crypto/ecdsa and crypto/elliptic package, no external dependency at all
  • Full compatible with the secp256k1 signature in go-ethereum

Motivation

Golang's elliptic.Curve implements the short-form Weierstrass curve y² = x³ + ax + b, but only with a = -3, which are the case for NIST-recommended curves P224, P256,P384, and P521. For a general curve with a != -3, one would have to rely on external packages, which is quite an inconvenience.

For example, a very popular curve is secp256k1 with equation y² = x³ + 7, used by many crypto projects such as Bitcoin and Ethereum. In order to use it, one would usually need to import for example go-ethereum, which is a very large package with many dependencies.

This package provides a secp256k1 implementation solely based on Golang's native code. No external dependency is introduced.

How to use

Package's P256k1() method returns a elliptic.Curve that implements the secp256k1 curve, use it the same way as you would use other curves in the ecdsa package.

Or use package's SignBytes() and VerifyBytes() API that signs/verifies the signature as a byte-stream. See example below:

package anyname

import (
	"crypto/ecdsa"
	"crypto/rand"
	"crypto/sha256"
	"fmt"
	
	"github.com/dustinxie/ecc"
)

func signVerify(msg []byte) error {
	// generate secp256k1 private key
	p256k1 := ecc.P256k1()
	privKey, err := ecdsa.GenerateKey(p256k1, rand.Reader)
	if err != nil {
		// handle error
		return err
	}
	
	// sign message
	hash := sha256.Sum256(msg)
	sig, err := ecc.SignBytes(privKey, hash[:], ecc.Normal)
	if err != nil {
		return err
	}
	
	// verify message
	if !ecc.VerifyBytes(&privKey.PublicKey, hash[:], sig, ecc.Normal) {
		return fmt.Errorf("failed to verify secp256k1 signature")
	}
	return nil
}

Signing options

The package provides 2 additional signing options:

  • To tackle the ECDSA signature malleability issue (see "Rationale" in here), pass the flag LowerS to signing API. This ensures the resulting s value in the signature is less than or equal to half of N (the order of the curve)
// generate 64-byte signature R || S, with s <= N/2
sig, err := ecc.SignBytes(privKey, hash, ecc.LowerS)
if err != nil {
	return err
}

if !ecc.VerifyBytes(&privKey.PublicKey, hash, sig, ecc.LowerS) {
	return fmt.Errorf("failed to verify secp256k1 signature")
}
return nil
  • To return the one-byte recovery ID that can be used to recover public key from the signature, pass the flag RecID to signing API
// generate 65-byte signature R || S || V
sig, err := ecc.SignBytes(privKey, hash, ecc.RecID)
if err != nil {
	return err
}

if !ecc.VerifyBytes(&privKey.PublicKey, hash, sig, ecc.RecID) {
	return fmt.Errorf("failed to verify secp256k1 signature")
}

the resulting 65-byte signature allows you to recover public key from it:

pubKey, err := RecoverPubkey("P-256k1", hash, sig)
if err != nil {
	return err
}

if !pubKey.Equal(&privKey.PublicKey) {
	return fmt.Errorf("recovered public key not equal to signing public key")
}
return nil

The recommendation is to always enable ecc.LowerS option when signing any message. And finally, you can pass both flags to signing API:

sig, err := ecc.SignBytes(privKey, hash, ecc.LowerS | ecc.RecID)

Full Ethereum compatibility

Package also provides the following 3 API that are fully compatible with the official go-ethereum. They are actually just a wrapper of our API using proper options.

func SignEthereum(hash []byte, priv *ecdsa.PrivateKey) ([]byte, error)

func VerifyEthereum(pubkey, hash, sig []byte, isHomestead bool) bool

func RecoverEthereum(hash, sig []byte) ([]byte, error)

ecc's People

Contributors

dustinxie avatar

Watchers

 avatar

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.