decred / dcrd

Decred daemon in Go (golang).
https://decred.org
ISC License
737 stars 291 forks source link

substracting points on ed curve #1172

Closed mottla closed 6 years ago

mottla commented 6 years ago

HI! I'm writing a CryptoNote implementation for university using your edwards package. I try to check (a-b)G == aG-bG On the p256 it works, on the twisted edcurve, it does not. Can you tell me why? I'd be so thankful.. It worked before and now I did some code refactoring and suddenly experience this bug.. I reduced it up untill that point so far..

The code looks: func TestSub(t testing.T) { //curve := edwards.Edwards() curve:= elliptic.P256() alpha := RandFieldElement(curve) alpha2 := RandFieldElement(curve) sum := new(big.Int).Sub(alpha,alpha2) sum.Mod(sum,curve.Params().N) r1,:=curve.ScalarBaseMult(sum.Bytes()) fmt.Println(r1) aa1,aa2:=curve.ScalarBaseMult(alpha.Bytes()) aa3,aa4:=curve.ScalarBaseMult(alpha2.Bytes()) a1,:=curve.Add(aa1,aa2,aa3,aa4.Neg(aa4)) fmt.Println(a1) } where func RandFieldElement(c elliptic.Curve) (k big.Int) { params := c.Params() b := make([]byte, params.BitSize/8+8) _, err := io.ReadFull(rand.Reader, b) if err != nil { panic("random failed..") } b[0] &= 248 b[31] &= 127 b[31] |= 64 k = new(big.Int).SetBytes(b) n := new(big.Int).Sub(params.N, one) k.Mod(k, n) k.Add(k, one) return }

davecgh commented 6 years ago

I'm sure you don't need the answer anymore, as I see it's been a while, but I just now noticed this. The values being produced by your code are actually the same, they're just represented as the negative mod P. I modified your code slightly to mod the negation of the Y value of the point by P before the addition and to perform Px = P - Px, and Py = P - Py when the produced points aren't the same so the results match as you're expecting.

package main

import (
    "crypto/elliptic"
    "crypto/rand"
    "fmt"
    "io"
    "math/big"

    "github.com/decred/dcrd/dcrec/edwards"
)

var one = big.NewInt(1)

func RandFieldElement(c elliptic.Curve) (k *big.Int) {
    params := c.Params()
    b := make([]byte, params.BitSize/8+8)
    _, err := io.ReadFull(rand.Reader, b)
    if err != nil {
        panic("random failed..")
    }
    b[0] &= 248
    b[31] &= 127
    b[31] |= 64
    k = new(big.Int).SetBytes(b)
    n := new(big.Int).Sub(params.N, one)
    k.Mod(k, n)
    k.Add(k, one)
    return
}

func main() {
    curve := edwards.Edwards()
    //curve := elliptic.P256()
    a := RandFieldElement(curve)
    b := RandFieldElement(curve)
    sum := new(big.Int).Sub(a, b)
    sum.Mod(sum, curve.Params().N)
    sGx, sGy := curve.ScalarBaseMult(sum.Bytes())
    ax, ay := curve.ScalarBaseMult(a.Bytes())
    bx, by := curve.ScalarBaseMult(b.Bytes())
    negBy := new(big.Int).Neg(by)
    negBy.Mod(negBy, curve.Params().P)
    Px, Py := curve.Add(ax, ay, bx, negBy)
    if sGx.Cmp(Px) != 0 {
        Px.Sub(curve.Params().P, Px)
        Py.Sub(curve.Params().P, Py)
    }
    fmt.Printf(" (a-b)G: %x %x\n", sGx, sGy)
    fmt.Printf("aG - bG: %x %x\n", Px, Py)
}

Sample Output:


 (a-b)G: 2c1998de8b5a9d5f485f2841a99838d9443ea8b297d1e28928043e80f0635c81 4b318b1887bd7ebc809893fc2a33daedd741b9ef954bc8fcd0299a7f90b0973c
aG - bG: 2c1998de8b5a9d5f485f2841a99838d9443ea8b297d1e28928043e80f0635c81 4b318b1887bd7ebc809893fc2a33daedd741b9ef954bc8fcd0299a7f90b0973c

 (a-b)G: 5488eb2f7f9f42ba6c94bd1983dd177277d6e763518212c922d638bc85310277 167dde9fc5c9a048d21687285bb3e2a783e3a03c236137b14a3db042c7106960
aG - bG: 5488eb2f7f9f42ba6c94bd1983dd177277d6e763518212c922d638bc85310277 167dde9fc5c9a048d21687285bb3e2a783e3a03c236137b14a3db042c7106960

 (a-b)G: 110b3ead7b493e655bc07b74c541e20aab6de22435d7eb346815350ec6620473 12b3f52acdf22066ad2db0e115d1b14094164fa6db7813d85a0651f62d1ef702
aG - bG: 110b3ead7b493e655bc07b74c541e20aab6de22435d7eb346815350ec6620473 12b3f52acdf22066ad2db0e115d1b14094164fa6db7813d85a0651f62d1ef702