github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-378/twistededwards/eddsa/marshal.go (about)

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