diff --git a/babyjub/babyjub.go b/babyjub/babyjub.go index 4174c42..55d88a9 100644 --- a/babyjub/babyjub.go +++ b/babyjub/babyjub.go @@ -203,47 +203,49 @@ func PointCoordSign(c *big.Int) bool { return c.Cmp(new(big.Int).Rsh(constants.Q, 1)) == 1 } -// PackPoint packs a point into a 32 byte array -func PackPoint(ay *big.Int, sign bool) [32]byte { - leBuf := utils.BigIntLEBytes(ay) +// PackSignY packs the given sign and the coordinate Y of a point into a 32 +// byte array. This method does not check that the values belong to a valid +// Point in the curve. +func PackSignY(sign bool, y *big.Int) [32]byte { + leBuf := utils.BigIntLEBytes(y) if sign { leBuf[31] = leBuf[31] | 0x80 //nolint:gomnd } return leBuf } +// UnpackSignY returns the sign and coordinate Y from a given compressed point. +// This method does not check that the Point belongs to the BabyJubJub curve, +// thus does not return error in such case. This method is intended to obtain +// the sign and the Y coordinate without checking if the point belongs to the +// curve, if the objective is to uncompress a point, Decompress method should +// be used instead. +func UnpackSignY(leBuf [32]byte) (bool, *big.Int) { + sign := false + y := big.NewInt(0) + if (leBuf[31] & 0x80) != 0x00 { //nolint:gomnd + sign = true + leBuf[31] = leBuf[31] & 0x7F //nolint:gomnd + } + utils.SetBigIntFromLEBytes(y, leBuf[:]) + return sign, y +} + // Compress the point into a 32 byte array that contains the y coordinate in // little endian and the sign of the x coordinate. func (p *Point) Compress() [32]byte { sign := PointCoordSign(p.X) - return PackPoint(p.Y, sign) + return PackSignY(sign, p.Y) } // Decompress a compressed Point into p, and also returns the decompressed // Point. Returns error if the compressed Point is invalid. func (p *Point) Decompress(leBuf [32]byte) (*Point, error) { var sign bool - sign, p.Y = CompressedPointToSignAndY(leBuf) + sign, p.Y = UnpackSignY(leBuf) return PointFromSignAndY(sign, p.Y) } -// CompressedPointToSignAndY returns the sign and coordinate Y from a given -// compressed point. This method does not check that the Point belongs to the -// BabyJubJub curve, thus does not return error in such case. This method is -// intended to obtain the sign and the Y coordinate without checking if the -// point belongs to the curve, if the objective is to uncompress a point -// Decompress method should be used instead. -func CompressedPointToSignAndY(leBuf [32]byte) (bool, *big.Int) { - sign := false - y := big.NewInt(0) - if (leBuf[31] & 0x80) != 0x00 { //nolint:gomnd - sign = true - leBuf[31] = leBuf[31] & 0x7F //nolint:gomnd - } - utils.SetBigIntFromLEBytes(y, leBuf[:]) - return sign, y -} - // PointFromSignAndY returns a Point from a Sign and the Y coordinate func PointFromSignAndY(sign bool, y *big.Int) (*Point, error) { var p Point diff --git a/babyjub/babyjub_test.go b/babyjub/babyjub_test.go index 566a6f9..462fc96 100644 --- a/babyjub/babyjub_test.go +++ b/babyjub/babyjub_test.go @@ -218,6 +218,26 @@ func TestPointFromSignAndy(t *testing.T) { assert.Equal(t, p.Y.String(), p2.Y.String()) } +func TestPackAndUnpackSignY(t *testing.T) { + x := utils.NewIntFromString( + "17777552123799933955779906779655732241715742912184938656739573121738514868268") + y := utils.NewIntFromString( + "2626589144620713026669568689430873010625803728049924121243784502389097019475") + p := &Point{X: x, Y: y} + pComp := p.Compress() + + s, y := UnpackSignY(pComp) + + pComp2 := PackSignY(s, y) + assert.Equal(t, pComp, pComp2) + + emptyPointComp := [32]byte{} + s, y = UnpackSignY(emptyPointComp) + + pComp2 = PackSignY(s, y) + assert.Equal(t, emptyPointComp, pComp2) +} + func TestCompressDecompress1(t *testing.T) { x := utils.NewIntFromString( "17777552123799933955779906779655732241715742912184938656739573121738514868268") diff --git a/babyjub/eddsa_test.go b/babyjub/eddsa_test.go index 495f990..7e8f696 100644 --- a/babyjub/eddsa_test.go +++ b/babyjub/eddsa_test.go @@ -139,7 +139,7 @@ func TestCompressDecompress(t *testing.T) { func TestSignatureCompScannerValuer(t *testing.T) { privK := NewRandPrivKey() - var value driver.Valuer //nolint:gosimple this is done to ensure interface compability + var value driver.Valuer //nolint:gosimple this is done to ensure interface compatibility value = privK.SignPoseidon(big.NewInt(674238462)).Compress() scan := privK.SignPoseidon(big.NewInt(1)).Compress() fromDB, err := value.Value()