bgls

package
v0.5.3 Latest Latest
Warning

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

Go to latest
Published: Mar 5, 2021 License: Apache-2.0 Imports: 6 Imported by: 0

README

Bgls

This implements bgls signatures using the curves interface. This also implements all three methods for securing against the rogue public key attack as described in Dan Boneh's paper https://crypto.stanford.edu/~dabo/pubs/papers/BLSmultisig.html.

Definitions

Aggregate Signature

An aggregate signature allows you to take signatures for different messages, and combine them into a single signature of the same size as each of the original signatures. This aggregate signature will verify all of the message / signature pairs that compose it. There is one attack on aggregate signatures, called the rogue public key attack. There are three defense mechanisms that eliminate the attacks possibility, and they are described in the next section. Note that aggregate signatures can also be aggregated together.

This takes n+1 pairing operations, where n is the number of message / signature pairs which the aggregate signature proves.

Multi-Signature

A multi-signature is an aggregate signature where all the signatures are over the same message. Due to how bgls signatures work, this allows for the entire signatures to be verified in 2 pairings, regardless of how many signatures are aggregated together. This allows for very efficient verification.

Protections against the Rogue Public key attack

More documentation is provided in the godocs.

Enforcing distinct messages

This is implemented in DistinctMessage.go. This ensures that no two messages are used from separate pubkeys by prepending the public key before the message, thereby preventing the rogue public key attack. However this sacrifices the efficient multisig verifications, since all messages are distinct.

If you are using DistinctMsg to secure against the rogue public key attack, you are intended to use: AggregateSignatures, KeyGen, DistinctMsgSign, DistinctMsgVerifySingleSignature, DistinctMsgVerifyAggregateSignatureature

Knowledge of Secret Key (Kosk)

This is implemented in blsKosk.go. It uses a BLS signature on the public key to prove knowledge of the secret key. This method requires an authentication to be published before its corresponding public key can be used. These authentications maintain aggregatability (even with other signatures), however due to security considerations as described within the godocs, signatures produced from Kosk are not cross-compatible with that of normal BLS.

To use Kosk to secure against the rogue public key attack, you are intended to use: AggregateSignatures, KeyGen, KoskSign, KoskVerifySingleSignature, KoskVerifyMultiSignature KoskVerifyMultiSignatureWithMultiplicity, KoskVerifyAggregateSignature

BLS with hashed aggregation exponents (HAE)

This is the third method for protecting against the rogue public key attack, as described in Boneh's paper. It is implemented in blsHAE.go. This method of securing against the rogue public key attack has the upside of not requiring an authentication message and still allowing for efficient multisignature verification. However more information needs to be collected to aggregate already aggregated HAE signatures. (Since you would have to know which signatures went into each of the component aggregate signatures, and in what order they appeared.)

This method relies on a hash function from G^n \to \R^n. This library uses blake2x, where each key in G^n is written one after another, and then n*16 bytes are read from the XOF. The authors of this library know of no standard currently, if a standard hash function for this method is chosen, then this library will switch to that. However this hash satisfies the criterion laid out in Boneh's paper. We can remove the need for knowing the order in which signatures went into the hash function by sorting by the public keys in the hash, and using the sorted list throughout. Currently we don't need to worry about the order and that overhead, but we can implement this.

Note. This is called Hashed Aggregation Exponents in lieu of an official name for this defense against the rogue public key attack.

If you are using HAE to secure against the rogue public key attack, you are intended to use: KeyGen, Sign, VerifySingleSignature, AggregateSignaturesWithHAE, VerifyMultiSignatureWithHAE, VerifyAggregateSignatureWithHAE

Benchmarks

These still need to be created.

References

Documentation

Overview

Package bgls implements bls signatures, as described by Short Signatures from the Weil Pairing. In this library, an aggregate signature refers to an aggregation of signatures on different messages into a single signature. A multi signature refers to an aggregation of signatures on the same message into the same signature. The difference is that a multi signature can be verified quite quickly, using 2 pairing operations regardless of the number of signers, whereas an aggregate signature requires n+1 pairing operations.

There are three different methods to protect against the rogue public key attack. The three methods are proving knowledge of secret key (kosk), enforcing that all messages are distinct (Distinct Message), and using a hash of the public keys to create exponents that are used in aggregation (Hashed Aggregation Exponents - HAE). These are all described in https://crypto.stanford.edu/~dabo/pubs/papers/BLSmultisig.html, where HAE is Dan Boneh's new method introduced in that article.

