keysplitting

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 8, 2022 License: Apache-2.0 Imports: 10 Imported by: 2

README

keysplitting

Wrapper around Go's RSA library supporting multi-party signatures and decryption

Note

We will release a stable (v1) version soon. Until then, we make no guarantees and you should not use this for production applications.

Documentation
Installation
go get github.com/bastionzero/keysplitting

Documentation

Overview

Package keysplitting implements primitives for multi-party RSA signatures using Go's crypto/rsa library

Overview

Keysplitting supports a simple and secure flow for producing multi-party signatures. First, a broker generates an ordinary RSA keypair and splits the private key into shards:

key, _ := rsa.GenerateKey(rand.Reader, 2048)
shards, err := keysplitting.SplitD(key, 2, keysplitting.Addition)
if err != nil {
    return err
}

The broker then distributes the private shards (as well as the public key) over a secure channel, destroying each shards as it is sent. If the broker will be one of the parties to the signature, it keeps one of the shards.

When it comes time to sign a message, the key shards do not need to be reassembled. Instead, each party uses its shard to generate a partial signature. It is these partial signatures, not the shards, that are combined to create the final valid signature. This can be verified against the public key in the usual way:

err = rsa.VerifyPKCS1v15(&key.PublicKey, crypto.SHA512, hash, fullSig)

The additive vs. multiplicative split schemes

Keysplitting offers two algorithms for splitting the private key, Addition and Multiplication, specified by the SplitBy type. Both methods are equally secure and applicable to most use cases. However, the following differences may lead you to choose one over the other:

  • The Multiplication algorithm supports blinding during signature (TODO: not yet implemented)
  • The Multiplication algorithm can only be used sequentially (i.e. partial signatures / decryptions are generated one at a time by parties who each have their own shard)
  • The Addition algorithm can be used sequentially. Alternatively, all parties can partially sign at once and send the results to a broker, who can combine them without using a key shard

To learn how to use each algorithm, see the examples. To learn more about how they work, see this TODO: detailed explanation published somewhere!!

Sources

[1] https://eprint.iacr.org/2001/060.pdf
[2] https://crypto.stanford.edu/semmail/mrsa.pdf

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SignFirst

func SignFirst(random io.Reader, shard *SplitPrivateKey, hashFn crypto.Hash, hashed []byte) ([]byte, error)

SignFirst uses the given key shard to perform the initial signature on a hashed message. Note that hashed must be the result of hashing the input message using the given hash function

func SignNext

func SignNext(random io.Reader, shard *SplitPrivateKey, hashFn crypto.Hash, hashed []byte, splitBy SplitBy, partialSig []byte) ([]byte, error)

SignNext uses the given key shard to sign a partially-signed message

If SplitBy.Multiplication is used, nextSig(H) <- partialSig(H)^shard (mod N), i.e. a chain of exponentiation

If SplitBy.Addition is used, nextSig(H) <- partialSig(H) * H^shard (mod N), i.e. a chain of multiplication

Note that hashed must be the result of hashing the input message using the given hash function.

Types

type SplitBy

type SplitBy int

SplitBy determines the algorithm used to split the private key and combine partial signatures. Either algorithm is suitable from a performance and security standpoint

const (
	Multiplication SplitBy = iota
	Addition
)

type SplitPrivateKey added in v0.2.0

type SplitPrivateKey struct {
	PublicKey *rsa.PublicKey // public part
	D         *big.Int       // split private exponent

}

A SplitPrivateKey represents an RSA key shard. The public key matches that of the original key

func DecodePEM added in v0.3.0

func DecodePEM(encoded string) (*SplitPrivateKey, error)

func SplitD

func SplitD(priv *rsa.PrivateKey, k int, splitBy SplitBy) ([]*SplitPrivateKey, error)

SplitD returns k private key shards that together compose priv.D

If SplitBy.Multiplication is used, the shards will be such that s1 * s2 * ... * sk ≡ D (mod phi(N))

If SplitBy.Addition is used, the shards will be such that s1 + s2 + ... + sk ≡ D (mod phi(N))

"Either type of split lends itself equally well to two-party based signing," [1] but they are not interoperable. Whichever SplitBy method you use with SplitD, you must use the same method when running SignNext

func (*SplitPrivateKey) EncodePEM added in v0.3.0

func (spk *SplitPrivateKey) EncodePEM() (string, error)

Directories

Path Synopsis
to run these scripts, do:
to run these scripts, do:

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL