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 }