Proof of knowledge of the secret key is done in this library through doing a BLS signature on the public key itself as a message. See blsKosk.go for more details. Note that this Kosk method is not interoperable with 'plain' bls due to design choices explained in blsKosk.go

BLS with distinct messages is done in this library by prepending the public key to each message, before signing, to ensure that it each message is unique. (thereby circumventing rogue public key attacks). See blsDistinctMessage.go for more details. Note that BLS with distinct messages does not offer multi sigs in their efficiently computable form where only 2 pairings are required.

The third method for preventing the rogue public key attack is explained in in blsHAE.go, and in Boneh's paper. The method for hashing public keys to the exponents is to write them to blake2x, and then to squeeze the corresponding amount of output from the XOF.

blsKosk.go implements Knowledge of secret key (Kosk) BLS. You do a proof to show that you know the secret key. This protects against the rogue public key attack.

Proof of knowledge of the secret key is done in this library through doing a BLS signature on the public key itself as a message. There is a situation where this doesn't prove knowledge of the secret key. Suppose there is a BLS signing oracle for (pk1, sk1). Let pkA = -pk1 + x*g_2. Note that sig_pkA(pkA) = -sig_pk1(pkA) + xH(-pk1 + x*g_2) Consequently, if pk1 signs on pkA, this doesn't prove that person A knows skA and the rogue public key attack is possible as pkA is an authenticated key. One solution to fix this is to ensure that it is impossible for pk1 to sign the same pkA that is used in authentication. The way this is implemented here is to make the sign/verify methods prepend a 0x01 byte to any message that is being signed, and to make authentication prepend a null to public key before its signed. Since one would only ever authenticate their own public key, noone could get a signature from you that would work for their own authentication. (As all signatures you give out, other than your own authentication, have a 0x01 byte prepended instead of a null byte)

Prepending bytes to ensure signing / authentication domain seperation sacrifices interoperability between KoskBls and normal BLS, however the advantage is that the authentications are aggregatable. They're aggregatable, since they are BLS signatures but all on distinct messages since they are distinct public keys.

If you are using Kosk to secure against the rogue public key attack, you are intended to use: AggregateSignatures, KeyGen, KoskSign, KoskVerifySingleSignature, KoskVerifyMultiSignature KoskVerifyMultiSignatureWithMultiplicity, KoskVerifyAggregateSignature

blsDistinctMessage.go implements the method of using Distinct Messages for aggregate signatures. This ensures that no two messages are used from separate pubkeys by prepending the public key before the message, thereby preventing the rogue public key attack.

If you are using DistinctMsg to secure against the rogue public key attack, you are intended to use: AggregateSignatures, KeyGen, DistinctMsgSign, DistinctMsgVerifySingleSignature, DistinctMsgVerifyAggregateSignature

The third method in Boneh's paper is dubbed "BLS with hashed aggregation exponents(HAE)" here, and is implemented in blsHAE.go. This is normal bls, but when aggregating you hash the `n` public keys to get `n` numbers in the range [0,2^(128)). Call these numbers t_0, t_1, ... t_{n-1}. Then you scale the ith signature to the by t_i, before multiplying them together.

For Verification, you hash to obtain the same t_0, t_1, ... t_{n-1}, and scale the public keys accordingly. Then BLS proceeds as normal with these scaled public keys. Note that this method cannot aggregate pre-aggregated signatures. (I.e. you can only aggregate once), and it also requires inputing the keys into the hash function in the same order.

The hash function from G^n \to \R^n is blake2x. The uncompressed marshal of every key is written to then blake2x instance. Then n 16 byte numbers are read from the XOF, each corresponding to a value of t.

Note. I am calling this Hashed Aggregation Exponents in lieu of a better name for this defense against the rogue public key attack.

If you are using HAE to secure against the rogue public key attack, you are intended to use: KeyGen, Sign, VerifySingleSignature, AggregateSignaturesWithHAE, VerifyMultiSignatureWithHAE, VerifyAggregateSignatureWithHAE

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AggregateKeys

func AggregateKeys(keys []Point) Point

AggregateKeys sums an array of public keys into one key. This wrapper only exists so end-users don't have to use the method from curve

func AggregateSignatures

func AggregateSignatures(sigs []Point) Point

AggregateSignatures aggregates an array of signatures into one aggsig. This wrapper only exists so end-users don't have to use the method from curves

func AggregateSignaturesWithHAE

func AggregateSignaturesWithHAE(sigs []Point, pubkeys []Point) Point

AggregateSignaturesWithHAE aggregates the signatures, using the hashed exponents derived from the pubkeys to protect against the rogue public key attack.

func AmsAggregateMembershipKeyShares added in v0.5.2

