aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/bn256/cloudflare/gfp.go
blob: e8e84e7b3b581808d99c15ced865c04cb9fb2dbc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package bn256

import (
    "errors"
    "fmt"
)

type gfP [4]uint64

func newGFp(x int64) (out *gfP) {
    if x >= 0 {
        out = &gfP{uint64(x)}
    } else {
        out = &gfP{uint64(-x)}
        gfpNeg(out, out)
    }

    montEncode(out, out)
    return out
}

func (e *gfP) String() string {
    return fmt.Sprintf("%16.16x%16.16x%16.16x%16.16x", e[3], e[2], e[1], e[0])
}

func (e *gfP) Set(f *gfP) {
    e[0] = f[0]
    e[1] = f[1]
    e[2] = f[2]
    e[3] = f[3]
}

func (e *gfP) Invert(f *gfP) {
    bits := [4]uint64{0x3c208c16d87cfd45, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029}

    sum, power := &gfP{}, &gfP{}
    sum.Set(rN1)
    power.Set(f)

    for word := 0; word < 4; word++ {
        for bit := uint(0); bit < 64; bit++ {
            if (bits[word]>>bit)&1 == 1 {
                gfpMul(sum, sum, power)
            }
            gfpMul(power, power, power)
        }
    }

    gfpMul(sum, sum, r3)
    e.Set(sum)
}

func (e *gfP) Marshal(out []byte) {
    for w := uint(0); w < 4; w++ {
        for b := uint(0); b < 8; b++ {
            out[8*w+b] = byte(e[3-w] >> (56 - 8*b))
        }
    }
}

func (e *gfP) Unmarshal(in []byte) error {
    // Unmarshal the bytes into little endian form
    for w := uint(0); w < 4; w++ {
        for b := uint(0); b < 8; b++ {
            e[3-w] += uint64(in[8*w+b]) << (56 - 8*b)
        }
    }
    // Ensure the point respects the curve modulus
    for i := 3; i >= 0; i-- {
        if e[i] < p2[i] {
            return nil
        }
        if e[i] > p2[i] {
            return errors.New("bn256: coordinate exceeds modulus")
        }
    }
    return errors.New("bn256: coordinate equals modulus")
}

func montEncode(c, a *gfP) { gfpMul(c, a, r2) }
func montDecode(c, a *gfP) { gfpMul(c, a, &gfP{1}) }