github.com/platonnetwork/platon-go@v0.7.6/crypto/bls/schnorrNIZK.go (about)

     1  package bls
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"strings"
    10  
    11  	"github.com/PlatONnetwork/PlatON-Go/crypto"
    12  	"github.com/PlatONnetwork/PlatON-Go/rlp"
    13  )
    14  
    15  // Match only 128 hex char length proof
    16  type SchnorrProofHex [64]byte
    17  
    18  func (pfe SchnorrProofHex) String() string {
    19  	return hex.EncodeToString(pfe[:])
    20  }
    21  
    22  // MarshalText implements the encoding.TextMarshaler interface.
    23  func (pfe SchnorrProofHex) MarshalText() ([]byte, error) {
    24  	return []byte(hex.EncodeToString(pfe[:])), nil
    25  }
    26  
    27  // UnmarshalText implements the encoding.TextUnmarshaler interface.
    28  func (pfe *SchnorrProofHex) UnmarshalText(text []byte) error {
    29  
    30  	var p SchnorrProofHex
    31  	b, err := hex.DecodeString(strings.TrimPrefix(string(text), "0x"))
    32  	if err != nil {
    33  		return err
    34  	} else if len(b) != len(p) {
    35  		return fmt.Errorf("wrong length, want %d hex chars", len(p)*2)
    36  	}
    37  	copy(p[:], b)
    38  
    39  	*pfe = p
    40  	return nil
    41  }
    42  
    43  type SchnorrProof struct {
    44  	C, R SecretKey
    45  }
    46  
    47  // Serialize --
    48  func (pf *SchnorrProof) Serialize() []byte {
    49  	return append(pf.C.Serialize(), (pf.R.Serialize())...)
    50  
    51  }
    52  
    53  // Deserialize --
    54  func (pf *SchnorrProof) Deserialize(buf []byte) error {
    55  	if len(buf)%2 != 0 {
    56  		return errors.New("the length of C and R not equal in proof")
    57  	}
    58  
    59  	pivot := len(buf) / 2
    60  
    61  	pf.C.Deserialize(buf[:pivot])
    62  	pf.R.Deserialize(buf[pivot:])
    63  	return nil
    64  }
    65  
    66  func (pf *SchnorrProof) MarshalText() ([]byte, error) {
    67  	return []byte(fmt.Sprintf("%x", pf.Serialize())), nil
    68  }
    69  
    70  func (pf *SchnorrProof) UnmarshalText(text []byte) error {
    71  	key, err := hex.DecodeString(string(text))
    72  	if err != nil {
    73  		return err
    74  	}
    75  	return pf.Deserialize(key)
    76  }
    77  
    78  func (pf *SchnorrProof) EncodeRLP(w io.Writer) error {
    79  	return rlp.Encode(w, pf.Serialize())
    80  }
    81  
    82  func (pf *SchnorrProof) DecodeRLP(s *rlp.Stream) error {
    83  	buf, err := s.Bytes()
    84  	if err != nil {
    85  		return err
    86  	}
    87  	return pf.Deserialize(buf)
    88  }
    89  
    90  func (sec *SecretKey) MakeSchnorrNIZKP() (*SchnorrProof, error) {
    91  
    92  	P := sec.GetPublicKey()
    93  	var sk SecretKey
    94  	sk.SetByCSPRNG()
    95  	V := sk.GetPublicKey()
    96  	G := GetGeneratorOfG2()
    97  	input1 := G.Serialize()
    98  	input2 := P.Serialize()
    99  	input3 := V.Serialize()
   100  	var buffer bytes.Buffer
   101  	buffer.Write(input1)
   102  	buffer.Write(input2)
   103  	buffer.Write(input3)
   104  	output := buffer.Bytes()
   105  	h := crypto.Keccak256(output)
   106  	var c SecretKey
   107  	err := c.SetLittleEndian(h)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  	temp := *sec
   112  	temp.Mul(&c)
   113  	r := sk
   114  	r.Sub(&temp)
   115  	sig := new(SchnorrProof)
   116  	sig.C = c
   117  	sig.R = r
   118  	return sig, nil
   119  }
   120  
   121  func (sig *SchnorrProof) VerifySchnorrNIZK(pk PublicKey) error {
   122  
   123  	if !G2IsValid(&pk) {
   124  		return errors.New("P isnot valid")
   125  	}
   126  	c := sig.C
   127  	r := sig.R
   128  	G := GetGeneratorOfG2()
   129  	//V1 = G * r + A * c     c = H(G || pk || V’)
   130  	var Pr PublicKey
   131  	Pr = *G
   132  	Pr.Mul(&r)
   133  	Pc := pk
   134  	Pc.Mul(&c)
   135  	V1 := Pr
   136  	V1.Add(&Pc)
   137  	input1 := G.Serialize()
   138  	input2 := pk.Serialize()
   139  	input3 := V1.Serialize()
   140  	var buffer bytes.Buffer
   141  	buffer.Write(input1)
   142  	buffer.Write(input2)
   143  	buffer.Write(input3)
   144  	output := buffer.Bytes()
   145  	h := crypto.Keccak256(output)
   146  	var c1 SecretKey
   147  	err := c1.SetLittleEndian(h)
   148  	if err != nil {
   149  		return err
   150  	}
   151  	if !c.IsEqual(&c1) {
   152  		return errors.New("not same c = H(G || pk || V’)")
   153  	}
   154  	return nil
   155  
   156  }