mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-11-14 12:15:18 +00:00
584 lines
14 KiB
Go
584 lines
14 KiB
Go
package application
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"encoding/json"
|
|
|
|
"github.com/pkg/errors"
|
|
"golang.org/x/crypto/sha3"
|
|
"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/core/curves"
|
|
bls48581 "source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/core/curves/native/bls48581"
|
|
"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/ot/base/simplest"
|
|
"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/ot/extension/kos"
|
|
"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/tecdsa/dkls/v1/sign"
|
|
"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/zkp/schnorr"
|
|
)
|
|
|
|
type MultiplyReceiverRound int
|
|
type MultiplySenderRound int
|
|
|
|
const (
|
|
MULTIPLY_RECEIVER_ROUND_UNINITIALIZED = MultiplyReceiverRound(iota)
|
|
MULTIPLY_RECEIVER_ROUND_1_COMPUTE_AND_ZKP_TO_PUBKEY
|
|
MULTIPLY_RECEIVER_ROUND_2_PAD_TRANSFER
|
|
MULTIPLY_RECEIVER_ROUND_3_VERIFY
|
|
MULTIPLY_RECEIVER_ROUND_4_MULTIPLY_INIT
|
|
MULTIPLY_RECEIVER_ROUND_5_MULTIPLY
|
|
MULTIPLY_RECEIVER_ROUND_6_DONE
|
|
)
|
|
|
|
const (
|
|
MULTIPLY_SENDER_ROUND_UNINITIALIZED = MultiplySenderRound(iota)
|
|
MULTIPLY_SENDER_ROUND_1_INITIALIZED
|
|
MULTIPLY_SENDER_ROUND_2_VERIFY_SCHNORR_AND_PAD_TRANSFER
|
|
MULTIPLY_SENDER_ROUND_3_RESPOND_TO_CHALLENGE
|
|
MULTIPLY_SENDER_ROUND_4_VERIFY
|
|
MULTIPLY_SENDER_ROUND_5_MULTIPLY
|
|
MULTIPLY_SENDER_ROUND_6_DONE
|
|
)
|
|
|
|
type Iterator interface {
|
|
Init() error
|
|
Next(message []byte) ([]byte, error)
|
|
IsDone() bool
|
|
GetPoints() []curves.Point
|
|
GetScalars() []curves.Scalar
|
|
}
|
|
|
|
type MultiplySender struct {
|
|
seed [32]byte
|
|
alphas []curves.Scalar
|
|
curve *curves.Curve
|
|
simplestReceiver *simplest.Receiver
|
|
sender []*sign.MultiplySender
|
|
step MultiplySenderRound
|
|
}
|
|
|
|
type MultiplyReceiver struct {
|
|
seed [32]byte
|
|
betas []curves.Scalar
|
|
curve *curves.Curve
|
|
simplestSender *simplest.Sender
|
|
receiver []*sign.MultiplyReceiver
|
|
step MultiplyReceiverRound
|
|
}
|
|
|
|
var _ Iterator = (*MultiplySender)(nil)
|
|
var _ Iterator = (*MultiplyReceiver)(nil)
|
|
|
|
type SchnorrProof struct {
|
|
C []byte
|
|
S []byte
|
|
Statement []byte
|
|
}
|
|
|
|
type KOSRound2Output struct {
|
|
Tau [][][]byte
|
|
}
|
|
|
|
type MultiplyRound2Output struct {
|
|
COTRound2Output *KOSRound2Output
|
|
R [][]byte
|
|
U []byte
|
|
}
|
|
|
|
func NewMultiplySender(
|
|
alphas []curves.Scalar,
|
|
curve *curves.Curve,
|
|
seed [32]byte,
|
|
) *MultiplySender {
|
|
return &MultiplySender{
|
|
seed: seed,
|
|
alphas: alphas,
|
|
curve: curve,
|
|
simplestReceiver: nil,
|
|
sender: []*sign.MultiplySender{},
|
|
step: MULTIPLY_SENDER_ROUND_UNINITIALIZED,
|
|
}
|
|
}
|
|
|
|
func NewMultiplyReceiver(
|
|
betas []curves.Scalar,
|
|
curve *curves.Curve,
|
|
seed [32]byte,
|
|
) *MultiplyReceiver {
|
|
return &MultiplyReceiver{
|
|
seed: seed,
|
|
betas: betas,
|
|
curve: curve,
|
|
simplestSender: nil,
|
|
receiver: []*sign.MultiplyReceiver{},
|
|
step: MULTIPLY_RECEIVER_ROUND_UNINITIALIZED,
|
|
}
|
|
}
|
|
|
|
func (s *MultiplySender) Init() error {
|
|
seed := sha3.Sum256(append(append([]byte{}, s.seed[:]...), []byte("OT")...))
|
|
var err error
|
|
s.simplestReceiver, err = simplest.NewReceiver(s.curve, 584, seed)
|
|
s.step = MULTIPLY_SENDER_ROUND_1_INITIALIZED
|
|
return err
|
|
}
|
|
|
|
func (r *MultiplyReceiver) Init() error {
|
|
seed := sha3.Sum256(append(append([]byte{}, r.seed[:]...), []byte("OT")...))
|
|
var err error
|
|
r.simplestSender, err = simplest.NewSender(r.curve, 584, seed)
|
|
r.step = MULTIPLY_RECEIVER_ROUND_1_COMPUTE_AND_ZKP_TO_PUBKEY
|
|
return err
|
|
}
|
|
|
|
func (s *MultiplySender) Next(message []byte) ([]byte, error) {
|
|
switch s.step {
|
|
case MULTIPLY_SENDER_ROUND_1_INITIALIZED:
|
|
s.step = MULTIPLY_SENDER_ROUND_2_VERIFY_SCHNORR_AND_PAD_TRANSFER
|
|
return nil, nil
|
|
case MULTIPLY_SENDER_ROUND_2_VERIFY_SCHNORR_AND_PAD_TRANSFER:
|
|
proof := &SchnorrProof{}
|
|
err := json.Unmarshal([]byte(message), proof)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
schnorrC, err := s.curve.Scalar.SetBytes(proof.C)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
schnorrS, err := s.curve.Scalar.SetBytes(proof.S)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
schnorrStatement, err := s.curve.Point.FromAffineCompressed(proof.Statement)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
schnorrProof := &schnorr.Proof{
|
|
C: schnorrC,
|
|
S: schnorrS,
|
|
Statement: schnorrStatement,
|
|
}
|
|
|
|
receiversMaskedChoice, err :=
|
|
s.simplestReceiver.Round2VerifySchnorrAndPadTransfer(schnorrProof)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
marshaledReceiversMaskedChoice, err := json.Marshal(receiversMaskedChoice)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
s.step = MULTIPLY_SENDER_ROUND_3_RESPOND_TO_CHALLENGE
|
|
return marshaledReceiversMaskedChoice, nil
|
|
case MULTIPLY_SENDER_ROUND_3_RESPOND_TO_CHALLENGE:
|
|
challenge := [][32]byte{}
|
|
err := json.Unmarshal([]byte(message), &challenge)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
challengeResponse, err := s.simplestReceiver.Round4RespondToChallenge(
|
|
challenge,
|
|
)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
marshaledChallengeResponse, err := json.Marshal(challengeResponse)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
s.step = MULTIPLY_SENDER_ROUND_4_VERIFY
|
|
return marshaledChallengeResponse, errors.Wrap(err, "next")
|
|
case MULTIPLY_SENDER_ROUND_4_VERIFY:
|
|
challengeOpenings := [][2][32]byte{}
|
|
err := json.Unmarshal([]byte(message), &challengeOpenings)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
err = s.simplestReceiver.Round6Verify(challengeOpenings)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
baseOtReceiverOutput := s.simplestReceiver.Output
|
|
|
|
for i := 0; i < len(s.alphas); i++ {
|
|
seed := sha3.Sum256(
|
|
append(
|
|
append(
|
|
append([]byte{}, s.seed[:]...),
|
|
[]byte("MUL")...,
|
|
),
|
|
binary.BigEndian.AppendUint64([]byte{}, uint64(i))...,
|
|
),
|
|
)
|
|
sender, err := sign.NewMultiplySender(
|
|
584,
|
|
160,
|
|
baseOtReceiverOutput,
|
|
s.curve,
|
|
seed,
|
|
)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
s.sender = append(s.sender, sender)
|
|
}
|
|
|
|
s.step = MULTIPLY_SENDER_ROUND_5_MULTIPLY
|
|
return nil, nil
|
|
case MULTIPLY_SENDER_ROUND_5_MULTIPLY:
|
|
round1Outputs := []*kos.Round1Output{}
|
|
err := json.Unmarshal([]byte(message), &round1Outputs)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
if len(round1Outputs) != len(s.alphas) {
|
|
return nil, errors.Wrap(errors.New("incorrect number of outputs"), "next")
|
|
}
|
|
|
|
outputs := []*MultiplyRound2Output{}
|
|
|
|
for i := 0; i < len(s.alphas); i++ {
|
|
round2Output, err := s.sender[i].Round2Multiply(
|
|
s.alphas[i],
|
|
round1Outputs[i],
|
|
)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
tau := [][][]byte{}
|
|
for _, t := range round2Output.COTRound2Output.Tau {
|
|
tBytes := [][]byte{}
|
|
for _, ts := range t {
|
|
tBytes = append(tBytes, ts.Bytes())
|
|
}
|
|
tau = append(tau, tBytes)
|
|
}
|
|
|
|
r := [][]byte{}
|
|
for _, rs := range round2Output.R {
|
|
r = append(r, rs.Bytes())
|
|
}
|
|
|
|
outputs = append(outputs, &MultiplyRound2Output{
|
|
COTRound2Output: &KOSRound2Output{
|
|
Tau: tau,
|
|
},
|
|
R: r,
|
|
U: round2Output.U.Bytes(),
|
|
})
|
|
}
|
|
|
|
marshaledOutputs, err := json.Marshal(outputs)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
s.step = MULTIPLY_SENDER_ROUND_6_DONE
|
|
return marshaledOutputs, nil
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
func (r *MultiplyReceiver) Next(message []byte) ([]byte, error) {
|
|
switch r.step {
|
|
case MULTIPLY_RECEIVER_ROUND_1_COMPUTE_AND_ZKP_TO_PUBKEY:
|
|
proof, err := r.simplestSender.Round1ComputeAndZkpToPublicKey()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
schnorrProof := &SchnorrProof{
|
|
C: proof.C.Bytes(),
|
|
S: proof.S.Bytes(),
|
|
Statement: proof.Statement.ToAffineCompressed(),
|
|
}
|
|
|
|
marshaledProof, err := json.Marshal(schnorrProof)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
r.step = MULTIPLY_RECEIVER_ROUND_2_PAD_TRANSFER
|
|
return marshaledProof, nil
|
|
case MULTIPLY_RECEIVER_ROUND_2_PAD_TRANSFER:
|
|
receiversMaskedChoice := [][]byte{}
|
|
err := json.Unmarshal([]byte(message), &receiversMaskedChoice)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
challenge, err := r.simplestSender.Round3PadTransfer(receiversMaskedChoice)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
marshaledChallenge, err := json.Marshal(challenge)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
r.step = MULTIPLY_RECEIVER_ROUND_3_VERIFY
|
|
return marshaledChallenge, nil
|
|
case MULTIPLY_RECEIVER_ROUND_3_VERIFY:
|
|
challengeResponse := [][32]byte{}
|
|
err := json.Unmarshal([]byte(message), &challengeResponse)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
challengeOpenings, err := r.simplestSender.Round5Verify(challengeResponse)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
marshaledChallengeOpenings, err := json.Marshal(challengeOpenings)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
r.step = MULTIPLY_RECEIVER_ROUND_4_MULTIPLY_INIT
|
|
|
|
return marshaledChallengeOpenings, nil
|
|
case MULTIPLY_RECEIVER_ROUND_4_MULTIPLY_INIT:
|
|
baseOtSenderOutput := r.simplestSender.Output
|
|
outputs := []*kos.Round1Output{}
|
|
|
|
for i := 0; i < len(r.betas); i++ {
|
|
seed := sha3.Sum256(
|
|
append(
|
|
append(
|
|
append([]byte{}, r.seed[:]...),
|
|
[]byte("MUL")...,
|
|
),
|
|
binary.BigEndian.AppendUint64([]byte{}, uint64(i))...,
|
|
),
|
|
)
|
|
receiver, err := sign.NewMultiplyReceiver(
|
|
584,
|
|
160,
|
|
baseOtSenderOutput,
|
|
r.curve,
|
|
seed,
|
|
)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
r.receiver = append(r.receiver, receiver)
|
|
round1Output, err := r.receiver[i].Round1Initialize(r.betas[i])
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
outputs = append(outputs, round1Output)
|
|
}
|
|
|
|
marshaledOutputs, err := json.Marshal(outputs)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
r.step = MULTIPLY_RECEIVER_ROUND_5_MULTIPLY
|
|
return marshaledOutputs, nil
|
|
case MULTIPLY_RECEIVER_ROUND_5_MULTIPLY:
|
|
round2Output := []*MultiplyRound2Output{}
|
|
err := json.Unmarshal([]byte(message), &round2Output)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
if len(round2Output) != len(r.betas) {
|
|
return nil, errors.Wrap(errors.New("incorrect number of outputs"), "next")
|
|
}
|
|
|
|
for i := 0; i < len(r.betas); i++ {
|
|
rawRound2Output := &sign.MultiplyRound2Output{
|
|
COTRound2Output: &kos.Round2Output{
|
|
Tau: [][]curves.Scalar{},
|
|
},
|
|
R: []curves.Scalar{},
|
|
U: nil,
|
|
}
|
|
|
|
for _, t := range round2Output[i].COTRound2Output.Tau {
|
|
tScalars := []curves.Scalar{}
|
|
for _, ts := range t {
|
|
sc, err := r.curve.Scalar.SetBytes(ts)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
tScalars = append(tScalars, sc)
|
|
}
|
|
rawRound2Output.COTRound2Output.Tau = append(
|
|
rawRound2Output.COTRound2Output.Tau,
|
|
tScalars,
|
|
)
|
|
}
|
|
|
|
for _, rs := range round2Output[i].R {
|
|
sc, err := r.curve.Scalar.SetBytes(rs)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
rawRound2Output.R = append(rawRound2Output.R, sc)
|
|
}
|
|
|
|
rawRound2Output.U, err = r.curve.Scalar.SetBytes(round2Output[i].U)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
|
|
err := r.receiver[i].Round3Multiply(rawRound2Output)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "next")
|
|
}
|
|
}
|
|
|
|
r.step = MULTIPLY_RECEIVER_ROUND_6_DONE
|
|
return nil, nil
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (s *MultiplySender) IsDone() bool {
|
|
return s.step == MULTIPLY_SENDER_ROUND_6_DONE
|
|
}
|
|
|
|
func (r *MultiplyReceiver) IsDone() bool {
|
|
return r.step == MULTIPLY_RECEIVER_ROUND_6_DONE
|
|
}
|
|
|
|
func (s *MultiplySender) GetPoints() []curves.Point {
|
|
points := []curves.Point{}
|
|
|
|
for i := 0; i < len(s.alphas); i++ {
|
|
points = append(
|
|
points,
|
|
s.curve.NewGeneratorPoint().Mul(
|
|
s.sender[i].OutputAdditiveShare,
|
|
),
|
|
)
|
|
}
|
|
|
|
return points
|
|
}
|
|
|
|
func (r *MultiplyReceiver) GetPoints() []curves.Point {
|
|
points := []curves.Point{}
|
|
|
|
for i := 0; i < len(r.betas); i++ {
|
|
points = append(
|
|
points,
|
|
r.curve.NewGeneratorPoint().Mul(
|
|
r.receiver[i].OutputAdditiveShare,
|
|
),
|
|
)
|
|
}
|
|
|
|
return points
|
|
}
|
|
|
|
func (s *MultiplySender) GetScalars() []curves.Scalar {
|
|
scalars := []curves.Scalar{}
|
|
|
|
for i := 0; i < len(s.alphas); i++ {
|
|
scalars = append(
|
|
scalars,
|
|
s.sender[i].OutputAdditiveShare,
|
|
)
|
|
}
|
|
|
|
return scalars
|
|
}
|
|
|
|
func (r *MultiplyReceiver) GetScalars() []curves.Scalar {
|
|
scalars := []curves.Scalar{}
|
|
|
|
for i := 0; i < len(r.betas); i++ {
|
|
scalars = append(
|
|
scalars,
|
|
r.receiver[i].OutputAdditiveShare,
|
|
)
|
|
}
|
|
|
|
return scalars
|
|
}
|
|
|
|
func (s *MultiplySender) GetSignatureOfProverKey(
|
|
proverKey []byte,
|
|
) ([]byte, error) {
|
|
signature := make([]byte, int(bls48581.MODBYTES)+1)
|
|
key := s.sender[0].OutputAdditiveShare.Bytes()
|
|
|
|
if bls48581.Core_Sign(signature, proverKey, key) != bls48581.BLS_OK {
|
|
return nil, errors.Wrap(
|
|
errors.New("could not sign"),
|
|
"get signature of prover key",
|
|
)
|
|
}
|
|
|
|
return signature[:], nil
|
|
}
|
|
|
|
func (r *MultiplyReceiver) GetSignatureOfProverKey(
|
|
proverKey []byte,
|
|
) ([]byte, error) {
|
|
signature := make([]byte, int(bls48581.MODBYTES)+1)
|
|
key := r.receiver[0].OutputAdditiveShare.Bytes()
|
|
|
|
if bls48581.Core_Sign(signature, proverKey, key) != bls48581.BLS_OK {
|
|
return nil, errors.Wrap(
|
|
errors.New("could not sign"),
|
|
"get signature of prover key",
|
|
)
|
|
}
|
|
|
|
return signature[:], nil
|
|
}
|
|
|
|
func SignProverKeyForCommit(
|
|
proverKey []byte,
|
|
commitKey curves.Scalar,
|
|
) ([]byte, error) {
|
|
signature := make([]byte, int(bls48581.MODBYTES)+1)
|
|
key := commitKey.Bytes()
|
|
|
|
if bls48581.Core_Sign(signature, proverKey, key) != bls48581.BLS_OK {
|
|
return nil, errors.Wrap(
|
|
errors.New("could not sign"),
|
|
"sign prover key for commit",
|
|
)
|
|
}
|
|
|
|
return signature[:], nil
|
|
}
|
|
|
|
func VerifySignatureOfProverKey(
|
|
proverKey []byte,
|
|
signature []byte,
|
|
publicPointG2 curves.Point,
|
|
) error {
|
|
w := publicPointG2.ToAffineCompressed()
|
|
|
|
if bls48581.Core_Verify(signature, proverKey, w) != bls48581.BLS_OK {
|
|
return errors.Wrap(
|
|
errors.New("could not verify"),
|
|
"verify signature of prover key",
|
|
)
|
|
}
|
|
|
|
return nil
|
|
}
|