// Copyright 2020 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // The go-ethereum library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . package bls12381 import ( "errors" "math/big" ) func fromBytes(in []byte) (*fe, error) { fe := &fe{} if len(in) != 48 { return nil, errors.New("input string should be equal 48 bytes") } fe.setBytes(in) if !fe.isValid() { return nil, errors.New("must be less than modulus") } toMont(fe, fe) return fe, nil } func fromBig(in *big.Int) (*fe, error) { fe := new(fe).setBig(in) if !fe.isValid() { return nil, errors.New("invalid input string") } toMont(fe, fe) return fe, nil } func fromString(in string) (*fe, error) { fe, err := new(fe).setString(in) if err != nil { return nil, err } if !fe.isValid() { return nil, errors.New("invalid input string") } toMont(fe, fe) return fe, nil } func toBytes(e *fe) []byte { e2 := new(fe) fromMont(e2, e) return e2.bytes() } func toBig(e *fe) *big.Int { e2 := new(fe) fromMont(e2, e) return e2.big() } func toString(e *fe) (s string) { e2 := new(fe) fromMont(e2, e) return e2.string() } func toMont(c, a *fe) { mul(c, a, r2) } func fromMont(c, a *fe) { mul(c, a, &fe{1}) } func exp(c, a *fe, e *big.Int) { z := new(fe).set(r1) for i := e.BitLen(); i >= 0; i-- { mul(z, z, z) if e.Bit(i) == 1 { mul(z, z, a) } } c.set(z) } func inverse(inv, e *fe) { if e.isZero() { inv.zero() return } u := new(fe).set(&modulus) v := new(fe).set(e) s := &fe{1} r := &fe{0} var k int var z uint64 var found = false // Phase 1 for i := 0; i < 768; i++ { if v.isZero() { found = true break } if u.isEven() { u.div2(0) s.mul2() } else if v.isEven() { v.div2(0) z += r.mul2() } else if u.cmp(v) == 1 { lsubAssign(u, v) u.div2(0) laddAssign(r, s) s.mul2() } else { lsubAssign(v, u) v.div2(0) laddAssign(s, r) z += r.mul2() } k++ } if !found { inv.zero() return } if k < 381 || k > 381+384 { inv.zero() return } if r.cmp(&modulus) != -1 || z > 0 { lsubAssign(r, &modulus) } u.set(&modulus) lsubAssign(u, r) // Phase 2 for i := k; i < 384*2; i++ { double(u, u) } inv.set(u) } func sqrt(c, a *fe) bool { u, v := new(fe).set(a), new(fe) exp(c, a, pPlus1Over4) square(v, c) return u.equal(v) } func isQuadraticNonResidue(elem *fe) bool { result := new(fe) exp(result, elem, pMinus1Over2) return !result.isOne() }