// Bytes returns the variable length byte slice of the value. // It returns the byte slice using the same endianness as i. func (i *Int) Bytes() []byte { buff := i.V.Bytes() if i.BO == LittleEndian { buff = util.Reverse(buff, buff) } return buff }
// Decode an Edwards curve point into the given x,y coordinates. // Returns an error if the input does not denote a valid curve point. // Note that this does NOT check if the point is in the prime-order subgroup: // an adversary could create an encoding denoting a point // on the twist of the curve, or in a larger subgroup. // However, the "safecurves" criteria (http://safecurves.cr.yp.to) // ensure that none of these other subgroups are small // other than the tiny ones represented by the cofactor; // hence Diffie-Hellman exchange can be done without subgroup checking // without exposing more than the least-significant bits of the scalar. func (c *curve) decodePoint(bb []byte, x, y *nist.Int) error { // Convert from little-endian //fmt.Printf("decoding:\n%s\n", hex.Dump(bb)) b := make([]byte, len(bb)) util.Reverse(b, bb) // Extract the sign of the x-coordinate xsign := uint(b[0] >> 7) b[0] &^= 0x80 // Extract the y-coordinate y.V.SetBytes(b) y.M = &c.P // Compute the corresponding x-coordinate if !c.solveForX(x, y) { return errors.New("invalid elliptic curve point") } if c.coordSign(x) != xsign { x.Neg(x) } return nil }
// SetBytes set the value value to a number represented // by a byte string. // Endianness depends on the endianess set in i. func (i *Int) SetBytes(a []byte) abstract.Scalar { var buff = a if i.BO == LittleEndian { buff = util.Reverse(nil, a) } i.V.SetBytes(buff).Mod(&i.V, i.M) return i }
// Encode the value of this Int into a little-endian byte-slice // at least min bytes but no more than max bytes long. // Panics if max != 0 and the Int cannot be represented in max bytes. func (i *Int) LittleEndian(min, max int) []byte { act := i.MarshalSize() pad := act if pad < min { pad = min } if max != 0 && pad > max { panic("Int not representable in max bytes") } buf := make([]byte, pad) util.Reverse(buf[:act], i.V.Bytes()) return buf }
// Attempt to decode a Int from a byte-slice buffer. // Returns an error if the buffer is not exactly Len() bytes long // or if the contents of the buffer represents an out-of-range integer. func (i *Int) UnmarshalBinary(buf []byte) error { if len(buf) != i.MarshalSize() { return errors.New("Int.Decode: wrong size buffer") } // Still needed here because of the comparison with the modulo if i.BO == LittleEndian { buf = util.Reverse(nil, buf) } i.V.SetBytes(buf) if i.V.Cmp(i.M) >= 0 { return errors.New("Int.Decode: value out of range") } return nil }
// Encode an Edwards curve point. // We use little-endian encoding for consistency with Ed25519. func (c *curve) encodePoint(x, y *nist.Int) []byte { // Encode the y-coordinate b, _ := y.MarshalBinary() // Encode the sign of the x-coordinate. if y.M.BitLen()&7 == 0 { // No unused bits at the top of y-coordinate encoding, // so we must prepend a whole byte. b = append(make([]byte, 1), b...) } if c.coordSign(x) != 0 { b[0] |= 0x80 } // Convert to little-endian util.Reverse(b, b) //fmt.Printf("encoding %s,%s:\n%s\n", x.String(), y.String(), // hex.Dump(b)) return b }
// Pick a [pseudo-]random curve point with optional embedded data, // filling in the point's x,y coordinates // and returning any remaining data not embedded. func (c *curve) pickPoint(P point, data []byte, rand cipher.Stream) []byte { // How much data to embed? dl := c.pickLen() if dl > len(data) { dl = len(data) } // Retry until we find a valid point var x, y nist.Int var Q abstract.Point for { // Get random bits the size of a compressed Point encoding, // in which the topmost bit is reserved for the x-coord sign. l := c.PointLen() b := make([]byte, l) rand.XORKeyStream(b, b) // Interpret as little-endian if data != nil { b[0] = byte(dl) // Encode length in low 8 bits copy(b[1:1+dl], data) // Copy in data to embed } util.Reverse(b, b) // Convert to big-endian form xsign := b[0] >> 7 // save x-coordinate sign bit b[0] &^= 0xff << uint(c.P.BitLen()&7) // clear high bits y.M = &c.P // set y-coordinate y.SetBytes(b) if !c.solveForX(&x, &y) { // Corresponding x-coordinate? continue // none, retry } // Pick a random sign for the x-coordinate if c.coordSign(&x) != uint(xsign) { x.Neg(&x) } // Initialize the point P.initXY(&x.V, &y.V, c.self) if c.full { // If we're using the full group, // we just need any point on the curve, so we're done. return data[dl:] } // We're using the prime-order subgroup, // so we need to make sure the point is in that subgroup. // If we're not trying to embed data, // we can convert our point into one in the subgroup // simply by multiplying it by the cofactor. if data == nil { P.Mul(P, &c.cofact) // multiply by cofactor if P.Equal(c.null) { continue // unlucky; try again } return data[dl:] } // Since we need the point's y-coordinate to make sense, // we must simply check if the point is in the subgroup // and retry point generation until it is. if Q == nil { Q = c.self.Point() } Q.Mul(P, &c.order) if Q.Equal(c.null) { return data[dl:] } // Keep trying... } }
// Set value to a number represented in a little-endian byte string. func (i *Int) SetLittleEndian(a []byte) *Int { be := make([]byte, len(a)) util.Reverse(be, a) i.V.SetBytes(be).Mod(&i.V, i.M) return i }