github.com/consensys/gnark-crypto@v0.14.0/internal/generator/edwards/eddsa/template/marshal.go.tmpl (about)

     1  import (
     2  	"crypto/subtle"
     3  	"errors"
     4  	"io"
     5  	"math/big"
     6  	"github.com/consensys/gnark-crypto/ecc/{{.Name}}/twistededwards"
     7  	"github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr"
     8  )
     9  
    10  // cf point.go (ugly copy)
    11  const mUnmask = 0x7f
    12  
    13  var errWrongSize = errors.New("wrong size buffer")
    14  var errSBiggerThanRMod = errors.New("s >= r_mod")
    15  var errRBiggerThanPMod = errors.New("r >= p_mod")
    16  var errZero = errors.New("zero value")
    17  
    18  // Bytes returns the binary representation of the public key
    19  // follows https://tools.ietf.org/html/rfc8032#section-3.1
    20  // and returns a compressed representation of the point (x,y)
    21  //
    22  // x, y are the coordinates of the point
    23  // on the twisted Edwards as big endian integers.
    24  // compressed representation store x with a parity bit to recompute y
    25  func (pk *PublicKey) Bytes() []byte {
    26  	var res [sizePublicKey]byte
    27  	pkBin := pk.A.Bytes()
    28  	subtle.ConstantTimeCopy(1, res[:sizeFr], pkBin[:])
    29  	return res[:]
    30  }
    31  
    32  // SetBytes sets p from binary representation in buf.
    33  // buf represents a public key as x||y where x, y are
    34  // interpreted as big endian binary numbers corresponding
    35  // to the coordinates of a point on the twisted Edwards.
    36  // It returns the number of bytes read from the buffer.
    37  func (pk *PublicKey) SetBytes(buf []byte) (int, error) {
    38  	n := 0
    39  	if len(buf) < sizePublicKey {
    40  		return n, io.ErrShortBuffer
    41  	}
    42  	if _, err := pk.A.SetBytes(buf[:sizeFr]); err != nil {
    43  		return 0, err
    44  	}
    45  	n += sizeFr
    46  	if !pk.A.IsOnCurve() {
    47  		return n, errNotOnCurve
    48  	}
    49  	return n, nil
    50  }
    51  
    52  // Bytes returns the binary representation of pk,
    53  // as byte array publicKey||scalar||randSrc
    54  // where publicKey is as publicKey.Bytes(), and
    55  // scalar is in big endian, of size sizeFr.
    56  func (privKey *PrivateKey) Bytes() []byte {
    57  	var res [sizePrivateKey]byte
    58  	pubkBin := privKey.PublicKey.A.Bytes()
    59  	subtle.ConstantTimeCopy(1, res[:sizeFr], pubkBin[:])
    60  	subtle.ConstantTimeCopy(1, res[sizeFr:2*sizeFr], privKey.scalar[:])
    61  	subtle.ConstantTimeCopy(1, res[2*sizeFr:], privKey.randSrc[:])
    62  	return res[:]
    63  }
    64  
    65  // SetBytes sets pk from buf, where buf is interpreted
    66  // as  publicKey||scalar||randSrc
    67  // where publicKey is as publicKey.Bytes(), and
    68  // scalar is in big endian, of size sizeFr.
    69  // It returns the number byte read.
    70  func (privKey *PrivateKey) SetBytes(buf []byte) (int, error) {
    71  	n := 0
    72  	if len(buf) < sizePrivateKey {
    73  		return n, io.ErrShortBuffer
    74  	}
    75  	if _, err := privKey.PublicKey.A.SetBytes(buf[:sizeFr]); err != nil {
    76  		return 0, err
    77  	}
    78  	n += sizeFr
    79  	if !privKey.PublicKey.A.IsOnCurve() {
    80  		return n, errNotOnCurve
    81  	}
    82  	subtle.ConstantTimeCopy(1, privKey.scalar[:], buf[sizeFr:2*sizeFr])
    83  	n += sizeFr
    84  	subtle.ConstantTimeCopy(1, privKey.randSrc[:], buf[2*sizeFr:])
    85  	n += sizeFr
    86  	return n, nil
    87  }
    88  
    89  // Bytes returns the binary representation of sig
    90  // as a byte array of size 3*sizeFr x||y||s where
    91  // * x, y are the coordinates of a point on the twisted
    92  //	Edwards represented in big endian
    93  // * s=r+h(r,a,m) mod l, the Hasse bound guarantees that
    94  //	s is smaller than sizeFr (in particular it is supposed
    95  // 	s is NOT blinded)
    96  func (sig *Signature) Bytes() []byte {
    97  	var res [sizeSignature]byte
    98  	sigRBin := sig.R.Bytes()
    99  	subtle.ConstantTimeCopy(1, res[:sizeFr], sigRBin[:])
   100  	subtle.ConstantTimeCopy(1, res[sizeFr:], sig.S[:])
   101  	return res[:]
   102  }
   103  
   104  // SetBytes sets sig from a buffer in binary.
   105  // buf is read interpreted as x||y||s where
   106  // * x,y are the coordinates of a point on the twisted
   107  //	Edwards represented in big endian
   108  // * s=r+h(r,a,m) mod l, the Hasse bound guarantees that
   109  //	s is smaller than sizeFr (in particular it is supposed
   110  // 	s is NOT blinded)
   111  // It returns the number of bytes read from buf.
   112  func (sig *Signature) SetBytes(buf []byte) (int, error) {
   113  	n := 0
   114  	if len(buf) != sizeSignature {
   115  		return n, errWrongSize
   116  	}
   117  
   118  	// R < P_mod (to avoid malleability)
   119  	// P_mod = field of def of the twisted Edwards = Fr snark field
   120  	fpMod := fr.Modulus()
   121  	zero := big.NewInt(0)
   122  	bufBigInt := new(big.Int)
   123  	bufCopy := make([]byte, fr.Bytes)
   124  	for i := 0; i < sizeFr; i++ {
   125  		bufCopy[sizeFr-1-i] = buf[i]
   126  	}
   127  	bufCopy[0] &= mUnmask
   128  	bufBigInt.SetBytes(bufCopy)
   129  	if bufBigInt.Cmp(zero) == 0 {
   130  		return 0, errZero
   131  	}
   132  	if bufBigInt.Cmp(fpMod) != -1 {
   133  		return 0, errRBiggerThanPMod
   134  	}
   135  
   136  	// S < R_mod (to avoid malleability)
   137  	// R_mod is the relevant group size of the twisted Edwards NOT the fr snark field so it's supposedly smaller
   138  	bufBigInt.SetBytes(buf[sizeFr : 2*sizeFr])
   139  	if bufBigInt.Cmp(zero) == 0 {
   140  		return 0, errZero
   141  	}
   142  	cp := twistededwards.GetEdwardsCurve()
   143  	if bufBigInt.Cmp(&cp.Order) != -1 {
   144  		return 0, errSBiggerThanRMod
   145  	}
   146  
   147  	// deserialisation
   148  	if _, err := sig.R.SetBytes(buf[:sizeFr]); err != nil {
   149  		return 0, err
   150  	}
   151  	n += sizeFr
   152  	if !sig.R.IsOnCurve() {
   153  		return n, errNotOnCurve
   154  	}
   155  	subtle.ConstantTimeCopy(1, sig.S[:], buf[sizeFr:2*sizeFr])
   156  	n += sizeFr
   157  	return n, nil
   158  }