func AmsAggregateMembershipKeyShares(curve CurveSystem, shares []Point) Point

func AmsCombineSignatureShares added in v0.5.2

func AmsCombineSignatureShares(pubkeys []Point, sigs []Point) (aggKey Point, aggSig Point)

func AmsCreateMembershipKeyShares added in v0.5.2

func AmsCreateMembershipKeyShares(curve CurveSystem, sk *big.Int, curIndex int, pubkeys []Point) []Point

func AmsCreateMembershipKeySharesKnownExp added in v0.5.2

func AmsCreateMembershipKeySharesKnownExp(curve CurveSystem, sk *big.Int, apk Point, exp *big.Int, numSigners int) []Point

func AmsCreateSignatureShare added in v0.5.2

func AmsCreateSignatureShare(curve CurveSystem, sk *big.Int, membershipKey Point, msg []byte) Point

func AmsVerifySignature added in v0.5.2

func AmsVerifySignature(curve CurveSystem, apk Point, signers []int, aggKey Point, aggSig Point, msg []byte) bool

func AmsVerifySignatureWithSetCheck added in v0.5.2

func AmsVerifySignatureWithSetCheck(curve CurveSystem, check func([]int) bool, apk Point, signers []int, aggKey Point, aggSig Point, msg []byte) bool

func AmspGetMessage added in v0.5.2

func AmspGetMessage(curve CurveSystem, pubkeys []Point, msg []byte) []byte

func Authenticate

func Authenticate(curve CurveSystem, sk *big.Int) Point

Authenticate generates an Aggregatable Authentication for a given secret key. It signs the public key generated from sk, with a 0x01 byte prepended to it.

func AuthenticateCustHash

func AuthenticateCustHash(curve CurveSystem, sk *big.Int, hash func([]byte) Point) Point

AuthenticateCustHash generates an Aggregatable Authentication for a given secret key. It signs the public key generated from sk, with a null byte prepended to it. This runs with the specified hash function.

func CheckAuthentication

func CheckAuthentication(curve CurveSystem, pubkey Point, authentication Point) bool

CheckAuthentication verifies that the provided signature is in fact authentication for this public key.

func CheckAuthenticationCustHash

func CheckAuthenticationCustHash(curve CurveSystem, pubkey Point, authentication Point, hash func([]byte) Point) bool

CheckAuthenticationCustHash verifies that the provided signature is in fact authentication for this public key.

func DistinctMsgSign

func DistinctMsgSign(curve CurveSystem, sk *big.Int, m []byte) Point

DistinctMsgSign creates a signature on a message with a private key, with prepending the public key to the message.

func DistinctMsgSignCustHash

func DistinctMsgSignCustHash(curve CurveSystem, sk *big.Int, msg []byte, hash func([]byte) Point) Point

DistinctMsgSignCustHash creates a signature on a message with a private key, using a supplied function to hash to g1.

func DistinctMsgVerifyAggregateSignature

func DistinctMsgVerifyAggregateSignature(curve CurveSystem, aggsig Point, keys []Point, msgs [][]byte) bool

DistinctMsgVerifyAggregateSignature checks that an aggsig was generated from the the provided set of public key / msg pairs, when the messages are signed using the 'Distinct Message' method.

func DistinctMsgVerifySingleSignature

func DistinctMsgVerifySingleSignature(curve CurveSystem, sig Point, pubkey Point, m []byte) bool

DistinctMsgVerifySingleSignature checks that a single 'Distinct Message' signature is valid

func KeyGen

func KeyGen(curve CurveSystem) (*big.Int, Point, error)

KeyGen generates a private / public key pair. The private key is a big int, and the the public key is on G2.

func KoskSign

func KoskSign(curve CurveSystem, sk *big.Int, msg []byte) Point

KoskSign creates a kosk signature on a message with a private key. A kosk signature prepends a 0x01 byte to the message before signing.

func KoskSignCustHash

func KoskSignCustHash(curve CurveSystem, sk *big.Int, msg []byte, hash func([]byte) Point) Point

KoskSignCustHash creates a kosk signature on a message with a private key, using a supplied function to hash to point. A kosk signature prepends a 0x01 byte to the message before signing.

func KoskVerifyAggregateSignature

func KoskVerifyAggregateSignature(curve CurveSystem, aggsig Point, keys []Point, msgs [][]byte) bool

KoskVerifyAggregateSignature verifies that the aggregated signature proves that all messages were signed by the associated keys.

func KoskVerifyBatchMultiSignature added in v0.5.2

