168 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			168 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								// 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 <http://www.gnu.org/licenses/>.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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 += 1
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									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()
							 | 
						||
| 
								 | 
							
								}
							 |