func KoskVerifyBatchMultiSignature(curve CurveSystem, aggsigs []Point, pubkeys [][]Point, msgs [][]byte) bool

KoskVerifyBatchMultiSignature checks that the set of aggregate signatures correctly proves that a set of messages has the correct associated pubkey. vulnerable against chosen key attack, if keys have not been authenticated This is faster than verifying each multisignature individually.

func KoskVerifyMultiSignature

func KoskVerifyMultiSignature(curve CurveSystem, aggsig Point, keys []Point, msg []byte) bool

KoskVerifyMultiSignature checks that the aggregate signature correctly proves that a single message has been signed by a set of keys, vulnerable against chosen key attack, if keys have not been authenticated

func KoskVerifyMultiSignatureWithMultiplicity

func KoskVerifyMultiSignatureWithMultiplicity(curve CurveSystem, aggsig Point, keys []Point,
	multiplicity []int64, msg []byte) bool

KoskVerifyMultiSignatureWithMultiplicity verifies a BLS multi signature where multiple copies of each signature may have been included in the aggregation

func KoskVerifySingleSignature

func KoskVerifySingleSignature(curve CurveSystem, sig Point, pubKey Point, msg []byte) bool

KoskVerifySingleSignature checks that a single kosk signature is valid.

func KoskVerifySingleSignatureCustHash

func KoskVerifySingleSignatureCustHash(curve CurveSystem, pubKey Point, msg []byte,
	sig Point, hash func([]byte) Point) bool

KoskVerifySingleSignatureCustHash checks that a single kosk signature is valid, with the supplied hash function.

func LoadPublicKey

func LoadPublicKey(curve CurveSystem, sk *big.Int) Point

LoadPublicKey turns secret key into a public key of type Point2

func Sign

func Sign(curve CurveSystem, sk *big.Int, msg []byte) Point

Sign creates a standard BLS signature on a message with a private key

func SignCustHash

func SignCustHash(sk *big.Int, msg []byte, hash func([]byte) Point) Point

SignCustHash creates a standard BLS signature on a message with a private key, using a supplied function to hash onto the curve where signatures lie.

func VerifyAggregateSignature

func VerifyAggregateSignature(curve CurveSystem, aggsig Point, keys []Point, msgs [][]byte) bool

VerifyAggregateSignature verifies that the aggregated signature proves that all messages were signed by the associated keys. This will fail if there are duplicate messages, due to the possibility of the rogue public-key attack. If duplicate messages should be allowed, one of the protections against the rogue public-key attack should be used. See doc.go for more details.

func VerifyAggregateSignatureWithHAE

func VerifyAggregateSignatureWithHAE(curve CurveSystem, aggsig Point, pubkeys []Point, msgs [][]byte) bool

VerifyAggregateSignatureWithHAE verifies signatures of different messages aggregated with HAE.

func VerifyBatchMultiSignatureWithHAE added in v0.5.2

func VerifyBatchMultiSignatureWithHAE(curve CurveSystem, aggsigs []Point, aggpubkeys []Point, msgs [][]byte, allowDups bool) bool

VerifyBatchMultiSignatureWithHAE verifies multiple MultiSignatures are valid, in time faster than verifying each multisignature individually.

func VerifyMultiSignatureWithHAE

func VerifyMultiSignatureWithHAE(curve CurveSystem, aggsig Point, pubkeys []Point, msg []byte) bool

VerifyMultiSignatureWithHAE verifies signatures of the same message aggregated with HAE.

func VerifySingleSignature

func VerifySingleSignature(curve CurveSystem, sig Point, pubKey Point, msg []byte) bool

VerifySingleSignature checks that a single standard BLS signature is valid

func VerifySingleSignatureCustHash

func VerifySingleSignatureCustHash(curve CurveSystem, sig Point, pubkey Point,
	msg []byte, hash func([]byte) Point) bool

VerifySingleSignatureCustHash checks that a single standard BLS signature is valid, using the supplied hash function to hash onto the curve where signatures lie.

Types

type AggSig

type AggSig struct {
	// contains filtered or unexported fields
}

AggSig holds paired sequences of keys and messages, and one signature

func (*AggSig) Verify

func (a *AggSig) Verify(curve CurveSystem) bool

Verify verifies an aggregate signature type.

type MultiSig

type MultiSig struct {
	// contains filtered or unexported fields
}

MultiSig holds set of keys and one message plus signature

func (MultiSig) Verify

func (m MultiSig) Verify(curve CurveSystem) bool

Verify checks that a single message has been signed by a set of keys vulnerable against rogue public-key attack, if keys have not been authenticated

Jump to

Keyboard shortcuts

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