321
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b.go
generated
vendored
Normal file
321
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b.go
generated
vendored
Normal file
@@ -0,0 +1,321 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package blake2b implements the BLAKE2b hash algorithm defined by RFC 7693
|
||||
// and the extendable output function (XOF) BLAKE2Xb.
|
||||
//
|
||||
// For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf
|
||||
// and for BLAKE2Xb see https://blake2.net/blake2x.pdf
|
||||
//
|
||||
// If you aren't sure which function you need, use BLAKE2b (Sum512 or New512).
|
||||
// If you need a secret-key MAC (message authentication code), use the New512
|
||||
// function with a non-nil key.
|
||||
//
|
||||
// BLAKE2X is a construction to compute hash values larger than 64 bytes. It
|
||||
// can produce hash values between 0 and 4 GiB.
|
||||
package blake2b
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"hash"
|
||||
)
|
||||
|
||||
const (
|
||||
// The blocksize of BLAKE2b in bytes.
|
||||
BlockSize = 128
|
||||
// The hash size of BLAKE2b-512 in bytes.
|
||||
Size = 64
|
||||
// The hash size of BLAKE2b-384 in bytes.
|
||||
Size384 = 48
|
||||
// The hash size of BLAKE2b-256 in bytes.
|
||||
Size256 = 32
|
||||
)
|
||||
|
||||
var (
|
||||
useAVX2 bool
|
||||
useAVX bool
|
||||
useSSE4 bool
|
||||
)
|
||||
|
||||
var (
|
||||
errKeySize = errors.New("blake2b: invalid key size")
|
||||
errHashSize = errors.New("blake2b: invalid hash size")
|
||||
)
|
||||
|
||||
var iv = [8]uint64{
|
||||
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
|
||||
0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
|
||||
}
|
||||
|
||||
// Sum512 returns the BLAKE2b-512 checksum of the data.
|
||||
func Sum512(data []byte) [Size]byte {
|
||||
var sum [Size]byte
|
||||
checkSum(&sum, Size, data)
|
||||
return sum
|
||||
}
|
||||
|
||||
// Sum384 returns the BLAKE2b-384 checksum of the data.
|
||||
func Sum384(data []byte) [Size384]byte {
|
||||
var sum [Size]byte
|
||||
var sum384 [Size384]byte
|
||||
checkSum(&sum, Size384, data)
|
||||
copy(sum384[:], sum[:Size384])
|
||||
return sum384
|
||||
}
|
||||
|
||||
// Sum256 returns the BLAKE2b-256 checksum of the data.
|
||||
func Sum256(data []byte) [Size256]byte {
|
||||
var sum [Size]byte
|
||||
var sum256 [Size256]byte
|
||||
checkSum(&sum, Size256, data)
|
||||
copy(sum256[:], sum[:Size256])
|
||||
return sum256
|
||||
}
|
||||
|
||||
// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil
|
||||
// key turns the hash into a MAC. The key must be between zero and 64 bytes long.
|
||||
func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) }
|
||||
|
||||
// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil
|
||||
// key turns the hash into a MAC. The key must be between zero and 64 bytes long.
|
||||
func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) }
|
||||
|
||||
// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil
|
||||
// key turns the hash into a MAC. The key must be between zero and 64 bytes long.
|
||||
func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) }
|
||||
|
||||
// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length.
|
||||
// A non-nil key turns the hash into a MAC. The key must be between zero and 64 bytes long.
|
||||
// The hash size can be a value between 1 and 64 but it is highly recommended to use
|
||||
// values equal or greater than:
|
||||
// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long).
|
||||
// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long).
|
||||
// When the key is nil, the returned hash.Hash implements BinaryMarshaler
|
||||
// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash.
|
||||
func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) }
|
||||
|
||||
// F is a compression function for BLAKE2b. It takes as an argument the state
|
||||
// vector `h`, message block vector `m`, offset counter `t`, final block indicator
|
||||
// flag `f`, and number of rounds `rounds`. The state vector provided as the first
|
||||
// parameter is modified by the function.
|
||||
func F(h *[8]uint64, m [16]uint64, c [2]uint64, final bool, rounds uint32) {
|
||||
var flag uint64
|
||||
if final {
|
||||
flag = 0xFFFFFFFFFFFFFFFF
|
||||
}
|
||||
f(h, &m, c[0], c[1], flag, uint64(rounds))
|
||||
}
|
||||
|
||||
func newDigest(hashSize int, key []byte) (*digest, error) {
|
||||
if hashSize < 1 || hashSize > Size {
|
||||
return nil, errHashSize
|
||||
}
|
||||
if len(key) > Size {
|
||||
return nil, errKeySize
|
||||
}
|
||||
d := &digest{
|
||||
size: hashSize,
|
||||
keyLen: len(key),
|
||||
}
|
||||
copy(d.key[:], key)
|
||||
d.Reset()
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func checkSum(sum *[Size]byte, hashSize int, data []byte) {
|
||||
h := iv
|
||||
h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24)
|
||||
var c [2]uint64
|
||||
|
||||
if length := len(data); length > BlockSize {
|
||||
n := length &^ (BlockSize - 1)
|
||||
if length == n {
|
||||
n -= BlockSize
|
||||
}
|
||||
hashBlocks(&h, &c, 0, data[:n])
|
||||
data = data[n:]
|
||||
}
|
||||
|
||||
var block [BlockSize]byte
|
||||
offset := copy(block[:], data)
|
||||
remaining := uint64(BlockSize - offset)
|
||||
if c[0] < remaining {
|
||||
c[1]--
|
||||
}
|
||||
c[0] -= remaining
|
||||
|
||||
hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:])
|
||||
|
||||
for i, v := range h[:(hashSize+7)/8] {
|
||||
binary.LittleEndian.PutUint64(sum[8*i:], v)
|
||||
}
|
||||
}
|
||||
|
||||
func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
|
||||
var m [16]uint64
|
||||
c0, c1 := c[0], c[1]
|
||||
|
||||
for i := 0; i < len(blocks); {
|
||||
c0 += BlockSize
|
||||
if c0 < BlockSize {
|
||||
c1++
|
||||
}
|
||||
for j := range m {
|
||||
m[j] = binary.LittleEndian.Uint64(blocks[i:])
|
||||
i += 8
|
||||
}
|
||||
f(h, &m, c0, c1, flag, 12)
|
||||
}
|
||||
c[0], c[1] = c0, c1
|
||||
}
|
||||
|
||||
type digest struct {
|
||||
h [8]uint64
|
||||
c [2]uint64
|
||||
size int
|
||||
block [BlockSize]byte
|
||||
offset int
|
||||
|
||||
key [BlockSize]byte
|
||||
keyLen int
|
||||
}
|
||||
|
||||
const (
|
||||
magic = "b2b"
|
||||
marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1
|
||||
)
|
||||
|
||||
func (d *digest) MarshalBinary() ([]byte, error) {
|
||||
if d.keyLen != 0 {
|
||||
return nil, errors.New("crypto/blake2b: cannot marshal MACs")
|
||||
}
|
||||
b := make([]byte, 0, marshaledSize)
|
||||
b = append(b, magic...)
|
||||
for i := 0; i < 8; i++ {
|
||||
b = appendUint64(b, d.h[i])
|
||||
}
|
||||
b = appendUint64(b, d.c[0])
|
||||
b = appendUint64(b, d.c[1])
|
||||
// Maximum value for size is 64
|
||||
b = append(b, byte(d.size))
|
||||
b = append(b, d.block[:]...)
|
||||
b = append(b, byte(d.offset))
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (d *digest) UnmarshalBinary(b []byte) error {
|
||||
if len(b) < len(magic) || string(b[:len(magic)]) != magic {
|
||||
return errors.New("crypto/blake2b: invalid hash state identifier")
|
||||
}
|
||||
if len(b) != marshaledSize {
|
||||
return errors.New("crypto/blake2b: invalid hash state size")
|
||||
}
|
||||
b = b[len(magic):]
|
||||
for i := 0; i < 8; i++ {
|
||||
b, d.h[i] = consumeUint64(b)
|
||||
}
|
||||
b, d.c[0] = consumeUint64(b)
|
||||
b, d.c[1] = consumeUint64(b)
|
||||
d.size = int(b[0])
|
||||
b = b[1:]
|
||||
copy(d.block[:], b[:BlockSize])
|
||||
b = b[BlockSize:]
|
||||
d.offset = int(b[0])
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *digest) BlockSize() int { return BlockSize }
|
||||
|
||||
func (d *digest) Size() int { return d.size }
|
||||
|
||||
func (d *digest) Reset() {
|
||||
d.h = iv
|
||||
d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24)
|
||||
d.offset, d.c[0], d.c[1] = 0, 0, 0
|
||||
if d.keyLen > 0 {
|
||||
d.block = d.key
|
||||
d.offset = BlockSize
|
||||
}
|
||||
}
|
||||
|
||||
func (d *digest) Write(p []byte) (n int, err error) {
|
||||
n = len(p)
|
||||
|
||||
if d.offset > 0 {
|
||||
remaining := BlockSize - d.offset
|
||||
if n <= remaining {
|
||||
d.offset += copy(d.block[d.offset:], p)
|
||||
return
|
||||
}
|
||||
copy(d.block[d.offset:], p[:remaining])
|
||||
hashBlocks(&d.h, &d.c, 0, d.block[:])
|
||||
d.offset = 0
|
||||
p = p[remaining:]
|
||||
}
|
||||
|
||||
if length := len(p); length > BlockSize {
|
||||
nn := length &^ (BlockSize - 1)
|
||||
if length == nn {
|
||||
nn -= BlockSize
|
||||
}
|
||||
hashBlocks(&d.h, &d.c, 0, p[:nn])
|
||||
p = p[nn:]
|
||||
}
|
||||
|
||||
if len(p) > 0 {
|
||||
d.offset += copy(d.block[:], p)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (d *digest) Sum(sum []byte) []byte {
|
||||
var hash [Size]byte
|
||||
d.finalize(&hash)
|
||||
return append(sum, hash[:d.size]...)
|
||||
}
|
||||
|
||||
func (d *digest) finalize(hash *[Size]byte) {
|
||||
var block [BlockSize]byte
|
||||
copy(block[:], d.block[:d.offset])
|
||||
remaining := uint64(BlockSize - d.offset)
|
||||
|
||||
c := d.c
|
||||
if c[0] < remaining {
|
||||
c[1]--
|
||||
}
|
||||
c[0] -= remaining
|
||||
|
||||
h := d.h
|
||||
hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:])
|
||||
|
||||
for i, v := range h {
|
||||
binary.LittleEndian.PutUint64(hash[8*i:], v)
|
||||
}
|
||||
}
|
||||
|
||||
func appendUint64(b []byte, x uint64) []byte {
|
||||
var a [8]byte
|
||||
binary.BigEndian.PutUint64(a[:], x)
|
||||
return append(b, a[:]...)
|
||||
}
|
||||
|
||||
//nolint:unused,deadcode
|
||||
func appendUint32(b []byte, x uint32) []byte {
|
||||
var a [4]byte
|
||||
binary.BigEndian.PutUint32(a[:], x)
|
||||
return append(b, a[:]...)
|
||||
}
|
||||
|
||||
func consumeUint64(b []byte) ([]byte, uint64) {
|
||||
x := binary.BigEndian.Uint64(b)
|
||||
return b[8:], x
|
||||
}
|
||||
|
||||
//nolint:unused,deadcode
|
||||
func consumeUint32(b []byte) ([]byte, uint32) {
|
||||
x := binary.BigEndian.Uint32(b)
|
||||
return b[4:], x
|
||||
}
|
||||
38
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.go
generated
vendored
Normal file
38
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.7 && amd64 && !gccgo && !appengine
|
||||
// +build go1.7,amd64,!gccgo,!appengine
|
||||
|
||||
package blake2b
|
||||
|
||||
import "golang.org/x/sys/cpu"
|
||||
|
||||
func init() {
|
||||
useAVX2 = cpu.X86.HasAVX2
|
||||
useAVX = cpu.X86.HasAVX
|
||||
useSSE4 = cpu.X86.HasSSE41
|
||||
}
|
||||
|
||||
//go:noescape
|
||||
func fAVX2(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64)
|
||||
|
||||
//go:noescape
|
||||
func fAVX(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64)
|
||||
|
||||
//go:noescape
|
||||
func fSSE4(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64)
|
||||
|
||||
func f(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) {
|
||||
switch {
|
||||
case useAVX2:
|
||||
fAVX2(h, m, c0, c1, flag, rounds)
|
||||
case useAVX:
|
||||
fAVX(h, m, c0, c1, flag, rounds)
|
||||
case useSSE4:
|
||||
fSSE4(h, m, c0, c1, flag, rounds)
|
||||
default:
|
||||
fGeneric(h, m, c0, c1, flag, rounds)
|
||||
}
|
||||
}
|
||||
717
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.s
generated
vendored
Normal file
717
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.s
generated
vendored
Normal file
@@ -0,0 +1,717 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.7,amd64,!gccgo,!appengine
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
DATA ·AVX2_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908
|
||||
DATA ·AVX2_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b
|
||||
DATA ·AVX2_iv0<>+0x10(SB)/8, $0x3c6ef372fe94f82b
|
||||
DATA ·AVX2_iv0<>+0x18(SB)/8, $0xa54ff53a5f1d36f1
|
||||
GLOBL ·AVX2_iv0<>(SB), (NOPTR+RODATA), $32
|
||||
|
||||
DATA ·AVX2_iv1<>+0x00(SB)/8, $0x510e527fade682d1
|
||||
DATA ·AVX2_iv1<>+0x08(SB)/8, $0x9b05688c2b3e6c1f
|
||||
DATA ·AVX2_iv1<>+0x10(SB)/8, $0x1f83d9abfb41bd6b
|
||||
DATA ·AVX2_iv1<>+0x18(SB)/8, $0x5be0cd19137e2179
|
||||
GLOBL ·AVX2_iv1<>(SB), (NOPTR+RODATA), $32
|
||||
|
||||
DATA ·AVX2_c40<>+0x00(SB)/8, $0x0201000706050403
|
||||
DATA ·AVX2_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b
|
||||
DATA ·AVX2_c40<>+0x10(SB)/8, $0x0201000706050403
|
||||
DATA ·AVX2_c40<>+0x18(SB)/8, $0x0a09080f0e0d0c0b
|
||||
GLOBL ·AVX2_c40<>(SB), (NOPTR+RODATA), $32
|
||||
|
||||
DATA ·AVX2_c48<>+0x00(SB)/8, $0x0100070605040302
|
||||
DATA ·AVX2_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a
|
||||
DATA ·AVX2_c48<>+0x10(SB)/8, $0x0100070605040302
|
||||
DATA ·AVX2_c48<>+0x18(SB)/8, $0x09080f0e0d0c0b0a
|
||||
GLOBL ·AVX2_c48<>(SB), (NOPTR+RODATA), $32
|
||||
|
||||
DATA ·AVX_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908
|
||||
DATA ·AVX_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b
|
||||
GLOBL ·AVX_iv0<>(SB), (NOPTR+RODATA), $16
|
||||
|
||||
DATA ·AVX_iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b
|
||||
DATA ·AVX_iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1
|
||||
GLOBL ·AVX_iv1<>(SB), (NOPTR+RODATA), $16
|
||||
|
||||
DATA ·AVX_iv2<>+0x00(SB)/8, $0x510e527fade682d1
|
||||
DATA ·AVX_iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f
|
||||
GLOBL ·AVX_iv2<>(SB), (NOPTR+RODATA), $16
|
||||
|
||||
DATA ·AVX_iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b
|
||||
DATA ·AVX_iv3<>+0x08(SB)/8, $0x5be0cd19137e2179
|
||||
GLOBL ·AVX_iv3<>(SB), (NOPTR+RODATA), $16
|
||||
|
||||
DATA ·AVX_c40<>+0x00(SB)/8, $0x0201000706050403
|
||||
DATA ·AVX_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b
|
||||
GLOBL ·AVX_c40<>(SB), (NOPTR+RODATA), $16
|
||||
|
||||
DATA ·AVX_c48<>+0x00(SB)/8, $0x0100070605040302
|
||||
DATA ·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a
|
||||
GLOBL ·AVX_c48<>(SB), (NOPTR+RODATA), $16
|
||||
|
||||
#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39
|
||||
#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93
|
||||
#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e
|
||||
#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93
|
||||
#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39
|
||||
|
||||
#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \
|
||||
VPADDQ m0, Y0, Y0; \
|
||||
VPADDQ Y1, Y0, Y0; \
|
||||
VPXOR Y0, Y3, Y3; \
|
||||
VPSHUFD $-79, Y3, Y3; \
|
||||
VPADDQ Y3, Y2, Y2; \
|
||||
VPXOR Y2, Y1, Y1; \
|
||||
VPSHUFB c40, Y1, Y1; \
|
||||
VPADDQ m1, Y0, Y0; \
|
||||
VPADDQ Y1, Y0, Y0; \
|
||||
VPXOR Y0, Y3, Y3; \
|
||||
VPSHUFB c48, Y3, Y3; \
|
||||
VPADDQ Y3, Y2, Y2; \
|
||||
VPXOR Y2, Y1, Y1; \
|
||||
VPADDQ Y1, Y1, t; \
|
||||
VPSRLQ $63, Y1, Y1; \
|
||||
VPXOR t, Y1, Y1; \
|
||||
VPERMQ_0x39_Y1_Y1; \
|
||||
VPERMQ_0x4E_Y2_Y2; \
|
||||
VPERMQ_0x93_Y3_Y3; \
|
||||
VPADDQ m2, Y0, Y0; \
|
||||
VPADDQ Y1, Y0, Y0; \
|
||||
VPXOR Y0, Y3, Y3; \
|
||||
VPSHUFD $-79, Y3, Y3; \
|
||||
VPADDQ Y3, Y2, Y2; \
|
||||
VPXOR Y2, Y1, Y1; \
|
||||
VPSHUFB c40, Y1, Y1; \
|
||||
VPADDQ m3, Y0, Y0; \
|
||||
VPADDQ Y1, Y0, Y0; \
|
||||
VPXOR Y0, Y3, Y3; \
|
||||
VPSHUFB c48, Y3, Y3; \
|
||||
VPADDQ Y3, Y2, Y2; \
|
||||
VPXOR Y2, Y1, Y1; \
|
||||
VPADDQ Y1, Y1, t; \
|
||||
VPSRLQ $63, Y1, Y1; \
|
||||
VPXOR t, Y1, Y1; \
|
||||
VPERMQ_0x39_Y3_Y3; \
|
||||
VPERMQ_0x4E_Y2_Y2; \
|
||||
VPERMQ_0x93_Y1_Y1
|
||||
|
||||
#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E
|
||||
#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26
|
||||
#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E
|
||||
#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36
|
||||
#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E
|
||||
|
||||
#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n
|
||||
#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n
|
||||
#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n
|
||||
#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n
|
||||
#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n
|
||||
|
||||
#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01
|
||||
#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01
|
||||
#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01
|
||||
#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01
|
||||
#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01
|
||||
|
||||
#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01
|
||||
#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01
|
||||
#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01
|
||||
#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01
|
||||
#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01
|
||||
|
||||
#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8
|
||||
#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01
|
||||
|
||||
// load msg: Y12 = (i0, i1, i2, i3)
|
||||
// i0, i1, i2, i3 must not be 0
|
||||
#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \
|
||||
VMOVQ_SI_X12(i0*8); \
|
||||
VMOVQ_SI_X11(i2*8); \
|
||||
VPINSRQ_1_SI_X12(i1*8); \
|
||||
VPINSRQ_1_SI_X11(i3*8); \
|
||||
VINSERTI128 $1, X11, Y12, Y12
|
||||
|
||||
// load msg: Y13 = (i0, i1, i2, i3)
|
||||
// i0, i1, i2, i3 must not be 0
|
||||
#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \
|
||||
VMOVQ_SI_X13(i0*8); \
|
||||
VMOVQ_SI_X11(i2*8); \
|
||||
VPINSRQ_1_SI_X13(i1*8); \
|
||||
VPINSRQ_1_SI_X11(i3*8); \
|
||||
VINSERTI128 $1, X11, Y13, Y13
|
||||
|
||||
// load msg: Y14 = (i0, i1, i2, i3)
|
||||
// i0, i1, i2, i3 must not be 0
|
||||
#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \
|
||||
VMOVQ_SI_X14(i0*8); \
|
||||
VMOVQ_SI_X11(i2*8); \
|
||||
VPINSRQ_1_SI_X14(i1*8); \
|
||||
VPINSRQ_1_SI_X11(i3*8); \
|
||||
VINSERTI128 $1, X11, Y14, Y14
|
||||
|
||||
// load msg: Y15 = (i0, i1, i2, i3)
|
||||
// i0, i1, i2, i3 must not be 0
|
||||
#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \
|
||||
VMOVQ_SI_X15(i0*8); \
|
||||
VMOVQ_SI_X11(i2*8); \
|
||||
VPINSRQ_1_SI_X15(i1*8); \
|
||||
VPINSRQ_1_SI_X11(i3*8); \
|
||||
VINSERTI128 $1, X11, Y15, Y15
|
||||
|
||||
#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \
|
||||
VMOVQ_SI_X12_0; \
|
||||
VMOVQ_SI_X11(4*8); \
|
||||
VPINSRQ_1_SI_X12(2*8); \
|
||||
VPINSRQ_1_SI_X11(6*8); \
|
||||
VINSERTI128 $1, X11, Y12, Y12; \
|
||||
LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \
|
||||
LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \
|
||||
LOAD_MSG_AVX2_Y15(9, 11, 13, 15)
|
||||
|
||||
#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \
|
||||
LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \
|
||||
LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \
|
||||
VMOVQ_SI_X11(11*8); \
|
||||
VPSHUFD $0x4E, 0*8(SI), X14; \
|
||||
VPINSRQ_1_SI_X11(5*8); \
|
||||
VINSERTI128 $1, X11, Y14, Y14; \
|
||||
LOAD_MSG_AVX2_Y15(12, 2, 7, 3)
|
||||
|
||||
#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \
|
||||
VMOVQ_SI_X11(5*8); \
|
||||
VMOVDQU 11*8(SI), X12; \
|
||||
VPINSRQ_1_SI_X11(15*8); \
|
||||
VINSERTI128 $1, X11, Y12, Y12; \
|
||||
VMOVQ_SI_X13(8*8); \
|
||||
VMOVQ_SI_X11(2*8); \
|
||||
VPINSRQ_1_SI_X13_0; \
|
||||
VPINSRQ_1_SI_X11(13*8); \
|
||||
VINSERTI128 $1, X11, Y13, Y13; \
|
||||
LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \
|
||||
LOAD_MSG_AVX2_Y15(14, 6, 1, 4)
|
||||
|
||||
#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \
|
||||
LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \
|
||||
LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \
|
||||
LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \
|
||||
VMOVQ_SI_X15(6*8); \
|
||||
VMOVQ_SI_X11_0; \
|
||||
VPINSRQ_1_SI_X15(10*8); \
|
||||
VPINSRQ_1_SI_X11(8*8); \
|
||||
VINSERTI128 $1, X11, Y15, Y15
|
||||
|
||||
#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \
|
||||
LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \
|
||||
VMOVQ_SI_X13_0; \
|
||||
VMOVQ_SI_X11(4*8); \
|
||||
VPINSRQ_1_SI_X13(7*8); \
|
||||
VPINSRQ_1_SI_X11(15*8); \
|
||||
VINSERTI128 $1, X11, Y13, Y13; \
|
||||
LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \
|
||||
LOAD_MSG_AVX2_Y15(1, 12, 8, 13)
|
||||
|
||||
#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \
|
||||
VMOVQ_SI_X12(2*8); \
|
||||
VMOVQ_SI_X11_0; \
|
||||
VPINSRQ_1_SI_X12(6*8); \
|
||||
VPINSRQ_1_SI_X11(8*8); \
|
||||
VINSERTI128 $1, X11, Y12, Y12; \
|
||||
LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \
|
||||
LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \
|
||||
LOAD_MSG_AVX2_Y15(13, 5, 14, 9)
|
||||
|
||||
#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \
|
||||
LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \
|
||||
LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \
|
||||
VMOVQ_SI_X14_0; \
|
||||
VPSHUFD $0x4E, 8*8(SI), X11; \
|
||||
VPINSRQ_1_SI_X14(6*8); \
|
||||
VINSERTI128 $1, X11, Y14, Y14; \
|
||||
LOAD_MSG_AVX2_Y15(7, 3, 2, 11)
|
||||
|
||||
#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \
|
||||
LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \
|
||||
LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \
|
||||
LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \
|
||||
VMOVQ_SI_X15_0; \
|
||||
VMOVQ_SI_X11(6*8); \
|
||||
VPINSRQ_1_SI_X15(4*8); \
|
||||
VPINSRQ_1_SI_X11(10*8); \
|
||||
VINSERTI128 $1, X11, Y15, Y15
|
||||
|
||||
#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \
|
||||
VMOVQ_SI_X12(6*8); \
|
||||
VMOVQ_SI_X11(11*8); \
|
||||
VPINSRQ_1_SI_X12(14*8); \
|
||||
VPINSRQ_1_SI_X11_0; \
|
||||
VINSERTI128 $1, X11, Y12, Y12; \
|
||||
LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \
|
||||
VMOVQ_SI_X11(1*8); \
|
||||
VMOVDQU 12*8(SI), X14; \
|
||||
VPINSRQ_1_SI_X11(10*8); \
|
||||
VINSERTI128 $1, X11, Y14, Y14; \
|
||||
VMOVQ_SI_X15(2*8); \
|
||||
VMOVDQU 4*8(SI), X11; \
|
||||
VPINSRQ_1_SI_X15(7*8); \
|
||||
VINSERTI128 $1, X11, Y15, Y15
|
||||
|
||||
#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \
|
||||
LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \
|
||||
VMOVQ_SI_X13(2*8); \
|
||||
VPSHUFD $0x4E, 5*8(SI), X11; \
|
||||
VPINSRQ_1_SI_X13(4*8); \
|
||||
VINSERTI128 $1, X11, Y13, Y13; \
|
||||
LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \
|
||||
VMOVQ_SI_X15(11*8); \
|
||||
VMOVQ_SI_X11(12*8); \
|
||||
VPINSRQ_1_SI_X15(14*8); \
|
||||
VPINSRQ_1_SI_X11_0; \
|
||||
VINSERTI128 $1, X11, Y15, Y15
|
||||
|
||||
// func fAVX2(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64)
|
||||
TEXT ·fAVX2(SB), 4, $64-48 // frame size = 32 + 32 byte alignment
|
||||
MOVQ h+0(FP), AX
|
||||
MOVQ m+8(FP), SI
|
||||
MOVQ c0+16(FP), R8
|
||||
MOVQ c1+24(FP), R9
|
||||
MOVQ flag+32(FP), CX
|
||||
MOVQ rounds+40(FP), BX
|
||||
|
||||
MOVQ SP, DX
|
||||
MOVQ SP, R10
|
||||
ADDQ $31, R10
|
||||
ANDQ $~31, R10
|
||||
MOVQ R10, SP
|
||||
|
||||
MOVQ CX, 16(SP)
|
||||
XORQ CX, CX
|
||||
MOVQ CX, 24(SP)
|
||||
|
||||
VMOVDQU ·AVX2_c40<>(SB), Y4
|
||||
VMOVDQU ·AVX2_c48<>(SB), Y5
|
||||
|
||||
VMOVDQU 0(AX), Y8
|
||||
VMOVDQU 32(AX), Y9
|
||||
VMOVDQU ·AVX2_iv0<>(SB), Y6
|
||||
VMOVDQU ·AVX2_iv1<>(SB), Y7
|
||||
|
||||
MOVQ R8, 0(SP)
|
||||
MOVQ R9, 8(SP)
|
||||
|
||||
VMOVDQA Y8, Y0
|
||||
VMOVDQA Y9, Y1
|
||||
VMOVDQA Y6, Y2
|
||||
VPXOR 0(SP), Y7, Y3
|
||||
|
||||
loop:
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15()
|
||||
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3()
|
||||
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4()
|
||||
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8()
|
||||
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13()
|
||||
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9()
|
||||
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11()
|
||||
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10()
|
||||
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5()
|
||||
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0()
|
||||
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
|
||||
|
||||
JMP loop
|
||||
|
||||
done:
|
||||
VPXOR Y0, Y8, Y8
|
||||
VPXOR Y1, Y9, Y9
|
||||
VPXOR Y2, Y8, Y8
|
||||
VPXOR Y3, Y9, Y9
|
||||
|
||||
VMOVDQU Y8, 0(AX)
|
||||
VMOVDQU Y9, 32(AX)
|
||||
VZEROUPPER
|
||||
|
||||
MOVQ DX, SP
|
||||
RET
|
||||
|
||||
#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA
|
||||
#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB
|
||||
#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF
|
||||
#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD
|
||||
#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE
|
||||
|
||||
#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7
|
||||
#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF
|
||||
#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7
|
||||
#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF
|
||||
#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7
|
||||
#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7
|
||||
#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF
|
||||
#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF
|
||||
|
||||
#define SHUFFLE_AVX() \
|
||||
VMOVDQA X6, X13; \
|
||||
VMOVDQA X2, X14; \
|
||||
VMOVDQA X4, X6; \
|
||||
VPUNPCKLQDQ_X13_X13_X15; \
|
||||
VMOVDQA X5, X4; \
|
||||
VMOVDQA X6, X5; \
|
||||
VPUNPCKHQDQ_X15_X7_X6; \
|
||||
VPUNPCKLQDQ_X7_X7_X15; \
|
||||
VPUNPCKHQDQ_X15_X13_X7; \
|
||||
VPUNPCKLQDQ_X3_X3_X15; \
|
||||
VPUNPCKHQDQ_X15_X2_X2; \
|
||||
VPUNPCKLQDQ_X14_X14_X15; \
|
||||
VPUNPCKHQDQ_X15_X3_X3; \
|
||||
|
||||
#define SHUFFLE_AVX_INV() \
|
||||
VMOVDQA X2, X13; \
|
||||
VMOVDQA X4, X14; \
|
||||
VPUNPCKLQDQ_X2_X2_X15; \
|
||||
VMOVDQA X5, X4; \
|
||||
VPUNPCKHQDQ_X15_X3_X2; \
|
||||
VMOVDQA X14, X5; \
|
||||
VPUNPCKLQDQ_X3_X3_X15; \
|
||||
VMOVDQA X6, X14; \
|
||||
VPUNPCKHQDQ_X15_X13_X3; \
|
||||
VPUNPCKLQDQ_X7_X7_X15; \
|
||||
VPUNPCKHQDQ_X15_X6_X6; \
|
||||
VPUNPCKLQDQ_X14_X14_X15; \
|
||||
VPUNPCKHQDQ_X15_X7_X7; \
|
||||
|
||||
#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \
|
||||
VPADDQ m0, v0, v0; \
|
||||
VPADDQ v2, v0, v0; \
|
||||
VPADDQ m1, v1, v1; \
|
||||
VPADDQ v3, v1, v1; \
|
||||
VPXOR v0, v6, v6; \
|
||||
VPXOR v1, v7, v7; \
|
||||
VPSHUFD $-79, v6, v6; \
|
||||
VPSHUFD $-79, v7, v7; \
|
||||
VPADDQ v6, v4, v4; \
|
||||
VPADDQ v7, v5, v5; \
|
||||
VPXOR v4, v2, v2; \
|
||||
VPXOR v5, v3, v3; \
|
||||
VPSHUFB c40, v2, v2; \
|
||||
VPSHUFB c40, v3, v3; \
|
||||
VPADDQ m2, v0, v0; \
|
||||
VPADDQ v2, v0, v0; \
|
||||
VPADDQ m3, v1, v1; \
|
||||
VPADDQ v3, v1, v1; \
|
||||
VPXOR v0, v6, v6; \
|
||||
VPXOR v1, v7, v7; \
|
||||
VPSHUFB c48, v6, v6; \
|
||||
VPSHUFB c48, v7, v7; \
|
||||
VPADDQ v6, v4, v4; \
|
||||
VPADDQ v7, v5, v5; \
|
||||
VPXOR v4, v2, v2; \
|
||||
VPXOR v5, v3, v3; \
|
||||
VPADDQ v2, v2, t0; \
|
||||
VPSRLQ $63, v2, v2; \
|
||||
VPXOR t0, v2, v2; \
|
||||
VPADDQ v3, v3, t0; \
|
||||
VPSRLQ $63, v3, v3; \
|
||||
VPXOR t0, v3, v3
|
||||
|
||||
// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7)
|
||||
// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0
|
||||
#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \
|
||||
VMOVQ_SI_X12(i0*8); \
|
||||
VMOVQ_SI_X13(i2*8); \
|
||||
VMOVQ_SI_X14(i4*8); \
|
||||
VMOVQ_SI_X15(i6*8); \
|
||||
VPINSRQ_1_SI_X12(i1*8); \
|
||||
VPINSRQ_1_SI_X13(i3*8); \
|
||||
VPINSRQ_1_SI_X14(i5*8); \
|
||||
VPINSRQ_1_SI_X15(i7*8)
|
||||
|
||||
// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7)
|
||||
#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \
|
||||
VMOVQ_SI_X12_0; \
|
||||
VMOVQ_SI_X13(4*8); \
|
||||
VMOVQ_SI_X14(1*8); \
|
||||
VMOVQ_SI_X15(5*8); \
|
||||
VPINSRQ_1_SI_X12(2*8); \
|
||||
VPINSRQ_1_SI_X13(6*8); \
|
||||
VPINSRQ_1_SI_X14(3*8); \
|
||||
VPINSRQ_1_SI_X15(7*8)
|
||||
|
||||
// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3)
|
||||
#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \
|
||||
VPSHUFD $0x4E, 0*8(SI), X12; \
|
||||
VMOVQ_SI_X13(11*8); \
|
||||
VMOVQ_SI_X14(12*8); \
|
||||
VMOVQ_SI_X15(7*8); \
|
||||
VPINSRQ_1_SI_X13(5*8); \
|
||||
VPINSRQ_1_SI_X14(2*8); \
|
||||
VPINSRQ_1_SI_X15(3*8)
|
||||
|
||||
// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13)
|
||||
#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \
|
||||
VMOVDQU 11*8(SI), X12; \
|
||||
VMOVQ_SI_X13(5*8); \
|
||||
VMOVQ_SI_X14(8*8); \
|
||||
VMOVQ_SI_X15(2*8); \
|
||||
VPINSRQ_1_SI_X13(15*8); \
|
||||
VPINSRQ_1_SI_X14_0; \
|
||||
VPINSRQ_1_SI_X15(13*8)
|
||||
|
||||
// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8)
|
||||
#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \
|
||||
VMOVQ_SI_X12(2*8); \
|
||||
VMOVQ_SI_X13(4*8); \
|
||||
VMOVQ_SI_X14(6*8); \
|
||||
VMOVQ_SI_X15_0; \
|
||||
VPINSRQ_1_SI_X12(5*8); \
|
||||
VPINSRQ_1_SI_X13(15*8); \
|
||||
VPINSRQ_1_SI_X14(10*8); \
|
||||
VPINSRQ_1_SI_X15(8*8)
|
||||
|
||||
// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15)
|
||||
#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \
|
||||
VMOVQ_SI_X12(9*8); \
|
||||
VMOVQ_SI_X13(2*8); \
|
||||
VMOVQ_SI_X14_0; \
|
||||
VMOVQ_SI_X15(4*8); \
|
||||
VPINSRQ_1_SI_X12(5*8); \
|
||||
VPINSRQ_1_SI_X13(10*8); \
|
||||
VPINSRQ_1_SI_X14(7*8); \
|
||||
VPINSRQ_1_SI_X15(15*8)
|
||||
|
||||
// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3)
|
||||
#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \
|
||||
VMOVQ_SI_X12(2*8); \
|
||||
VMOVQ_SI_X13_0; \
|
||||
VMOVQ_SI_X14(12*8); \
|
||||
VMOVQ_SI_X15(11*8); \
|
||||
VPINSRQ_1_SI_X12(6*8); \
|
||||
VPINSRQ_1_SI_X13(8*8); \
|
||||
VPINSRQ_1_SI_X14(10*8); \
|
||||
VPINSRQ_1_SI_X15(3*8)
|
||||
|
||||
// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11)
|
||||
#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \
|
||||
MOVQ 0*8(SI), X12; \
|
||||
VPSHUFD $0x4E, 8*8(SI), X13; \
|
||||
MOVQ 7*8(SI), X14; \
|
||||
MOVQ 2*8(SI), X15; \
|
||||
VPINSRQ_1_SI_X12(6*8); \
|
||||
VPINSRQ_1_SI_X14(3*8); \
|
||||
VPINSRQ_1_SI_X15(11*8)
|
||||
|
||||
// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8)
|
||||
#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \
|
||||
MOVQ 6*8(SI), X12; \
|
||||
MOVQ 11*8(SI), X13; \
|
||||
MOVQ 15*8(SI), X14; \
|
||||
MOVQ 3*8(SI), X15; \
|
||||
VPINSRQ_1_SI_X12(14*8); \
|
||||
VPINSRQ_1_SI_X13_0; \
|
||||
VPINSRQ_1_SI_X14(9*8); \
|
||||
VPINSRQ_1_SI_X15(8*8)
|
||||
|
||||
// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10)
|
||||
#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \
|
||||
MOVQ 5*8(SI), X12; \
|
||||
MOVQ 8*8(SI), X13; \
|
||||
MOVQ 0*8(SI), X14; \
|
||||
MOVQ 6*8(SI), X15; \
|
||||
VPINSRQ_1_SI_X12(15*8); \
|
||||
VPINSRQ_1_SI_X13(2*8); \
|
||||
VPINSRQ_1_SI_X14(4*8); \
|
||||
VPINSRQ_1_SI_X15(10*8)
|
||||
|
||||
// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5)
|
||||
#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \
|
||||
VMOVDQU 12*8(SI), X12; \
|
||||
MOVQ 1*8(SI), X13; \
|
||||
MOVQ 2*8(SI), X14; \
|
||||
VPINSRQ_1_SI_X13(10*8); \
|
||||
VPINSRQ_1_SI_X14(7*8); \
|
||||
VMOVDQU 4*8(SI), X15
|
||||
|
||||
// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0)
|
||||
#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \
|
||||
MOVQ 15*8(SI), X12; \
|
||||
MOVQ 3*8(SI), X13; \
|
||||
MOVQ 11*8(SI), X14; \
|
||||
MOVQ 12*8(SI), X15; \
|
||||
VPINSRQ_1_SI_X12(9*8); \
|
||||
VPINSRQ_1_SI_X13(13*8); \
|
||||
VPINSRQ_1_SI_X14(14*8); \
|
||||
VPINSRQ_1_SI_X15_0
|
||||
|
||||
// func fAVX(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64)
|
||||
TEXT ·fAVX(SB), 4, $24-48 // frame size = 8 + 16 byte alignment
|
||||
MOVQ h+0(FP), AX
|
||||
MOVQ m+8(FP), SI
|
||||
MOVQ c0+16(FP), R8
|
||||
MOVQ c1+24(FP), R9
|
||||
MOVQ flag+32(FP), CX
|
||||
MOVQ rounds+40(FP), BX
|
||||
|
||||
MOVQ SP, BP
|
||||
MOVQ SP, R10
|
||||
ADDQ $15, R10
|
||||
ANDQ $~15, R10
|
||||
MOVQ R10, SP
|
||||
|
||||
VMOVDQU ·AVX_c40<>(SB), X0
|
||||
VMOVDQU ·AVX_c48<>(SB), X1
|
||||
VMOVDQA X0, X8
|
||||
VMOVDQA X1, X9
|
||||
|
||||
VMOVDQU ·AVX_iv3<>(SB), X0
|
||||
VMOVDQA X0, 0(SP)
|
||||
XORQ CX, 0(SP) // 0(SP) = ·AVX_iv3 ^ (CX || 0)
|
||||
|
||||
VMOVDQU 0(AX), X10
|
||||
VMOVDQU 16(AX), X11
|
||||
VMOVDQU 32(AX), X2
|
||||
VMOVDQU 48(AX), X3
|
||||
|
||||
VMOVQ_R8_X15
|
||||
VPINSRQ_1_R9_X15
|
||||
|
||||
VMOVDQA X10, X0
|
||||
VMOVDQA X11, X1
|
||||
VMOVDQU ·AVX_iv0<>(SB), X4
|
||||
VMOVDQU ·AVX_iv1<>(SB), X5
|
||||
VMOVDQU ·AVX_iv2<>(SB), X6
|
||||
|
||||
VPXOR X15, X6, X6
|
||||
VMOVDQA 0(SP), X7
|
||||
|
||||
loop:
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX_0_2_4_6_1_3_5_7()
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX()
|
||||
LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15)
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX_INV()
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6)
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX()
|
||||
LOAD_MSG_AVX_1_0_11_5_12_2_7_3()
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX_INV()
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX_11_12_5_15_8_0_2_13()
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX()
|
||||
LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4)
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX_INV()
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14)
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX()
|
||||
LOAD_MSG_AVX_2_5_4_15_6_10_0_8()
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX_INV()
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX_9_5_2_10_0_7_4_15()
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX()
|
||||
LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13)
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX_INV()
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX_2_6_0_8_12_10_11_3()
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX()
|
||||
LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9)
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX_INV()
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10)
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX()
|
||||
LOAD_MSG_AVX_0_6_9_8_7_3_2_11()
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX_INV()
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9)
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX()
|
||||
LOAD_MSG_AVX_5_15_8_2_0_4_6_10()
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX_INV()
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX_6_14_11_0_15_9_3_8()
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX()
|
||||
LOAD_MSG_AVX_12_13_1_10_2_7_4_5()
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX_INV()
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5)
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX()
|
||||
LOAD_MSG_AVX_15_9_3_13_11_14_12_0()
|
||||
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
|
||||
SHUFFLE_AVX_INV()
|
||||
|
||||
JMP loop
|
||||
|
||||
done:
|
||||
VMOVDQU 32(AX), X14
|
||||
VMOVDQU 48(AX), X15
|
||||
VPXOR X0, X10, X10
|
||||
VPXOR X1, X11, X11
|
||||
VPXOR X2, X14, X14
|
||||
VPXOR X3, X15, X15
|
||||
VPXOR X4, X10, X10
|
||||
VPXOR X5, X11, X11
|
||||
VPXOR X6, X14, X2
|
||||
VPXOR X7, X15, X3
|
||||
VMOVDQU X2, 32(AX)
|
||||
VMOVDQU X3, 48(AX)
|
||||
|
||||
VMOVDQU X10, 0(AX)
|
||||
VMOVDQU X11, 16(AX)
|
||||
VZEROUPPER
|
||||
|
||||
MOVQ BP, SP
|
||||
RET
|
||||
25
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.go
generated
vendored
Normal file
25
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.7 && amd64 && !gccgo && !appengine
|
||||
// +build !go1.7,amd64,!gccgo,!appengine
|
||||
|
||||
package blake2b
|
||||
|
||||
import "golang.org/x/sys/cpu"
|
||||
|
||||
func init() {
|
||||
useSSE4 = cpu.X86.HasSSE41
|
||||
}
|
||||
|
||||
//go:noescape
|
||||
func fSSE4(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64)
|
||||
|
||||
func f(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) {
|
||||
if useSSE4 {
|
||||
fSSE4(h, m, c0, c1, flag, rounds)
|
||||
} else {
|
||||
fGeneric(h, m, c0, c1, flag, rounds)
|
||||
}
|
||||
}
|
||||
253
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.s
generated
vendored
Normal file
253
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.s
generated
vendored
Normal file
@@ -0,0 +1,253 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
DATA ·iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908
|
||||
DATA ·iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b
|
||||
GLOBL ·iv0<>(SB), (NOPTR+RODATA), $16
|
||||
|
||||
DATA ·iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b
|
||||
DATA ·iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1
|
||||
GLOBL ·iv1<>(SB), (NOPTR+RODATA), $16
|
||||
|
||||
DATA ·iv2<>+0x00(SB)/8, $0x510e527fade682d1
|
||||
DATA ·iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f
|
||||
GLOBL ·iv2<>(SB), (NOPTR+RODATA), $16
|
||||
|
||||
DATA ·iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b
|
||||
DATA ·iv3<>+0x08(SB)/8, $0x5be0cd19137e2179
|
||||
GLOBL ·iv3<>(SB), (NOPTR+RODATA), $16
|
||||
|
||||
DATA ·c40<>+0x00(SB)/8, $0x0201000706050403
|
||||
DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b
|
||||
GLOBL ·c40<>(SB), (NOPTR+RODATA), $16
|
||||
|
||||
DATA ·c48<>+0x00(SB)/8, $0x0100070605040302
|
||||
DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a
|
||||
GLOBL ·c48<>(SB), (NOPTR+RODATA), $16
|
||||
|
||||
#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \
|
||||
MOVO v4, t1; \
|
||||
MOVO v5, v4; \
|
||||
MOVO t1, v5; \
|
||||
MOVO v6, t1; \
|
||||
PUNPCKLQDQ v6, t2; \
|
||||
PUNPCKHQDQ v7, v6; \
|
||||
PUNPCKHQDQ t2, v6; \
|
||||
PUNPCKLQDQ v7, t2; \
|
||||
MOVO t1, v7; \
|
||||
MOVO v2, t1; \
|
||||
PUNPCKHQDQ t2, v7; \
|
||||
PUNPCKLQDQ v3, t2; \
|
||||
PUNPCKHQDQ t2, v2; \
|
||||
PUNPCKLQDQ t1, t2; \
|
||||
PUNPCKHQDQ t2, v3
|
||||
|
||||
#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \
|
||||
MOVO v4, t1; \
|
||||
MOVO v5, v4; \
|
||||
MOVO t1, v5; \
|
||||
MOVO v2, t1; \
|
||||
PUNPCKLQDQ v2, t2; \
|
||||
PUNPCKHQDQ v3, v2; \
|
||||
PUNPCKHQDQ t2, v2; \
|
||||
PUNPCKLQDQ v3, t2; \
|
||||
MOVO t1, v3; \
|
||||
MOVO v6, t1; \
|
||||
PUNPCKHQDQ t2, v3; \
|
||||
PUNPCKLQDQ v7, t2; \
|
||||
PUNPCKHQDQ t2, v6; \
|
||||
PUNPCKLQDQ t1, t2; \
|
||||
PUNPCKHQDQ t2, v7
|
||||
|
||||
#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \
|
||||
PADDQ m0, v0; \
|
||||
PADDQ m1, v1; \
|
||||
PADDQ v2, v0; \
|
||||
PADDQ v3, v1; \
|
||||
PXOR v0, v6; \
|
||||
PXOR v1, v7; \
|
||||
PSHUFD $0xB1, v6, v6; \
|
||||
PSHUFD $0xB1, v7, v7; \
|
||||
PADDQ v6, v4; \
|
||||
PADDQ v7, v5; \
|
||||
PXOR v4, v2; \
|
||||
PXOR v5, v3; \
|
||||
PSHUFB c40, v2; \
|
||||
PSHUFB c40, v3; \
|
||||
PADDQ m2, v0; \
|
||||
PADDQ m3, v1; \
|
||||
PADDQ v2, v0; \
|
||||
PADDQ v3, v1; \
|
||||
PXOR v0, v6; \
|
||||
PXOR v1, v7; \
|
||||
PSHUFB c48, v6; \
|
||||
PSHUFB c48, v7; \
|
||||
PADDQ v6, v4; \
|
||||
PADDQ v7, v5; \
|
||||
PXOR v4, v2; \
|
||||
PXOR v5, v3; \
|
||||
MOVOU v2, t0; \
|
||||
PADDQ v2, t0; \
|
||||
PSRLQ $63, v2; \
|
||||
PXOR t0, v2; \
|
||||
MOVOU v3, t0; \
|
||||
PADDQ v3, t0; \
|
||||
PSRLQ $63, v3; \
|
||||
PXOR t0, v3
|
||||
|
||||
#define LOAD_MSG(m0, m1, m2, m3, i0, i1, i2, i3, i4, i5, i6, i7) \
|
||||
MOVQ i0*8(SI), m0; \
|
||||
PINSRQ $1, i1*8(SI), m0; \
|
||||
MOVQ i2*8(SI), m1; \
|
||||
PINSRQ $1, i3*8(SI), m1; \
|
||||
MOVQ i4*8(SI), m2; \
|
||||
PINSRQ $1, i5*8(SI), m2; \
|
||||
MOVQ i6*8(SI), m3; \
|
||||
PINSRQ $1, i7*8(SI), m3
|
||||
|
||||
// func fSSE4(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64)
|
||||
TEXT ·fSSE4(SB), 4, $24-48 // frame size = 8 + 16 byte alignment
|
||||
MOVQ h+0(FP), AX
|
||||
MOVQ m+8(FP), SI
|
||||
MOVQ c0+16(FP), R8
|
||||
MOVQ c1+24(FP), R9
|
||||
MOVQ flag+32(FP), CX
|
||||
MOVQ rounds+40(FP), BX
|
||||
|
||||
MOVQ SP, BP
|
||||
MOVQ SP, R10
|
||||
ADDQ $15, R10
|
||||
ANDQ $~15, R10
|
||||
MOVQ R10, SP
|
||||
|
||||
MOVOU ·iv3<>(SB), X0
|
||||
MOVO X0, 0(SP)
|
||||
XORQ CX, 0(SP) // 0(SP) = ·iv3 ^ (CX || 0)
|
||||
|
||||
MOVOU ·c40<>(SB), X13
|
||||
MOVOU ·c48<>(SB), X14
|
||||
|
||||
MOVOU 0(AX), X12
|
||||
MOVOU 16(AX), X15
|
||||
|
||||
MOVQ R8, X8
|
||||
PINSRQ $1, R9, X8
|
||||
|
||||
MOVO X12, X0
|
||||
MOVO X15, X1
|
||||
MOVOU 32(AX), X2
|
||||
MOVOU 48(AX), X3
|
||||
MOVOU ·iv0<>(SB), X4
|
||||
MOVOU ·iv1<>(SB), X5
|
||||
MOVOU ·iv2<>(SB), X6
|
||||
|
||||
PXOR X8, X6
|
||||
MOVO 0(SP), X7
|
||||
|
||||
loop:
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG(X8, X9, X10, X11, 0, 2, 4, 6, 1, 3, 5, 7)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
LOAD_MSG(X8, X9, X10, X11, 8, 10, 12, 14, 9, 11, 13, 15)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG(X8, X9, X10, X11, 14, 4, 9, 13, 10, 8, 15, 6)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
LOAD_MSG(X8, X9, X10, X11, 1, 0, 11, 5, 12, 2, 7, 3)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG(X8, X9, X10, X11, 11, 12, 5, 15, 8, 0, 2, 13)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
LOAD_MSG(X8, X9, X10, X11, 10, 3, 7, 9, 14, 6, 1, 4)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG(X8, X9, X10, X11, 7, 3, 13, 11, 9, 1, 12, 14)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
LOAD_MSG(X8, X9, X10, X11, 2, 5, 4, 15, 6, 10, 0, 8)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG(X8, X9, X10, X11, 9, 5, 2, 10, 0, 7, 4, 15)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
LOAD_MSG(X8, X9, X10, X11, 14, 11, 6, 3, 1, 12, 8, 13)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG(X8, X9, X10, X11, 2, 6, 0, 8, 12, 10, 11, 3)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
LOAD_MSG(X8, X9, X10, X11, 4, 7, 15, 1, 13, 5, 14, 9)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG(X8, X9, X10, X11, 12, 1, 14, 4, 5, 15, 13, 10)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
LOAD_MSG(X8, X9, X10, X11, 0, 6, 9, 8, 7, 3, 2, 11)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG(X8, X9, X10, X11, 13, 7, 12, 3, 11, 14, 1, 9)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
LOAD_MSG(X8, X9, X10, X11, 5, 15, 8, 2, 0, 4, 6, 10)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG(X8, X9, X10, X11, 6, 14, 11, 0, 15, 9, 3, 8)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
LOAD_MSG(X8, X9, X10, X11, 12, 13, 1, 10, 2, 7, 4, 5)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
|
||||
SUBQ $1, BX; JCS done
|
||||
LOAD_MSG(X8, X9, X10, X11, 10, 8, 7, 1, 2, 4, 6, 5)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
LOAD_MSG(X8, X9, X10, X11, 15, 9, 3, 13, 11, 14, 12, 0)
|
||||
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
|
||||
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
|
||||
|
||||
JMP loop
|
||||
|
||||
done:
|
||||
MOVOU 32(AX), X10
|
||||
MOVOU 48(AX), X11
|
||||
PXOR X0, X12
|
||||
PXOR X1, X15
|
||||
PXOR X2, X10
|
||||
PXOR X3, X11
|
||||
PXOR X4, X12
|
||||
PXOR X5, X15
|
||||
PXOR X6, X10
|
||||
PXOR X7, X11
|
||||
MOVOU X10, 32(AX)
|
||||
MOVOU X11, 48(AX)
|
||||
|
||||
MOVOU X12, 0(AX)
|
||||
MOVOU X15, 16(AX)
|
||||
|
||||
MOVQ BP, SP
|
||||
RET
|
||||
58
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_f_fuzz.go
generated
vendored
Normal file
58
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_f_fuzz.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
//go:build gofuzz
|
||||
// +build gofuzz
|
||||
|
||||
package blake2b
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
// Make sure the data confirms to the input model
|
||||
if len(data) != 211 {
|
||||
return 0
|
||||
}
|
||||
// Parse everything and call all the implementations
|
||||
var (
|
||||
rounds = binary.BigEndian.Uint16(data[0:2])
|
||||
|
||||
h [8]uint64
|
||||
m [16]uint64
|
||||
t [2]uint64
|
||||
f uint64
|
||||
)
|
||||
for i := 0; i < 8; i++ {
|
||||
offset := 2 + i*8
|
||||
h[i] = binary.LittleEndian.Uint64(data[offset : offset+8])
|
||||
}
|
||||
for i := 0; i < 16; i++ {
|
||||
offset := 66 + i*8
|
||||
m[i] = binary.LittleEndian.Uint64(data[offset : offset+8])
|
||||
}
|
||||
t[0] = binary.LittleEndian.Uint64(data[194:202])
|
||||
t[1] = binary.LittleEndian.Uint64(data[202:210])
|
||||
|
||||
if data[210]%2 == 1 { // Avoid spinning the fuzzer to hit 0/1
|
||||
f = 0xFFFFFFFFFFFFFFFF
|
||||
}
|
||||
// Run the blake2b compression on all instruction sets and cross reference
|
||||
want := h
|
||||
fGeneric(&want, &m, t[0], t[1], f, uint64(rounds))
|
||||
|
||||
have := h
|
||||
fSSE4(&have, &m, t[0], t[1], f, uint64(rounds))
|
||||
if have != want {
|
||||
panic("SSE4 mismatches generic algo")
|
||||
}
|
||||
have = h
|
||||
fAVX(&have, &m, t[0], t[1], f, uint64(rounds))
|
||||
if have != want {
|
||||
panic("AVX mismatches generic algo")
|
||||
}
|
||||
have = h
|
||||
fAVX2(&have, &m, t[0], t[1], f, uint64(rounds))
|
||||
if have != want {
|
||||
panic("AVX2 mismatches generic algo")
|
||||
}
|
||||
return 1
|
||||
}
|
||||
181
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_generic.go
generated
vendored
Normal file
181
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_generic.go
generated
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blake2b
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
// the precomputed values for BLAKE2b
|
||||
// there are 10 16-byte arrays - one for each round
|
||||
// the entries are calculated from the sigma constants.
|
||||
var precomputed = [10][16]byte{
|
||||
{0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15},
|
||||
{14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3},
|
||||
{11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4},
|
||||
{7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8},
|
||||
{9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13},
|
||||
{2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9},
|
||||
{12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11},
|
||||
{13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10},
|
||||
{6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5},
|
||||
{10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0},
|
||||
}
|
||||
|
||||
// nolint:unused,deadcode
|
||||
func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
|
||||
var m [16]uint64
|
||||
c0, c1 := c[0], c[1]
|
||||
|
||||
for i := 0; i < len(blocks); {
|
||||
c0 += BlockSize
|
||||
if c0 < BlockSize {
|
||||
c1++
|
||||
}
|
||||
for j := range m {
|
||||
m[j] = binary.LittleEndian.Uint64(blocks[i:])
|
||||
i += 8
|
||||
}
|
||||
fGeneric(h, &m, c0, c1, flag, 12)
|
||||
}
|
||||
c[0], c[1] = c0, c1
|
||||
}
|
||||
|
||||
func fGeneric(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) {
|
||||
v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]
|
||||
v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7]
|
||||
v12 ^= c0
|
||||
v13 ^= c1
|
||||
v14 ^= flag
|
||||
|
||||
for i := 0; i < int(rounds); i++ {
|
||||
s := &(precomputed[i%10])
|
||||
|
||||
v0 += m[s[0]]
|
||||
v0 += v4
|
||||
v12 ^= v0
|
||||
v12 = bits.RotateLeft64(v12, -32)
|
||||
v8 += v12
|
||||
v4 ^= v8
|
||||
v4 = bits.RotateLeft64(v4, -24)
|
||||
v1 += m[s[1]]
|
||||
v1 += v5
|
||||
v13 ^= v1
|
||||
v13 = bits.RotateLeft64(v13, -32)
|
||||
v9 += v13
|
||||
v5 ^= v9
|
||||
v5 = bits.RotateLeft64(v5, -24)
|
||||
v2 += m[s[2]]
|
||||
v2 += v6
|
||||
v14 ^= v2
|
||||
v14 = bits.RotateLeft64(v14, -32)
|
||||
v10 += v14
|
||||
v6 ^= v10
|
||||
v6 = bits.RotateLeft64(v6, -24)
|
||||
v3 += m[s[3]]
|
||||
v3 += v7
|
||||
v15 ^= v3
|
||||
v15 = bits.RotateLeft64(v15, -32)
|
||||
v11 += v15
|
||||
v7 ^= v11
|
||||
v7 = bits.RotateLeft64(v7, -24)
|
||||
|
||||
v0 += m[s[4]]
|
||||
v0 += v4
|
||||
v12 ^= v0
|
||||
v12 = bits.RotateLeft64(v12, -16)
|
||||
v8 += v12
|
||||
v4 ^= v8
|
||||
v4 = bits.RotateLeft64(v4, -63)
|
||||
v1 += m[s[5]]
|
||||
v1 += v5
|
||||
v13 ^= v1
|
||||
v13 = bits.RotateLeft64(v13, -16)
|
||||
v9 += v13
|
||||
v5 ^= v9
|
||||
v5 = bits.RotateLeft64(v5, -63)
|
||||
v2 += m[s[6]]
|
||||
v2 += v6
|
||||
v14 ^= v2
|
||||
v14 = bits.RotateLeft64(v14, -16)
|
||||
v10 += v14
|
||||
v6 ^= v10
|
||||
v6 = bits.RotateLeft64(v6, -63)
|
||||
v3 += m[s[7]]
|
||||
v3 += v7
|
||||
v15 ^= v3
|
||||
v15 = bits.RotateLeft64(v15, -16)
|
||||
v11 += v15
|
||||
v7 ^= v11
|
||||
v7 = bits.RotateLeft64(v7, -63)
|
||||
|
||||
v0 += m[s[8]]
|
||||
v0 += v5
|
||||
v15 ^= v0
|
||||
v15 = bits.RotateLeft64(v15, -32)
|
||||
v10 += v15
|
||||
v5 ^= v10
|
||||
v5 = bits.RotateLeft64(v5, -24)
|
||||
v1 += m[s[9]]
|
||||
v1 += v6
|
||||
v12 ^= v1
|
||||
v12 = bits.RotateLeft64(v12, -32)
|
||||
v11 += v12
|
||||
v6 ^= v11
|
||||
v6 = bits.RotateLeft64(v6, -24)
|
||||
v2 += m[s[10]]
|
||||
v2 += v7
|
||||
v13 ^= v2
|
||||
v13 = bits.RotateLeft64(v13, -32)
|
||||
v8 += v13
|
||||
v7 ^= v8
|
||||
v7 = bits.RotateLeft64(v7, -24)
|
||||
v3 += m[s[11]]
|
||||
v3 += v4
|
||||
v14 ^= v3
|
||||
v14 = bits.RotateLeft64(v14, -32)
|
||||
v9 += v14
|
||||
v4 ^= v9
|
||||
v4 = bits.RotateLeft64(v4, -24)
|
||||
|
||||
v0 += m[s[12]]
|
||||
v0 += v5
|
||||
v15 ^= v0
|
||||
v15 = bits.RotateLeft64(v15, -16)
|
||||
v10 += v15
|
||||
v5 ^= v10
|
||||
v5 = bits.RotateLeft64(v5, -63)
|
||||
v1 += m[s[13]]
|
||||
v1 += v6
|
||||
v12 ^= v1
|
||||
v12 = bits.RotateLeft64(v12, -16)
|
||||
v11 += v12
|
||||
v6 ^= v11
|
||||
v6 = bits.RotateLeft64(v6, -63)
|
||||
v2 += m[s[14]]
|
||||
v2 += v7
|
||||
v13 ^= v2
|
||||
v13 = bits.RotateLeft64(v13, -16)
|
||||
v8 += v13
|
||||
v7 ^= v8
|
||||
v7 = bits.RotateLeft64(v7, -63)
|
||||
v3 += m[s[15]]
|
||||
v3 += v4
|
||||
v14 ^= v3
|
||||
v14 = bits.RotateLeft64(v14, -16)
|
||||
v9 += v14
|
||||
v4 ^= v9
|
||||
v4 = bits.RotateLeft64(v4, -63)
|
||||
}
|
||||
h[0] ^= v0 ^ v8
|
||||
h[1] ^= v1 ^ v9
|
||||
h[2] ^= v2 ^ v10
|
||||
h[3] ^= v3 ^ v11
|
||||
h[4] ^= v4 ^ v12
|
||||
h[5] ^= v5 ^ v13
|
||||
h[6] ^= v6 ^ v14
|
||||
h[7] ^= v7 ^ v15
|
||||
}
|
||||
12
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_ref.go
generated
vendored
Normal file
12
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_ref.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !amd64 || appengine || gccgo
|
||||
// +build !amd64 appengine gccgo
|
||||
|
||||
package blake2b
|
||||
|
||||
func f(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) {
|
||||
fGeneric(h, m, c0, c1, flag, rounds)
|
||||
}
|
||||
177
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2x.go
generated
vendored
Normal file
177
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2x.go
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blake2b
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
// XOF defines the interface to hash functions that
|
||||
// support arbitrary-length output.
|
||||
type XOF interface {
|
||||
// Write absorbs more data into the hash's state. It panics if called
|
||||
// after Read.
|
||||
io.Writer
|
||||
|
||||
// Read reads more output from the hash. It returns io.EOF if the limit
|
||||
// has been reached.
|
||||
io.Reader
|
||||
|
||||
// Clone returns a copy of the XOF in its current state.
|
||||
Clone() XOF
|
||||
|
||||
// Reset resets the XOF to its initial state.
|
||||
Reset()
|
||||
}
|
||||
|
||||
// OutputLengthUnknown can be used as the size argument to NewXOF to indicate
|
||||
// the length of the output is not known in advance.
|
||||
const OutputLengthUnknown = 0
|
||||
|
||||
// magicUnknownOutputLength is a magic value for the output size that indicates
|
||||
// an unknown number of output bytes.
|
||||
const magicUnknownOutputLength = (1 << 32) - 1
|
||||
|
||||
// maxOutputLength is the absolute maximum number of bytes to produce when the
|
||||
// number of output bytes is unknown.
|
||||
const maxOutputLength = (1 << 32) * 64
|
||||
|
||||
// NewXOF creates a new variable-output-length hash. The hash either produce a
|
||||
// known number of bytes (1 <= size < 2**32-1), or an unknown number of bytes
|
||||
// (size == OutputLengthUnknown). In the latter case, an absolute limit of
|
||||
// 256GiB applies.
|
||||
//
|
||||
// A non-nil key turns the hash into a MAC. The key must between
|
||||
// zero and 32 bytes long.
|
||||
func NewXOF(size uint32, key []byte) (XOF, error) {
|
||||
if len(key) > Size {
|
||||
return nil, errKeySize
|
||||
}
|
||||
if size == magicUnknownOutputLength {
|
||||
// 2^32-1 indicates an unknown number of bytes and thus isn't a
|
||||
// valid length.
|
||||
return nil, errors.New("blake2b: XOF length too large")
|
||||
}
|
||||
if size == OutputLengthUnknown {
|
||||
size = magicUnknownOutputLength
|
||||
}
|
||||
x := &xof{
|
||||
d: digest{
|
||||
size: Size,
|
||||
keyLen: len(key),
|
||||
},
|
||||
length: size,
|
||||
}
|
||||
copy(x.d.key[:], key)
|
||||
x.Reset()
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type xof struct {
|
||||
d digest
|
||||
length uint32
|
||||
remaining uint64
|
||||
cfg, root, block [Size]byte
|
||||
offset int
|
||||
nodeOffset uint32
|
||||
readMode bool
|
||||
}
|
||||
|
||||
func (x *xof) Write(p []byte) (n int, err error) {
|
||||
if x.readMode {
|
||||
panic("blake2b: write to XOF after read")
|
||||
}
|
||||
return x.d.Write(p)
|
||||
}
|
||||
|
||||
func (x *xof) Clone() XOF {
|
||||
clone := *x
|
||||
return &clone
|
||||
}
|
||||
|
||||
func (x *xof) Reset() {
|
||||
x.cfg[0] = byte(Size)
|
||||
binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length
|
||||
binary.LittleEndian.PutUint32(x.cfg[12:], x.length) // XOF length
|
||||
x.cfg[17] = byte(Size) // inner hash size
|
||||
|
||||
x.d.Reset()
|
||||
x.d.h[1] ^= uint64(x.length) << 32
|
||||
|
||||
x.remaining = uint64(x.length)
|
||||
if x.remaining == magicUnknownOutputLength {
|
||||
x.remaining = maxOutputLength
|
||||
}
|
||||
x.offset, x.nodeOffset = 0, 0
|
||||
x.readMode = false
|
||||
}
|
||||
|
||||
func (x *xof) Read(p []byte) (n int, err error) {
|
||||
if !x.readMode {
|
||||
x.d.finalize(&x.root)
|
||||
x.readMode = true
|
||||
}
|
||||
|
||||
if x.remaining == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
n = len(p)
|
||||
if uint64(n) > x.remaining {
|
||||
n = int(x.remaining)
|
||||
p = p[:n]
|
||||
}
|
||||
|
||||
if x.offset > 0 {
|
||||
blockRemaining := Size - x.offset
|
||||
if n < blockRemaining {
|
||||
x.offset += copy(p, x.block[x.offset:])
|
||||
x.remaining -= uint64(n)
|
||||
return
|
||||
}
|
||||
copy(p, x.block[x.offset:])
|
||||
p = p[blockRemaining:]
|
||||
x.offset = 0
|
||||
x.remaining -= uint64(blockRemaining)
|
||||
}
|
||||
|
||||
for len(p) >= Size {
|
||||
binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset)
|
||||
x.nodeOffset++
|
||||
|
||||
x.d.initConfig(&x.cfg)
|
||||
x.d.Write(x.root[:])
|
||||
x.d.finalize(&x.block)
|
||||
|
||||
copy(p, x.block[:])
|
||||
p = p[Size:]
|
||||
x.remaining -= uint64(Size)
|
||||
}
|
||||
|
||||
if todo := len(p); todo > 0 {
|
||||
if x.remaining < uint64(Size) {
|
||||
x.cfg[0] = byte(x.remaining)
|
||||
}
|
||||
binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset)
|
||||
x.nodeOffset++
|
||||
|
||||
x.d.initConfig(&x.cfg)
|
||||
x.d.Write(x.root[:])
|
||||
x.d.finalize(&x.block)
|
||||
|
||||
x.offset = copy(p, x.block[:todo])
|
||||
x.remaining -= uint64(todo)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *digest) initConfig(cfg *[Size]byte) {
|
||||
d.offset, d.c[0], d.c[1] = 0, 0, 0
|
||||
for i := range d.h {
|
||||
d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(cfg[i*8:])
|
||||
}
|
||||
}
|
||||
33
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/register.go
generated
vendored
Normal file
33
vendor/github.com/ethereum/go-ethereum/crypto/blake2b/register.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.9
|
||||
// +build go1.9
|
||||
|
||||
package blake2b
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"hash"
|
||||
)
|
||||
|
||||
func init() {
|
||||
newHash256 := func() hash.Hash {
|
||||
h, _ := New256(nil)
|
||||
return h
|
||||
}
|
||||
newHash384 := func() hash.Hash {
|
||||
h, _ := New384(nil)
|
||||
return h
|
||||
}
|
||||
|
||||
newHash512 := func() hash.Hash {
|
||||
h, _ := New512(nil)
|
||||
return h
|
||||
}
|
||||
|
||||
crypto.RegisterHash(crypto.BLAKE2b_256, newHash256)
|
||||
crypto.RegisterHash(crypto.BLAKE2b_384, newHash384)
|
||||
crypto.RegisterHash(crypto.BLAKE2b_512, newHash512)
|
||||
}
|
||||
84
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/arithmetic_decl.go
generated
vendored
Normal file
84
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/arithmetic_decl.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
// 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/>.
|
||||
|
||||
//go:build (amd64 && blsasm) || (amd64 && blsadx)
|
||||
// +build amd64,blsasm amd64,blsadx
|
||||
|
||||
package bls12381
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/cpu"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if !enableADX || !cpu.X86.HasADX || !cpu.X86.HasBMI2 {
|
||||
mul = mulNoADX
|
||||
}
|
||||
}
|
||||
|
||||
// Use ADX backend for default
|
||||
var mul func(c, a, b *fe) = mulADX
|
||||
|
||||
func square(c, a *fe) {
|
||||
mul(c, a, a)
|
||||
}
|
||||
|
||||
func neg(c, a *fe) {
|
||||
if a.isZero() {
|
||||
c.set(a)
|
||||
} else {
|
||||
_neg(c, a)
|
||||
}
|
||||
}
|
||||
|
||||
//go:noescape
|
||||
func add(c, a, b *fe)
|
||||
|
||||
//go:noescape
|
||||
func addAssign(a, b *fe)
|
||||
|
||||
//go:noescape
|
||||
func ladd(c, a, b *fe)
|
||||
|
||||
//go:noescape
|
||||
func laddAssign(a, b *fe)
|
||||
|
||||
//go:noescape
|
||||
func double(c, a *fe)
|
||||
|
||||
//go:noescape
|
||||
func doubleAssign(a *fe)
|
||||
|
||||
//go:noescape
|
||||
func ldouble(c, a *fe)
|
||||
|
||||
//go:noescape
|
||||
func sub(c, a, b *fe)
|
||||
|
||||
//go:noescape
|
||||
func subAssign(a, b *fe)
|
||||
|
||||
//go:noescape
|
||||
func lsubAssign(a, b *fe)
|
||||
|
||||
//go:noescape
|
||||
func _neg(c, a *fe)
|
||||
|
||||
//go:noescape
|
||||
func mulNoADX(c, a, b *fe)
|
||||
|
||||
//go:noescape
|
||||
func mulADX(c, a, b *fe)
|
||||
567
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/arithmetic_fallback.go
generated
vendored
Normal file
567
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/arithmetic_fallback.go
generated
vendored
Normal file
@@ -0,0 +1,567 @@
|
||||
// Native go field arithmetic code is generated with 'goff'
|
||||
// https://github.com/ConsenSys/goff
|
||||
// Many function signature of field operations are renamed.
|
||||
|
||||
// Copyright 2020 ConsenSys AG
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// field modulus q =
|
||||
//
|
||||
// 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
|
||||
// Code generated by goff DO NOT EDIT
|
||||
// goff version: v0.1.0 - build: 790f1f56eac432441e043abff8819eacddd1d668
|
||||
// fe are assumed to be in Montgomery form in all methods
|
||||
|
||||
// /!\ WARNING /!\
|
||||
// this code has not been audited and is provided as-is. In particular,
|
||||
// there is no security guarantees such as constant time implementation
|
||||
// or side-channel attack resistance
|
||||
// /!\ WARNING /!\
|
||||
|
||||
// Package bls (generated by goff) contains field arithmetics operations
|
||||
|
||||
//go:build !amd64 || (!blsasm && !blsadx)
|
||||
// +build !amd64 !blsasm,!blsadx
|
||||
|
||||
package bls12381
|
||||
|
||||
import (
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
func add(z, x, y *fe) {
|
||||
var carry uint64
|
||||
|
||||
z[0], carry = bits.Add64(x[0], y[0], 0)
|
||||
z[1], carry = bits.Add64(x[1], y[1], carry)
|
||||
z[2], carry = bits.Add64(x[2], y[2], carry)
|
||||
z[3], carry = bits.Add64(x[3], y[3], carry)
|
||||
z[4], carry = bits.Add64(x[4], y[4], carry)
|
||||
z[5], _ = bits.Add64(x[5], y[5], carry)
|
||||
|
||||
// if z > q --> z -= q
|
||||
// note: this is NOT constant time
|
||||
if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
|
||||
var b uint64
|
||||
z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
|
||||
z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
|
||||
z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
|
||||
z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
|
||||
z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
|
||||
z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
|
||||
}
|
||||
}
|
||||
|
||||
func addAssign(x, y *fe) {
|
||||
var carry uint64
|
||||
|
||||
x[0], carry = bits.Add64(x[0], y[0], 0)
|
||||
x[1], carry = bits.Add64(x[1], y[1], carry)
|
||||
x[2], carry = bits.Add64(x[2], y[2], carry)
|
||||
x[3], carry = bits.Add64(x[3], y[3], carry)
|
||||
x[4], carry = bits.Add64(x[4], y[4], carry)
|
||||
x[5], _ = bits.Add64(x[5], y[5], carry)
|
||||
|
||||
// if z > q --> z -= q
|
||||
// note: this is NOT constant time
|
||||
if !(x[5] < 1873798617647539866 || (x[5] == 1873798617647539866 && (x[4] < 5412103778470702295 || (x[4] == 5412103778470702295 && (x[3] < 7239337960414712511 || (x[3] == 7239337960414712511 && (x[2] < 7435674573564081700 || (x[2] == 7435674573564081700 && (x[1] < 2210141511517208575 || (x[1] == 2210141511517208575 && (x[0] < 13402431016077863595))))))))))) {
|
||||
var b uint64
|
||||
x[0], b = bits.Sub64(x[0], 13402431016077863595, 0)
|
||||
x[1], b = bits.Sub64(x[1], 2210141511517208575, b)
|
||||
x[2], b = bits.Sub64(x[2], 7435674573564081700, b)
|
||||
x[3], b = bits.Sub64(x[3], 7239337960414712511, b)
|
||||
x[4], b = bits.Sub64(x[4], 5412103778470702295, b)
|
||||
x[5], _ = bits.Sub64(x[5], 1873798617647539866, b)
|
||||
}
|
||||
}
|
||||
|
||||
func ladd(z, x, y *fe) {
|
||||
var carry uint64
|
||||
z[0], carry = bits.Add64(x[0], y[0], 0)
|
||||
z[1], carry = bits.Add64(x[1], y[1], carry)
|
||||
z[2], carry = bits.Add64(x[2], y[2], carry)
|
||||
z[3], carry = bits.Add64(x[3], y[3], carry)
|
||||
z[4], carry = bits.Add64(x[4], y[4], carry)
|
||||
z[5], _ = bits.Add64(x[5], y[5], carry)
|
||||
}
|
||||
|
||||
func laddAssign(x, y *fe) {
|
||||
var carry uint64
|
||||
x[0], carry = bits.Add64(x[0], y[0], 0)
|
||||
x[1], carry = bits.Add64(x[1], y[1], carry)
|
||||
x[2], carry = bits.Add64(x[2], y[2], carry)
|
||||
x[3], carry = bits.Add64(x[3], y[3], carry)
|
||||
x[4], carry = bits.Add64(x[4], y[4], carry)
|
||||
x[5], _ = bits.Add64(x[5], y[5], carry)
|
||||
}
|
||||
|
||||
func double(z, x *fe) {
|
||||
var carry uint64
|
||||
|
||||
z[0], carry = bits.Add64(x[0], x[0], 0)
|
||||
z[1], carry = bits.Add64(x[1], x[1], carry)
|
||||
z[2], carry = bits.Add64(x[2], x[2], carry)
|
||||
z[3], carry = bits.Add64(x[3], x[3], carry)
|
||||
z[4], carry = bits.Add64(x[4], x[4], carry)
|
||||
z[5], _ = bits.Add64(x[5], x[5], carry)
|
||||
|
||||
// if z > q --> z -= q
|
||||
// note: this is NOT constant time
|
||||
if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
|
||||
var b uint64
|
||||
z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
|
||||
z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
|
||||
z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
|
||||
z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
|
||||
z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
|
||||
z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
|
||||
}
|
||||
}
|
||||
|
||||
func doubleAssign(z *fe) {
|
||||
var carry uint64
|
||||
|
||||
z[0], carry = bits.Add64(z[0], z[0], 0)
|
||||
z[1], carry = bits.Add64(z[1], z[1], carry)
|
||||
z[2], carry = bits.Add64(z[2], z[2], carry)
|
||||
z[3], carry = bits.Add64(z[3], z[3], carry)
|
||||
z[4], carry = bits.Add64(z[4], z[4], carry)
|
||||
z[5], _ = bits.Add64(z[5], z[5], carry)
|
||||
|
||||
// if z > q --> z -= q
|
||||
// note: this is NOT constant time
|
||||
if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
|
||||
var b uint64
|
||||
z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
|
||||
z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
|
||||
z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
|
||||
z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
|
||||
z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
|
||||
z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
|
||||
}
|
||||
}
|
||||
|
||||
func ldouble(z, x *fe) {
|
||||
var carry uint64
|
||||
|
||||
z[0], carry = bits.Add64(x[0], x[0], 0)
|
||||
z[1], carry = bits.Add64(x[1], x[1], carry)
|
||||
z[2], carry = bits.Add64(x[2], x[2], carry)
|
||||
z[3], carry = bits.Add64(x[3], x[3], carry)
|
||||
z[4], carry = bits.Add64(x[4], x[4], carry)
|
||||
z[5], _ = bits.Add64(x[5], x[5], carry)
|
||||
}
|
||||
|
||||
func sub(z, x, y *fe) {
|
||||
var b uint64
|
||||
z[0], b = bits.Sub64(x[0], y[0], 0)
|
||||
z[1], b = bits.Sub64(x[1], y[1], b)
|
||||
z[2], b = bits.Sub64(x[2], y[2], b)
|
||||
z[3], b = bits.Sub64(x[3], y[3], b)
|
||||
z[4], b = bits.Sub64(x[4], y[4], b)
|
||||
z[5], b = bits.Sub64(x[5], y[5], b)
|
||||
if b != 0 {
|
||||
var c uint64
|
||||
z[0], c = bits.Add64(z[0], 13402431016077863595, 0)
|
||||
z[1], c = bits.Add64(z[1], 2210141511517208575, c)
|
||||
z[2], c = bits.Add64(z[2], 7435674573564081700, c)
|
||||
z[3], c = bits.Add64(z[3], 7239337960414712511, c)
|
||||
z[4], c = bits.Add64(z[4], 5412103778470702295, c)
|
||||
z[5], _ = bits.Add64(z[5], 1873798617647539866, c)
|
||||
}
|
||||
}
|
||||
|
||||
func subAssign(z, x *fe) {
|
||||
var b uint64
|
||||
z[0], b = bits.Sub64(z[0], x[0], 0)
|
||||
z[1], b = bits.Sub64(z[1], x[1], b)
|
||||
z[2], b = bits.Sub64(z[2], x[2], b)
|
||||
z[3], b = bits.Sub64(z[3], x[3], b)
|
||||
z[4], b = bits.Sub64(z[4], x[4], b)
|
||||
z[5], b = bits.Sub64(z[5], x[5], b)
|
||||
if b != 0 {
|
||||
var c uint64
|
||||
z[0], c = bits.Add64(z[0], 13402431016077863595, 0)
|
||||
z[1], c = bits.Add64(z[1], 2210141511517208575, c)
|
||||
z[2], c = bits.Add64(z[2], 7435674573564081700, c)
|
||||
z[3], c = bits.Add64(z[3], 7239337960414712511, c)
|
||||
z[4], c = bits.Add64(z[4], 5412103778470702295, c)
|
||||
z[5], _ = bits.Add64(z[5], 1873798617647539866, c)
|
||||
}
|
||||
}
|
||||
|
||||
func lsubAssign(z, x *fe) {
|
||||
var b uint64
|
||||
z[0], b = bits.Sub64(z[0], x[0], 0)
|
||||
z[1], b = bits.Sub64(z[1], x[1], b)
|
||||
z[2], b = bits.Sub64(z[2], x[2], b)
|
||||
z[3], b = bits.Sub64(z[3], x[3], b)
|
||||
z[4], b = bits.Sub64(z[4], x[4], b)
|
||||
z[5], _ = bits.Sub64(z[5], x[5], b)
|
||||
}
|
||||
|
||||
func neg(z *fe, x *fe) {
|
||||
if x.isZero() {
|
||||
z.zero()
|
||||
return
|
||||
}
|
||||
var borrow uint64
|
||||
z[0], borrow = bits.Sub64(13402431016077863595, x[0], 0)
|
||||
z[1], borrow = bits.Sub64(2210141511517208575, x[1], borrow)
|
||||
z[2], borrow = bits.Sub64(7435674573564081700, x[2], borrow)
|
||||
z[3], borrow = bits.Sub64(7239337960414712511, x[3], borrow)
|
||||
z[4], borrow = bits.Sub64(5412103778470702295, x[4], borrow)
|
||||
z[5], _ = bits.Sub64(1873798617647539866, x[5], borrow)
|
||||
}
|
||||
|
||||
func mul(z, x, y *fe) {
|
||||
var t [6]uint64
|
||||
var c [3]uint64
|
||||
{
|
||||
// round 0
|
||||
v := x[0]
|
||||
c[1], c[0] = bits.Mul64(v, y[0])
|
||||
m := c[0] * 9940570264628428797
|
||||
c[2] = madd0(m, 13402431016077863595, c[0])
|
||||
c[1], c[0] = madd1(v, y[1], c[1])
|
||||
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
||||
c[1], c[0] = madd1(v, y[2], c[1])
|
||||
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
||||
c[1], c[0] = madd1(v, y[3], c[1])
|
||||
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
||||
c[1], c[0] = madd1(v, y[4], c[1])
|
||||
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
||||
c[1], c[0] = madd1(v, y[5], c[1])
|
||||
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
||||
}
|
||||
{
|
||||
// round 1
|
||||
v := x[1]
|
||||
c[1], c[0] = madd1(v, y[0], t[0])
|
||||
m := c[0] * 9940570264628428797
|
||||
c[2] = madd0(m, 13402431016077863595, c[0])
|
||||
c[1], c[0] = madd2(v, y[1], c[1], t[1])
|
||||
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[2], c[1], t[2])
|
||||
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[3], c[1], t[3])
|
||||
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[4], c[1], t[4])
|
||||
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[5], c[1], t[5])
|
||||
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
||||
}
|
||||
{
|
||||
// round 2
|
||||
v := x[2]
|
||||
c[1], c[0] = madd1(v, y[0], t[0])
|
||||
m := c[0] * 9940570264628428797
|
||||
c[2] = madd0(m, 13402431016077863595, c[0])
|
||||
c[1], c[0] = madd2(v, y[1], c[1], t[1])
|
||||
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[2], c[1], t[2])
|
||||
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[3], c[1], t[3])
|
||||
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[4], c[1], t[4])
|
||||
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[5], c[1], t[5])
|
||||
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
||||
}
|
||||
{
|
||||
// round 3
|
||||
v := x[3]
|
||||
c[1], c[0] = madd1(v, y[0], t[0])
|
||||
m := c[0] * 9940570264628428797
|
||||
c[2] = madd0(m, 13402431016077863595, c[0])
|
||||
c[1], c[0] = madd2(v, y[1], c[1], t[1])
|
||||
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[2], c[1], t[2])
|
||||
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[3], c[1], t[3])
|
||||
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[4], c[1], t[4])
|
||||
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[5], c[1], t[5])
|
||||
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
||||
}
|
||||
{
|
||||
// round 4
|
||||
v := x[4]
|
||||
c[1], c[0] = madd1(v, y[0], t[0])
|
||||
m := c[0] * 9940570264628428797
|
||||
c[2] = madd0(m, 13402431016077863595, c[0])
|
||||
c[1], c[0] = madd2(v, y[1], c[1], t[1])
|
||||
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[2], c[1], t[2])
|
||||
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[3], c[1], t[3])
|
||||
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[4], c[1], t[4])
|
||||
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[5], c[1], t[5])
|
||||
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
||||
}
|
||||
{
|
||||
// round 5
|
||||
v := x[5]
|
||||
c[1], c[0] = madd1(v, y[0], t[0])
|
||||
m := c[0] * 9940570264628428797
|
||||
c[2] = madd0(m, 13402431016077863595, c[0])
|
||||
c[1], c[0] = madd2(v, y[1], c[1], t[1])
|
||||
c[2], z[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[2], c[1], t[2])
|
||||
c[2], z[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[3], c[1], t[3])
|
||||
c[2], z[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[4], c[1], t[4])
|
||||
c[2], z[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
||||
c[1], c[0] = madd2(v, y[5], c[1], t[5])
|
||||
z[5], z[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
||||
}
|
||||
|
||||
// if z > q --> z -= q
|
||||
// note: this is NOT constant time
|
||||
if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
|
||||
var b uint64
|
||||
z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
|
||||
z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
|
||||
z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
|
||||
z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
|
||||
z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
|
||||
z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
|
||||
}
|
||||
}
|
||||
|
||||
func square(z, x *fe) {
|
||||
|
||||
var p [6]uint64
|
||||
|
||||
var u, v uint64
|
||||
{
|
||||
// round 0
|
||||
u, p[0] = bits.Mul64(x[0], x[0])
|
||||
m := p[0] * 9940570264628428797
|
||||
C := madd0(m, 13402431016077863595, p[0])
|
||||
var t uint64
|
||||
t, u, v = madd1sb(x[0], x[1], u)
|
||||
C, p[0] = madd2(m, 2210141511517208575, v, C)
|
||||
t, u, v = madd1s(x[0], x[2], t, u)
|
||||
C, p[1] = madd2(m, 7435674573564081700, v, C)
|
||||
t, u, v = madd1s(x[0], x[3], t, u)
|
||||
C, p[2] = madd2(m, 7239337960414712511, v, C)
|
||||
t, u, v = madd1s(x[0], x[4], t, u)
|
||||
C, p[3] = madd2(m, 5412103778470702295, v, C)
|
||||
_, u, v = madd1s(x[0], x[5], t, u)
|
||||
p[5], p[4] = madd3(m, 1873798617647539866, v, C, u)
|
||||
}
|
||||
{
|
||||
// round 1
|
||||
m := p[0] * 9940570264628428797
|
||||
C := madd0(m, 13402431016077863595, p[0])
|
||||
u, v = madd1(x[1], x[1], p[1])
|
||||
C, p[0] = madd2(m, 2210141511517208575, v, C)
|
||||
var t uint64
|
||||
t, u, v = madd2sb(x[1], x[2], p[2], u)
|
||||
C, p[1] = madd2(m, 7435674573564081700, v, C)
|
||||
t, u, v = madd2s(x[1], x[3], p[3], t, u)
|
||||
C, p[2] = madd2(m, 7239337960414712511, v, C)
|
||||
t, u, v = madd2s(x[1], x[4], p[4], t, u)
|
||||
C, p[3] = madd2(m, 5412103778470702295, v, C)
|
||||
_, u, v = madd2s(x[1], x[5], p[5], t, u)
|
||||
p[5], p[4] = madd3(m, 1873798617647539866, v, C, u)
|
||||
}
|
||||
{
|
||||
// round 2
|
||||
m := p[0] * 9940570264628428797
|
||||
C := madd0(m, 13402431016077863595, p[0])
|
||||
C, p[0] = madd2(m, 2210141511517208575, p[1], C)
|
||||
u, v = madd1(x[2], x[2], p[2])
|
||||
C, p[1] = madd2(m, 7435674573564081700, v, C)
|
||||
var t uint64
|
||||
t, u, v = madd2sb(x[2], x[3], p[3], u)
|
||||
C, p[2] = madd2(m, 7239337960414712511, v, C)
|
||||
t, u, v = madd2s(x[2], x[4], p[4], t, u)
|
||||
C, p[3] = madd2(m, 5412103778470702295, v, C)
|
||||
_, u, v = madd2s(x[2], x[5], p[5], t, u)
|
||||
p[5], p[4] = madd3(m, 1873798617647539866, v, C, u)
|
||||
}
|
||||
{
|
||||
// round 3
|
||||
m := p[0] * 9940570264628428797
|
||||
C := madd0(m, 13402431016077863595, p[0])
|
||||
C, p[0] = madd2(m, 2210141511517208575, p[1], C)
|
||||
C, p[1] = madd2(m, 7435674573564081700, p[2], C)
|
||||
u, v = madd1(x[3], x[3], p[3])
|
||||
C, p[2] = madd2(m, 7239337960414712511, v, C)
|
||||
var t uint64
|
||||
t, u, v = madd2sb(x[3], x[4], p[4], u)
|
||||
C, p[3] = madd2(m, 5412103778470702295, v, C)
|
||||
_, u, v = madd2s(x[3], x[5], p[5], t, u)
|
||||
p[5], p[4] = madd3(m, 1873798617647539866, v, C, u)
|
||||
}
|
||||
{
|
||||
// round 4
|
||||
m := p[0] * 9940570264628428797
|
||||
C := madd0(m, 13402431016077863595, p[0])
|
||||
C, p[0] = madd2(m, 2210141511517208575, p[1], C)
|
||||
C, p[1] = madd2(m, 7435674573564081700, p[2], C)
|
||||
C, p[2] = madd2(m, 7239337960414712511, p[3], C)
|
||||
u, v = madd1(x[4], x[4], p[4])
|
||||
C, p[3] = madd2(m, 5412103778470702295, v, C)
|
||||
_, u, v = madd2sb(x[4], x[5], p[5], u)
|
||||
p[5], p[4] = madd3(m, 1873798617647539866, v, C, u)
|
||||
}
|
||||
{
|
||||
// round 5
|
||||
m := p[0] * 9940570264628428797
|
||||
C := madd0(m, 13402431016077863595, p[0])
|
||||
C, z[0] = madd2(m, 2210141511517208575, p[1], C)
|
||||
C, z[1] = madd2(m, 7435674573564081700, p[2], C)
|
||||
C, z[2] = madd2(m, 7239337960414712511, p[3], C)
|
||||
C, z[3] = madd2(m, 5412103778470702295, p[4], C)
|
||||
u, v = madd1(x[5], x[5], p[5])
|
||||
z[5], z[4] = madd3(m, 1873798617647539866, v, C, u)
|
||||
}
|
||||
|
||||
// if z > q --> z -= q
|
||||
// note: this is NOT constant time
|
||||
if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
|
||||
var b uint64
|
||||
z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
|
||||
z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
|
||||
z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
|
||||
z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
|
||||
z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
|
||||
z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
|
||||
}
|
||||
}
|
||||
|
||||
// arith.go
|
||||
// Copyright 2020 ConsenSys AG
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Code generated by goff DO NOT EDIT
|
||||
|
||||
func madd(a, b, t, u, v uint64) (uint64, uint64, uint64) {
|
||||
var carry uint64
|
||||
hi, lo := bits.Mul64(a, b)
|
||||
v, carry = bits.Add64(lo, v, 0)
|
||||
u, carry = bits.Add64(hi, u, carry)
|
||||
t, _ = bits.Add64(t, 0, carry)
|
||||
return t, u, v
|
||||
}
|
||||
|
||||
// madd0 hi = a*b + c (discards lo bits)
|
||||
func madd0(a, b, c uint64) (hi uint64) {
|
||||
var carry, lo uint64
|
||||
hi, lo = bits.Mul64(a, b)
|
||||
_, carry = bits.Add64(lo, c, 0)
|
||||
hi, _ = bits.Add64(hi, 0, carry)
|
||||
return
|
||||
}
|
||||
|
||||
// madd1 hi, lo = a*b + c
|
||||
func madd1(a, b, c uint64) (hi uint64, lo uint64) {
|
||||
var carry uint64
|
||||
hi, lo = bits.Mul64(a, b)
|
||||
lo, carry = bits.Add64(lo, c, 0)
|
||||
hi, _ = bits.Add64(hi, 0, carry)
|
||||
return
|
||||
}
|
||||
|
||||
// madd2 hi, lo = a*b + c + d
|
||||
func madd2(a, b, c, d uint64) (hi uint64, lo uint64) {
|
||||
var carry uint64
|
||||
hi, lo = bits.Mul64(a, b)
|
||||
c, carry = bits.Add64(c, d, 0)
|
||||
hi, _ = bits.Add64(hi, 0, carry)
|
||||
lo, carry = bits.Add64(lo, c, 0)
|
||||
hi, _ = bits.Add64(hi, 0, carry)
|
||||
return
|
||||
}
|
||||
|
||||
// madd2s superhi, hi, lo = 2*a*b + c + d + e
|
||||
func madd2s(a, b, c, d, e uint64) (superhi, hi, lo uint64) {
|
||||
var carry, sum uint64
|
||||
|
||||
hi, lo = bits.Mul64(a, b)
|
||||
lo, carry = bits.Add64(lo, lo, 0)
|
||||
hi, superhi = bits.Add64(hi, hi, carry)
|
||||
|
||||
sum, carry = bits.Add64(c, e, 0)
|
||||
hi, _ = bits.Add64(hi, 0, carry)
|
||||
lo, carry = bits.Add64(lo, sum, 0)
|
||||
hi, _ = bits.Add64(hi, 0, carry)
|
||||
hi, _ = bits.Add64(hi, 0, d)
|
||||
return
|
||||
}
|
||||
|
||||
func madd1s(a, b, d, e uint64) (superhi, hi, lo uint64) {
|
||||
var carry uint64
|
||||
|
||||
hi, lo = bits.Mul64(a, b)
|
||||
lo, carry = bits.Add64(lo, lo, 0)
|
||||
hi, superhi = bits.Add64(hi, hi, carry)
|
||||
lo, carry = bits.Add64(lo, e, 0)
|
||||
hi, _ = bits.Add64(hi, 0, carry)
|
||||
hi, _ = bits.Add64(hi, 0, d)
|
||||
return
|
||||
}
|
||||
|
||||
func madd2sb(a, b, c, e uint64) (superhi, hi, lo uint64) {
|
||||
var carry, sum uint64
|
||||
|
||||
hi, lo = bits.Mul64(a, b)
|
||||
lo, carry = bits.Add64(lo, lo, 0)
|
||||
hi, superhi = bits.Add64(hi, hi, carry)
|
||||
|
||||
sum, carry = bits.Add64(c, e, 0)
|
||||
hi, _ = bits.Add64(hi, 0, carry)
|
||||
lo, carry = bits.Add64(lo, sum, 0)
|
||||
hi, _ = bits.Add64(hi, 0, carry)
|
||||
return
|
||||
}
|
||||
|
||||
func madd1sb(a, b, e uint64) (superhi, hi, lo uint64) {
|
||||
var carry uint64
|
||||
|
||||
hi, lo = bits.Mul64(a, b)
|
||||
lo, carry = bits.Add64(lo, lo, 0)
|
||||
hi, superhi = bits.Add64(hi, hi, carry)
|
||||
lo, carry = bits.Add64(lo, e, 0)
|
||||
hi, _ = bits.Add64(hi, 0, carry)
|
||||
return
|
||||
}
|
||||
|
||||
func madd3(a, b, c, d, e uint64) (hi uint64, lo uint64) {
|
||||
var carry uint64
|
||||
hi, lo = bits.Mul64(a, b)
|
||||
c, carry = bits.Add64(c, d, 0)
|
||||
hi, _ = bits.Add64(hi, 0, carry)
|
||||
lo, carry = bits.Add64(lo, c, 0)
|
||||
hi, _ = bits.Add64(hi, e, carry)
|
||||
return
|
||||
}
|
||||
2150
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/arithmetic_x86.s
generated
vendored
Normal file
2150
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/arithmetic_x86.s
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
25
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/arithmetic_x86_adx.go
generated
vendored
Normal file
25
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/arithmetic_x86_adx.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// 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/>.
|
||||
|
||||
//go:build amd64 && blsadx
|
||||
// +build amd64,blsadx
|
||||
|
||||
package bls12381
|
||||
|
||||
// enableADX is true if the ADX/BMI2 instruction set was requested for the BLS
|
||||
// implementation. The system may still fall back to plain ASM if the necessary
|
||||
// instructions are unavailable on the CPU.
|
||||
const enableADX = true
|
||||
25
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/arithmetic_x86_noadx.go
generated
vendored
Normal file
25
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/arithmetic_x86_noadx.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// 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/>.
|
||||
|
||||
//go:build amd64 && blsasm
|
||||
// +build amd64,blsasm
|
||||
|
||||
package bls12381
|
||||
|
||||
// enableADX is true if the ADX/BMI2 instruction set was requested for the BLS
|
||||
// implementation. The system may still fall back to plain ASM if the necessary
|
||||
// instructions are unavailable on the CPU.
|
||||
const enableADX = false
|
||||
230
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/bls12_381.go
generated
vendored
Normal file
230
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/bls12_381.go
generated
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
// 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
|
||||
|
||||
/*
|
||||
Field Constants
|
||||
*/
|
||||
|
||||
// Base field modulus
|
||||
// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
|
||||
|
||||
// Size of six words
|
||||
// r = 2 ^ 384
|
||||
|
||||
// modulus = p
|
||||
var modulus = fe{0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a}
|
||||
|
||||
var (
|
||||
// -p^(-1) mod 2^64
|
||||
inp uint64 = 0x89f3fffcfffcfffd
|
||||
// This value is used in assembly code
|
||||
_ = inp
|
||||
)
|
||||
|
||||
// r mod p
|
||||
var r1 = &fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}
|
||||
|
||||
// r^2 mod p
|
||||
var r2 = &fe{
|
||||
0xf4df1f341c341746, 0x0a76e6a609d104f1, 0x8de5476c4c95b6d5, 0x67eb88a9939d83c0, 0x9a793e85b519952d, 0x11988fe592cae3aa,
|
||||
}
|
||||
|
||||
// -1 + 0 * u
|
||||
var negativeOne2 = &fe2{
|
||||
fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
}
|
||||
|
||||
// 2 ^ (-1)
|
||||
var twoInv = &fe{0x1804000000015554, 0x855000053ab00001, 0x633cb57c253c276f, 0x6e22d1ec31ebb502, 0xd3916126f2d14ca2, 0x17fbb8571a006596}
|
||||
|
||||
// (p - 3) / 4
|
||||
var pMinus3Over4 = bigFromHex("0x680447a8e5ff9a692c6e9ed90d2eb35d91dd2e13ce144afd9cc34a83dac3d8907aaffffac54ffffee7fbfffffffeaaa")
|
||||
|
||||
// (p + 1) / 4
|
||||
var pPlus1Over4 = bigFromHex("0x680447a8e5ff9a692c6e9ed90d2eb35d91dd2e13ce144afd9cc34a83dac3d8907aaffffac54ffffee7fbfffffffeaab")
|
||||
|
||||
// (p - 1) / 2
|
||||
var pMinus1Over2 = bigFromHex("0xd0088f51cbff34d258dd3db21a5d66bb23ba5c279c2895fb39869507b587b120f55ffff58a9ffffdcff7fffffffd555")
|
||||
|
||||
// -1
|
||||
var nonResidue1 = &fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206}
|
||||
|
||||
// (1 + 1 * u)
|
||||
var nonResidue2 = &fe2{
|
||||
fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
|
||||
fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
|
||||
}
|
||||
|
||||
/*
|
||||
Curve Constants
|
||||
*/
|
||||
|
||||
// b coefficient for G1
|
||||
var b = &fe{0xaa270000000cfff3, 0x53cc0032fc34000a, 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, 0x8ec9733bbf78ab2f, 0x09d645513d83de7e}
|
||||
|
||||
// b coefficient for G2
|
||||
var b2 = &fe2{
|
||||
fe{0xaa270000000cfff3, 0x53cc0032fc34000a, 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, 0x8ec9733bbf78ab2f, 0x09d645513d83de7e},
|
||||
fe{0xaa270000000cfff3, 0x53cc0032fc34000a, 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, 0x8ec9733bbf78ab2f, 0x09d645513d83de7e},
|
||||
}
|
||||
|
||||
// Curve order
|
||||
var q = bigFromHex("0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001")
|
||||
|
||||
// Efficient cofactor of G1
|
||||
var cofactorEFFG1 = bigFromHex("0xd201000000010001")
|
||||
|
||||
// Efficient cofactor of G2
|
||||
var cofactorEFFG2 = bigFromHex("0x0bc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551")
|
||||
|
||||
var g1One = PointG1{
|
||||
fe{0x5cb38790fd530c16, 0x7817fc679976fff5, 0x154f95c7143ba1c1, 0xf0ae6acdf3d0e747, 0xedce6ecc21dbf440, 0x120177419e0bfb75},
|
||||
fe{0xbaac93d50ce72271, 0x8c22631a7918fd8e, 0xdd595f13570725ce, 0x51ac582950405194, 0x0e1c8c3fad0059c0, 0x0bbc3efc5008a26a},
|
||||
fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
|
||||
}
|
||||
|
||||
var g2One = PointG2{
|
||||
fe2{
|
||||
fe{0xf5f28fa202940a10, 0xb3f5fb2687b4961a, 0xa1a893b53e2ae580, 0x9894999d1a3caee9, 0x6f67b7631863366b, 0x058191924350bcd7},
|
||||
fe{0xa5a9c0759e23f606, 0xaaa0c59dbccd60c3, 0x3bb17e18e2867806, 0x1b1ab6cc8541b367, 0xc2b6ed0ef2158547, 0x11922a097360edf3},
|
||||
},
|
||||
fe2{
|
||||
fe{0x4c730af860494c4a, 0x597cfa1f5e369c5a, 0xe7e6856caa0a635a, 0xbbefb5e96e0d495f, 0x07d3a975f0ef25a2, 0x083fd8e7e80dae5},
|
||||
fe{0xadc0fc92df64b05d, 0x18aa270a2b1461dc, 0x86adac6a3be4eba0, 0x79495c4ec93da33a, 0xe7175850a43ccaed, 0xb2bc2a163de1bf2},
|
||||
},
|
||||
fe2{
|
||||
fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
}
|
||||
|
||||
/*
|
||||
Frobenious Coeffs
|
||||
*/
|
||||
|
||||
var frobeniusCoeffs61 = [6]fe2{
|
||||
{
|
||||
fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
{
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
fe{0xcd03c9e48671f071, 0x5dab22461fcda5d2, 0x587042afd3851b95, 0x8eb60ebe01bacb9e, 0x03f97d6e83d050d2, 0x18f0206554638741},
|
||||
},
|
||||
{
|
||||
fe{0x30f1361b798a64e8, 0xf3b8ddab7ece5a2a, 0x16a8ca3ac61577f7, 0xc26a2ff874fd029b, 0x3636b76660701c6e, 0x051ba4ab241b6160},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
{
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
|
||||
},
|
||||
{
|
||||
fe{0xcd03c9e48671f071, 0x5dab22461fcda5d2, 0x587042afd3851b95, 0x8eb60ebe01bacb9e, 0x03f97d6e83d050d2, 0x18f0206554638741},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
{
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
fe{0x30f1361b798a64e8, 0xf3b8ddab7ece5a2a, 0x16a8ca3ac61577f7, 0xc26a2ff874fd029b, 0x3636b76660701c6e, 0x051ba4ab241b6160},
|
||||
},
|
||||
}
|
||||
|
||||
var frobeniusCoeffs62 = [6]fe2{
|
||||
{
|
||||
fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
{
|
||||
fe{0x890dc9e4867545c3, 0x2af322533285a5d5, 0x50880866309b7e2c, 0xa20d1b8c7e881024, 0x14e4f04fe2db9068, 0x14e56d3f1564853a},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
{
|
||||
fe{0xcd03c9e48671f071, 0x5dab22461fcda5d2, 0x587042afd3851b95, 0x8eb60ebe01bacb9e, 0x03f97d6e83d050d2, 0x18f0206554638741},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
{
|
||||
fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
{
|
||||
fe{0x30f1361b798a64e8, 0xf3b8ddab7ece5a2a, 0x16a8ca3ac61577f7, 0xc26a2ff874fd029b, 0x3636b76660701c6e, 0x051ba4ab241b6160},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
{
|
||||
fe{0xecfb361b798dba3a, 0xc100ddb891865a2c, 0x0ec08ff1232bda8e, 0xd5c13cc6f1ca4721, 0x47222a47bf7b5c04, 0x0110f184e51c5f59},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
}
|
||||
|
||||
var frobeniusCoeffs12 = [12]fe2{
|
||||
{
|
||||
fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
{
|
||||
fe{0x07089552b319d465, 0xc6695f92b50a8313, 0x97e83cccd117228f, 0xa35baecab2dc29ee, 0x1ce393ea5daace4d, 0x08f2220fb0fb66eb},
|
||||
fe{0xb2f66aad4ce5d646, 0x5842a06bfc497cec, 0xcf4895d42599d394, 0xc11b9cba40a8e8d0, 0x2e3813cbe5a0de89, 0x110eefda88847faf},
|
||||
},
|
||||
{
|
||||
fe{0xecfb361b798dba3a, 0xc100ddb891865a2c, 0x0ec08ff1232bda8e, 0xd5c13cc6f1ca4721, 0x47222a47bf7b5c04, 0x0110f184e51c5f59},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
{
|
||||
fe{0x3e2f585da55c9ad1, 0x4294213d86c18183, 0x382844c88b623732, 0x92ad2afd19103e18, 0x1d794e4fac7cf0b9, 0x0bd592fc7d825ec8},
|
||||
fe{0x7bcfa7a25aa30fda, 0xdc17dec12a927e7c, 0x2f088dd86b4ebef1, 0xd1ca2087da74d4a7, 0x2da2596696cebc1d, 0x0e2b7eedbbfd87d2},
|
||||
},
|
||||
{
|
||||
fe{0x30f1361b798a64e8, 0xf3b8ddab7ece5a2a, 0x16a8ca3ac61577f7, 0xc26a2ff874fd029b, 0x3636b76660701c6e, 0x051ba4ab241b6160},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
{
|
||||
fe{0x3726c30af242c66c, 0x7c2ac1aad1b6fe70, 0xa04007fbba4b14a2, 0xef517c3266341429, 0x0095ba654ed2226b, 0x02e370eccc86f7dd},
|
||||
fe{0x82d83cf50dbce43f, 0xa2813e53df9d018f, 0xc6f0caa53c65e181, 0x7525cf528d50fe95, 0x4a85ed50f4798a6b, 0x171da0fd6cf8eebd},
|
||||
},
|
||||
{
|
||||
fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
{
|
||||
fe{0xb2f66aad4ce5d646, 0x5842a06bfc497cec, 0xcf4895d42599d394, 0xc11b9cba40a8e8d0, 0x2e3813cbe5a0de89, 0x110eefda88847faf},
|
||||
fe{0x07089552b319d465, 0xc6695f92b50a8313, 0x97e83cccd117228f, 0xa35baecab2dc29ee, 0x1ce393ea5daace4d, 0x08f2220fb0fb66eb},
|
||||
},
|
||||
{
|
||||
fe{0xcd03c9e48671f071, 0x5dab22461fcda5d2, 0x587042afd3851b95, 0x8eb60ebe01bacb9e, 0x03f97d6e83d050d2, 0x18f0206554638741},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
{
|
||||
fe{0x7bcfa7a25aa30fda, 0xdc17dec12a927e7c, 0x2f088dd86b4ebef1, 0xd1ca2087da74d4a7, 0x2da2596696cebc1d, 0x0e2b7eedbbfd87d2},
|
||||
fe{0x3e2f585da55c9ad1, 0x4294213d86c18183, 0x382844c88b623732, 0x92ad2afd19103e18, 0x1d794e4fac7cf0b9, 0x0bd592fc7d825ec8},
|
||||
},
|
||||
{
|
||||
fe{0x890dc9e4867545c3, 0x2af322533285a5d5, 0x50880866309b7e2c, 0xa20d1b8c7e881024, 0x14e4f04fe2db9068, 0x14e56d3f1564853a},
|
||||
fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
|
||||
},
|
||||
{
|
||||
fe{0x82d83cf50dbce43f, 0xa2813e53df9d018f, 0xc6f0caa53c65e181, 0x7525cf528d50fe95, 0x4a85ed50f4798a6b, 0x171da0fd6cf8eebd},
|
||||
fe{0x3726c30af242c66c, 0x7c2ac1aad1b6fe70, 0xa04007fbba4b14a2, 0xef517c3266341429, 0x0095ba654ed2226b, 0x02e370eccc86f7dd},
|
||||
},
|
||||
}
|
||||
|
||||
/*
|
||||
x
|
||||
*/
|
||||
|
||||
var x = bigFromHex("0xd201000000010000")
|
||||
340
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/field_element.go
generated
vendored
Normal file
340
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/field_element.go
generated
vendored
Normal file
@@ -0,0 +1,340 @@
|
||||
// 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 (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// fe is base field element representation
|
||||
type fe [6]uint64
|
||||
|
||||
// fe2 is element representation of 'fp2' which is quadratic extension of base field 'fp'
|
||||
// Representation follows c[0] + c[1] * u encoding order.
|
||||
type fe2 [2]fe
|
||||
|
||||
// fe6 is element representation of 'fp6' field which is cubic extension of 'fp2'
|
||||
// Representation follows c[0] + c[1] * v + c[2] * v^2 encoding order.
|
||||
type fe6 [3]fe2
|
||||
|
||||
// fe12 is element representation of 'fp12' field which is quadratic extension of 'fp6'
|
||||
// Representation follows c[0] + c[1] * w encoding order.
|
||||
type fe12 [2]fe6
|
||||
|
||||
func (fe *fe) setBytes(in []byte) *fe {
|
||||
size := 48
|
||||
l := len(in)
|
||||
if l >= size {
|
||||
l = size
|
||||
}
|
||||
padded := make([]byte, size)
|
||||
copy(padded[size-l:], in[:])
|
||||
var a int
|
||||
for i := 0; i < 6; i++ {
|
||||
a = size - i*8
|
||||
fe[i] = uint64(padded[a-1]) | uint64(padded[a-2])<<8 |
|
||||
uint64(padded[a-3])<<16 | uint64(padded[a-4])<<24 |
|
||||
uint64(padded[a-5])<<32 | uint64(padded[a-6])<<40 |
|
||||
uint64(padded[a-7])<<48 | uint64(padded[a-8])<<56
|
||||
}
|
||||
return fe
|
||||
}
|
||||
|
||||
func (fe *fe) setBig(a *big.Int) *fe {
|
||||
return fe.setBytes(a.Bytes())
|
||||
}
|
||||
|
||||
func (fe *fe) setString(s string) (*fe, error) {
|
||||
if s[:2] == "0x" {
|
||||
s = s[2:]
|
||||
}
|
||||
bytes, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fe.setBytes(bytes), nil
|
||||
}
|
||||
|
||||
func (fe *fe) set(fe2 *fe) *fe {
|
||||
fe[0] = fe2[0]
|
||||
fe[1] = fe2[1]
|
||||
fe[2] = fe2[2]
|
||||
fe[3] = fe2[3]
|
||||
fe[4] = fe2[4]
|
||||
fe[5] = fe2[5]
|
||||
return fe
|
||||
}
|
||||
|
||||
func (fe *fe) bytes() []byte {
|
||||
out := make([]byte, 48)
|
||||
var a int
|
||||
for i := 0; i < 6; i++ {
|
||||
a = 48 - i*8
|
||||
out[a-1] = byte(fe[i])
|
||||
out[a-2] = byte(fe[i] >> 8)
|
||||
out[a-3] = byte(fe[i] >> 16)
|
||||
out[a-4] = byte(fe[i] >> 24)
|
||||
out[a-5] = byte(fe[i] >> 32)
|
||||
out[a-6] = byte(fe[i] >> 40)
|
||||
out[a-7] = byte(fe[i] >> 48)
|
||||
out[a-8] = byte(fe[i] >> 56)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (fe *fe) big() *big.Int {
|
||||
return new(big.Int).SetBytes(fe.bytes())
|
||||
}
|
||||
|
||||
func (fe *fe) string() (s string) {
|
||||
for i := 5; i >= 0; i-- {
|
||||
s = fmt.Sprintf("%s%16.16x", s, fe[i])
|
||||
}
|
||||
return "0x" + s
|
||||
}
|
||||
|
||||
func (fe *fe) zero() *fe {
|
||||
fe[0] = 0
|
||||
fe[1] = 0
|
||||
fe[2] = 0
|
||||
fe[3] = 0
|
||||
fe[4] = 0
|
||||
fe[5] = 0
|
||||
return fe
|
||||
}
|
||||
|
||||
func (fe *fe) one() *fe {
|
||||
return fe.set(r1)
|
||||
}
|
||||
|
||||
func (fe *fe) rand(r io.Reader) (*fe, error) {
|
||||
bi, err := rand.Int(r, modulus.big())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fe.setBig(bi), nil
|
||||
}
|
||||
|
||||
func (fe *fe) isValid() bool {
|
||||
return fe.cmp(&modulus) < 0
|
||||
}
|
||||
|
||||
func (fe *fe) isOdd() bool {
|
||||
var mask uint64 = 1
|
||||
return fe[0]&mask != 0
|
||||
}
|
||||
|
||||
func (fe *fe) isEven() bool {
|
||||
var mask uint64 = 1
|
||||
return fe[0]&mask == 0
|
||||
}
|
||||
|
||||
func (fe *fe) isZero() bool {
|
||||
return (fe[5] | fe[4] | fe[3] | fe[2] | fe[1] | fe[0]) == 0
|
||||
}
|
||||
|
||||
func (fe *fe) isOne() bool {
|
||||
return fe.equal(r1)
|
||||
}
|
||||
|
||||
func (fe *fe) cmp(fe2 *fe) int {
|
||||
for i := 5; i >= 0; i-- {
|
||||
if fe[i] > fe2[i] {
|
||||
return 1
|
||||
} else if fe[i] < fe2[i] {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (fe *fe) equal(fe2 *fe) bool {
|
||||
return fe2[0] == fe[0] && fe2[1] == fe[1] && fe2[2] == fe[2] && fe2[3] == fe[3] && fe2[4] == fe[4] && fe2[5] == fe[5]
|
||||
}
|
||||
|
||||
func (e *fe) sign() bool {
|
||||
r := new(fe)
|
||||
fromMont(r, e)
|
||||
return r[0]&1 == 0
|
||||
}
|
||||
|
||||
func (fe *fe) div2(e uint64) {
|
||||
fe[0] = fe[0]>>1 | fe[1]<<63
|
||||
fe[1] = fe[1]>>1 | fe[2]<<63
|
||||
fe[2] = fe[2]>>1 | fe[3]<<63
|
||||
fe[3] = fe[3]>>1 | fe[4]<<63
|
||||
fe[4] = fe[4]>>1 | fe[5]<<63
|
||||
fe[5] = fe[5]>>1 | e<<63
|
||||
}
|
||||
|
||||
func (fe *fe) mul2() uint64 {
|
||||
e := fe[5] >> 63
|
||||
fe[5] = fe[5]<<1 | fe[4]>>63
|
||||
fe[4] = fe[4]<<1 | fe[3]>>63
|
||||
fe[3] = fe[3]<<1 | fe[2]>>63
|
||||
fe[2] = fe[2]<<1 | fe[1]>>63
|
||||
fe[1] = fe[1]<<1 | fe[0]>>63
|
||||
fe[0] = fe[0] << 1
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *fe2) zero() *fe2 {
|
||||
e[0].zero()
|
||||
e[1].zero()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *fe2) one() *fe2 {
|
||||
e[0].one()
|
||||
e[1].zero()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *fe2) set(e2 *fe2) *fe2 {
|
||||
e[0].set(&e2[0])
|
||||
e[1].set(&e2[1])
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *fe2) rand(r io.Reader) (*fe2, error) {
|
||||
a0, err := new(fe).rand(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a1, err := new(fe).rand(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fe2{*a0, *a1}, nil
|
||||
}
|
||||
|
||||
func (e *fe2) isOne() bool {
|
||||
return e[0].isOne() && e[1].isZero()
|
||||
}
|
||||
|
||||
func (e *fe2) isZero() bool {
|
||||
return e[0].isZero() && e[1].isZero()
|
||||
}
|
||||
|
||||
func (e *fe2) equal(e2 *fe2) bool {
|
||||
return e[0].equal(&e2[0]) && e[1].equal(&e2[1])
|
||||
}
|
||||
|
||||
func (e *fe2) sign() bool {
|
||||
r := new(fe)
|
||||
if !e[0].isZero() {
|
||||
fromMont(r, &e[0])
|
||||
return r[0]&1 == 0
|
||||
}
|
||||
fromMont(r, &e[1])
|
||||
return r[0]&1 == 0
|
||||
}
|
||||
|
||||
func (e *fe6) zero() *fe6 {
|
||||
e[0].zero()
|
||||
e[1].zero()
|
||||
e[2].zero()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *fe6) one() *fe6 {
|
||||
e[0].one()
|
||||
e[1].zero()
|
||||
e[2].zero()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *fe6) set(e2 *fe6) *fe6 {
|
||||
e[0].set(&e2[0])
|
||||
e[1].set(&e2[1])
|
||||
e[2].set(&e2[2])
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *fe6) rand(r io.Reader) (*fe6, error) {
|
||||
a0, err := new(fe2).rand(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a1, err := new(fe2).rand(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a2, err := new(fe2).rand(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fe6{*a0, *a1, *a2}, nil
|
||||
}
|
||||
|
||||
func (e *fe6) isOne() bool {
|
||||
return e[0].isOne() && e[1].isZero() && e[2].isZero()
|
||||
}
|
||||
|
||||
func (e *fe6) isZero() bool {
|
||||
return e[0].isZero() && e[1].isZero() && e[2].isZero()
|
||||
}
|
||||
|
||||
func (e *fe6) equal(e2 *fe6) bool {
|
||||
return e[0].equal(&e2[0]) && e[1].equal(&e2[1]) && e[2].equal(&e2[2])
|
||||
}
|
||||
|
||||
func (e *fe12) zero() *fe12 {
|
||||
e[0].zero()
|
||||
e[1].zero()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *fe12) one() *fe12 {
|
||||
e[0].one()
|
||||
e[1].zero()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *fe12) set(e2 *fe12) *fe12 {
|
||||
e[0].set(&e2[0])
|
||||
e[1].set(&e2[1])
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *fe12) rand(r io.Reader) (*fe12, error) {
|
||||
a0, err := new(fe6).rand(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a1, err := new(fe6).rand(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fe12{*a0, *a1}, nil
|
||||
}
|
||||
|
||||
func (e *fe12) isOne() bool {
|
||||
return e[0].isOne() && e[1].isZero()
|
||||
}
|
||||
|
||||
func (e *fe12) isZero() bool {
|
||||
return e[0].isZero() && e[1].isZero()
|
||||
}
|
||||
|
||||
func (e *fe12) equal(e2 *fe12) bool {
|
||||
return e[0].equal(&e2[0]) && e[1].equal(&e2[1])
|
||||
}
|
||||
167
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/fp.go
generated
vendored
Normal file
167
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/fp.go
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
// 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()
|
||||
}
|
||||
277
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/fp12.go
generated
vendored
Normal file
277
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/fp12.go
generated
vendored
Normal file
@@ -0,0 +1,277 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
type fp12 struct {
|
||||
fp12temp
|
||||
fp6 *fp6
|
||||
}
|
||||
|
||||
type fp12temp struct {
|
||||
t2 [9]*fe2
|
||||
t6 [5]*fe6
|
||||
t12 *fe12
|
||||
}
|
||||
|
||||
func newFp12Temp() fp12temp {
|
||||
t2 := [9]*fe2{}
|
||||
t6 := [5]*fe6{}
|
||||
for i := 0; i < len(t2); i++ {
|
||||
t2[i] = &fe2{}
|
||||
}
|
||||
for i := 0; i < len(t6); i++ {
|
||||
t6[i] = &fe6{}
|
||||
}
|
||||
return fp12temp{t2, t6, &fe12{}}
|
||||
}
|
||||
|
||||
func newFp12(fp6 *fp6) *fp12 {
|
||||
t := newFp12Temp()
|
||||
if fp6 == nil {
|
||||
return &fp12{t, newFp6(nil)}
|
||||
}
|
||||
return &fp12{t, fp6}
|
||||
}
|
||||
|
||||
func (e *fp12) fp2() *fp2 {
|
||||
return e.fp6.fp2
|
||||
}
|
||||
|
||||
func (e *fp12) fromBytes(in []byte) (*fe12, error) {
|
||||
if len(in) != 576 {
|
||||
return nil, errors.New("input string should be larger than 96 bytes")
|
||||
}
|
||||
fp6 := e.fp6
|
||||
c1, err := fp6.fromBytes(in[:288])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c0, err := fp6.fromBytes(in[288:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fe12{*c0, *c1}, nil
|
||||
}
|
||||
|
||||
func (e *fp12) toBytes(a *fe12) []byte {
|
||||
fp6 := e.fp6
|
||||
out := make([]byte, 576)
|
||||
copy(out[:288], fp6.toBytes(&a[1]))
|
||||
copy(out[288:], fp6.toBytes(&a[0]))
|
||||
return out
|
||||
}
|
||||
|
||||
func (e *fp12) new() *fe12 {
|
||||
return new(fe12)
|
||||
}
|
||||
|
||||
func (e *fp12) zero() *fe12 {
|
||||
return new(fe12)
|
||||
}
|
||||
|
||||
func (e *fp12) one() *fe12 {
|
||||
return new(fe12).one()
|
||||
}
|
||||
|
||||
func (e *fp12) add(c, a, b *fe12) {
|
||||
fp6 := e.fp6
|
||||
fp6.add(&c[0], &a[0], &b[0])
|
||||
fp6.add(&c[1], &a[1], &b[1])
|
||||
}
|
||||
|
||||
func (e *fp12) double(c, a *fe12) {
|
||||
fp6 := e.fp6
|
||||
fp6.double(&c[0], &a[0])
|
||||
fp6.double(&c[1], &a[1])
|
||||
}
|
||||
|
||||
func (e *fp12) sub(c, a, b *fe12) {
|
||||
fp6 := e.fp6
|
||||
fp6.sub(&c[0], &a[0], &b[0])
|
||||
fp6.sub(&c[1], &a[1], &b[1])
|
||||
}
|
||||
|
||||
func (e *fp12) neg(c, a *fe12) {
|
||||
fp6 := e.fp6
|
||||
fp6.neg(&c[0], &a[0])
|
||||
fp6.neg(&c[1], &a[1])
|
||||
}
|
||||
|
||||
func (e *fp12) conjugate(c, a *fe12) {
|
||||
fp6 := e.fp6
|
||||
c[0].set(&a[0])
|
||||
fp6.neg(&c[1], &a[1])
|
||||
}
|
||||
|
||||
func (e *fp12) square(c, a *fe12) {
|
||||
fp6, t := e.fp6, e.t6
|
||||
fp6.add(t[0], &a[0], &a[1])
|
||||
fp6.mul(t[2], &a[0], &a[1])
|
||||
fp6.mulByNonResidue(t[1], &a[1])
|
||||
fp6.addAssign(t[1], &a[0])
|
||||
fp6.mulByNonResidue(t[3], t[2])
|
||||
fp6.mulAssign(t[0], t[1])
|
||||
fp6.subAssign(t[0], t[2])
|
||||
fp6.sub(&c[0], t[0], t[3])
|
||||
fp6.double(&c[1], t[2])
|
||||
}
|
||||
|
||||
func (e *fp12) cyclotomicSquare(c, a *fe12) {
|
||||
t, fp2 := e.t2, e.fp2()
|
||||
e.fp4Square(t[3], t[4], &a[0][0], &a[1][1])
|
||||
fp2.sub(t[2], t[3], &a[0][0])
|
||||
fp2.doubleAssign(t[2])
|
||||
fp2.add(&c[0][0], t[2], t[3])
|
||||
fp2.add(t[2], t[4], &a[1][1])
|
||||
fp2.doubleAssign(t[2])
|
||||
fp2.add(&c[1][1], t[2], t[4])
|
||||
e.fp4Square(t[3], t[4], &a[1][0], &a[0][2])
|
||||
e.fp4Square(t[5], t[6], &a[0][1], &a[1][2])
|
||||
fp2.sub(t[2], t[3], &a[0][1])
|
||||
fp2.doubleAssign(t[2])
|
||||
fp2.add(&c[0][1], t[2], t[3])
|
||||
fp2.add(t[2], t[4], &a[1][2])
|
||||
fp2.doubleAssign(t[2])
|
||||
fp2.add(&c[1][2], t[2], t[4])
|
||||
fp2.mulByNonResidue(t[3], t[6])
|
||||
fp2.add(t[2], t[3], &a[1][0])
|
||||
fp2.doubleAssign(t[2])
|
||||
fp2.add(&c[1][0], t[2], t[3])
|
||||
fp2.sub(t[2], t[5], &a[0][2])
|
||||
fp2.doubleAssign(t[2])
|
||||
fp2.add(&c[0][2], t[2], t[5])
|
||||
}
|
||||
|
||||
func (e *fp12) mul(c, a, b *fe12) {
|
||||
t, fp6 := e.t6, e.fp6
|
||||
fp6.mul(t[1], &a[0], &b[0])
|
||||
fp6.mul(t[2], &a[1], &b[1])
|
||||
fp6.add(t[0], t[1], t[2])
|
||||
fp6.mulByNonResidue(t[2], t[2])
|
||||
fp6.add(t[3], t[1], t[2])
|
||||
fp6.add(t[1], &a[0], &a[1])
|
||||
fp6.add(t[2], &b[0], &b[1])
|
||||
fp6.mulAssign(t[1], t[2])
|
||||
c[0].set(t[3])
|
||||
fp6.sub(&c[1], t[1], t[0])
|
||||
}
|
||||
|
||||
func (e *fp12) mulAssign(a, b *fe12) {
|
||||
t, fp6 := e.t6, e.fp6
|
||||
fp6.mul(t[1], &a[0], &b[0])
|
||||
fp6.mul(t[2], &a[1], &b[1])
|
||||
fp6.add(t[0], t[1], t[2])
|
||||
fp6.mulByNonResidue(t[2], t[2])
|
||||
fp6.add(t[3], t[1], t[2])
|
||||
fp6.add(t[1], &a[0], &a[1])
|
||||
fp6.add(t[2], &b[0], &b[1])
|
||||
fp6.mulAssign(t[1], t[2])
|
||||
a[0].set(t[3])
|
||||
fp6.sub(&a[1], t[1], t[0])
|
||||
}
|
||||
|
||||
func (e *fp12) fp4Square(c0, c1, a0, a1 *fe2) {
|
||||
t, fp2 := e.t2, e.fp2()
|
||||
fp2.square(t[0], a0)
|
||||
fp2.square(t[1], a1)
|
||||
fp2.mulByNonResidue(t[2], t[1])
|
||||
fp2.add(c0, t[2], t[0])
|
||||
fp2.add(t[2], a0, a1)
|
||||
fp2.squareAssign(t[2])
|
||||
fp2.subAssign(t[2], t[0])
|
||||
fp2.sub(c1, t[2], t[1])
|
||||
}
|
||||
|
||||
func (e *fp12) inverse(c, a *fe12) {
|
||||
fp6, t := e.fp6, e.t6
|
||||
fp6.square(t[0], &a[0])
|
||||
fp6.square(t[1], &a[1])
|
||||
fp6.mulByNonResidue(t[1], t[1])
|
||||
fp6.sub(t[1], t[0], t[1])
|
||||
fp6.inverse(t[0], t[1])
|
||||
fp6.mul(&c[0], &a[0], t[0])
|
||||
fp6.mulAssign(t[0], &a[1])
|
||||
fp6.neg(&c[1], t[0])
|
||||
}
|
||||
|
||||
func (e *fp12) mulBy014Assign(a *fe12, c0, c1, c4 *fe2) {
|
||||
fp2, fp6, t, t2 := e.fp2(), e.fp6, e.t6, e.t2[0]
|
||||
fp6.mulBy01(t[0], &a[0], c0, c1)
|
||||
fp6.mulBy1(t[1], &a[1], c4)
|
||||
fp2.add(t2, c1, c4)
|
||||
fp6.add(t[2], &a[1], &a[0])
|
||||
fp6.mulBy01Assign(t[2], c0, t2)
|
||||
fp6.subAssign(t[2], t[0])
|
||||
fp6.sub(&a[1], t[2], t[1])
|
||||
fp6.mulByNonResidue(t[1], t[1])
|
||||
fp6.add(&a[0], t[1], t[0])
|
||||
}
|
||||
|
||||
func (e *fp12) exp(c, a *fe12, s *big.Int) {
|
||||
z := e.one()
|
||||
for i := s.BitLen() - 1; i >= 0; i-- {
|
||||
e.square(z, z)
|
||||
if s.Bit(i) == 1 {
|
||||
e.mul(z, z, a)
|
||||
}
|
||||
}
|
||||
c.set(z)
|
||||
}
|
||||
|
||||
func (e *fp12) cyclotomicExp(c, a *fe12, s *big.Int) {
|
||||
z := e.one()
|
||||
for i := s.BitLen() - 1; i >= 0; i-- {
|
||||
e.cyclotomicSquare(z, z)
|
||||
if s.Bit(i) == 1 {
|
||||
e.mul(z, z, a)
|
||||
}
|
||||
}
|
||||
c.set(z)
|
||||
}
|
||||
|
||||
func (e *fp12) frobeniusMap(c, a *fe12, power uint) {
|
||||
fp6 := e.fp6
|
||||
fp6.frobeniusMap(&c[0], &a[0], power)
|
||||
fp6.frobeniusMap(&c[1], &a[1], power)
|
||||
switch power {
|
||||
case 0:
|
||||
return
|
||||
case 6:
|
||||
fp6.neg(&c[1], &c[1])
|
||||
default:
|
||||
fp6.mulByBaseField(&c[1], &c[1], &frobeniusCoeffs12[power])
|
||||
}
|
||||
}
|
||||
|
||||
func (e *fp12) frobeniusMapAssign(a *fe12, power uint) {
|
||||
fp6 := e.fp6
|
||||
fp6.frobeniusMapAssign(&a[0], power)
|
||||
fp6.frobeniusMapAssign(&a[1], power)
|
||||
switch power {
|
||||
case 0:
|
||||
return
|
||||
case 6:
|
||||
fp6.neg(&a[1], &a[1])
|
||||
default:
|
||||
fp6.mulByBaseField(&a[1], &a[1], &frobeniusCoeffs12[power])
|
||||
}
|
||||
}
|
||||
252
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/fp2.go
generated
vendored
Normal file
252
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/fp2.go
generated
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
type fp2Temp struct {
|
||||
t [4]*fe
|
||||
}
|
||||
|
||||
type fp2 struct {
|
||||
fp2Temp
|
||||
}
|
||||
|
||||
func newFp2Temp() fp2Temp {
|
||||
t := [4]*fe{}
|
||||
for i := 0; i < len(t); i++ {
|
||||
t[i] = &fe{}
|
||||
}
|
||||
return fp2Temp{t}
|
||||
}
|
||||
|
||||
func newFp2() *fp2 {
|
||||
t := newFp2Temp()
|
||||
return &fp2{t}
|
||||
}
|
||||
|
||||
func (e *fp2) fromBytes(in []byte) (*fe2, error) {
|
||||
if len(in) != 96 {
|
||||
return nil, errors.New("length of input string should be 96 bytes")
|
||||
}
|
||||
c1, err := fromBytes(in[:48])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c0, err := fromBytes(in[48:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fe2{*c0, *c1}, nil
|
||||
}
|
||||
|
||||
func (e *fp2) toBytes(a *fe2) []byte {
|
||||
out := make([]byte, 96)
|
||||
copy(out[:48], toBytes(&a[1]))
|
||||
copy(out[48:], toBytes(&a[0]))
|
||||
return out
|
||||
}
|
||||
|
||||
func (e *fp2) new() *fe2 {
|
||||
return new(fe2).zero()
|
||||
}
|
||||
|
||||
func (e *fp2) zero() *fe2 {
|
||||
return new(fe2).zero()
|
||||
}
|
||||
|
||||
func (e *fp2) one() *fe2 {
|
||||
return new(fe2).one()
|
||||
}
|
||||
|
||||
func (e *fp2) add(c, a, b *fe2) {
|
||||
add(&c[0], &a[0], &b[0])
|
||||
add(&c[1], &a[1], &b[1])
|
||||
}
|
||||
|
||||
func (e *fp2) addAssign(a, b *fe2) {
|
||||
addAssign(&a[0], &b[0])
|
||||
addAssign(&a[1], &b[1])
|
||||
}
|
||||
|
||||
func (e *fp2) ladd(c, a, b *fe2) {
|
||||
ladd(&c[0], &a[0], &b[0])
|
||||
ladd(&c[1], &a[1], &b[1])
|
||||
}
|
||||
|
||||
func (e *fp2) double(c, a *fe2) {
|
||||
double(&c[0], &a[0])
|
||||
double(&c[1], &a[1])
|
||||
}
|
||||
|
||||
func (e *fp2) doubleAssign(a *fe2) {
|
||||
doubleAssign(&a[0])
|
||||
doubleAssign(&a[1])
|
||||
}
|
||||
|
||||
func (e *fp2) ldouble(c, a *fe2) {
|
||||
ldouble(&c[0], &a[0])
|
||||
ldouble(&c[1], &a[1])
|
||||
}
|
||||
|
||||
func (e *fp2) sub(c, a, b *fe2) {
|
||||
sub(&c[0], &a[0], &b[0])
|
||||
sub(&c[1], &a[1], &b[1])
|
||||
}
|
||||
|
||||
func (e *fp2) subAssign(c, a *fe2) {
|
||||
subAssign(&c[0], &a[0])
|
||||
subAssign(&c[1], &a[1])
|
||||
}
|
||||
|
||||
func (e *fp2) neg(c, a *fe2) {
|
||||
neg(&c[0], &a[0])
|
||||
neg(&c[1], &a[1])
|
||||
}
|
||||
|
||||
func (e *fp2) mul(c, a, b *fe2) {
|
||||
t := e.t
|
||||
mul(t[1], &a[0], &b[0])
|
||||
mul(t[2], &a[1], &b[1])
|
||||
add(t[0], &a[0], &a[1])
|
||||
add(t[3], &b[0], &b[1])
|
||||
sub(&c[0], t[1], t[2])
|
||||
addAssign(t[1], t[2])
|
||||
mul(t[0], t[0], t[3])
|
||||
sub(&c[1], t[0], t[1])
|
||||
}
|
||||
|
||||
func (e *fp2) mulAssign(a, b *fe2) {
|
||||
t := e.t
|
||||
mul(t[1], &a[0], &b[0])
|
||||
mul(t[2], &a[1], &b[1])
|
||||
add(t[0], &a[0], &a[1])
|
||||
add(t[3], &b[0], &b[1])
|
||||
sub(&a[0], t[1], t[2])
|
||||
addAssign(t[1], t[2])
|
||||
mul(t[0], t[0], t[3])
|
||||
sub(&a[1], t[0], t[1])
|
||||
}
|
||||
|
||||
func (e *fp2) square(c, a *fe2) {
|
||||
t := e.t
|
||||
ladd(t[0], &a[0], &a[1])
|
||||
sub(t[1], &a[0], &a[1])
|
||||
ldouble(t[2], &a[0])
|
||||
mul(&c[0], t[0], t[1])
|
||||
mul(&c[1], t[2], &a[1])
|
||||
}
|
||||
|
||||
func (e *fp2) squareAssign(a *fe2) {
|
||||
t := e.t
|
||||
ladd(t[0], &a[0], &a[1])
|
||||
sub(t[1], &a[0], &a[1])
|
||||
ldouble(t[2], &a[0])
|
||||
mul(&a[0], t[0], t[1])
|
||||
mul(&a[1], t[2], &a[1])
|
||||
}
|
||||
|
||||
func (e *fp2) mulByNonResidue(c, a *fe2) {
|
||||
t := e.t
|
||||
sub(t[0], &a[0], &a[1])
|
||||
add(&c[1], &a[0], &a[1])
|
||||
c[0].set(t[0])
|
||||
}
|
||||
|
||||
func (e *fp2) mulByB(c, a *fe2) {
|
||||
t := e.t
|
||||
double(t[0], &a[0])
|
||||
double(t[1], &a[1])
|
||||
doubleAssign(t[0])
|
||||
doubleAssign(t[1])
|
||||
sub(&c[0], t[0], t[1])
|
||||
add(&c[1], t[0], t[1])
|
||||
}
|
||||
|
||||
func (e *fp2) inverse(c, a *fe2) {
|
||||
t := e.t
|
||||
square(t[0], &a[0])
|
||||
square(t[1], &a[1])
|
||||
addAssign(t[0], t[1])
|
||||
inverse(t[0], t[0])
|
||||
mul(&c[0], &a[0], t[0])
|
||||
mul(t[0], t[0], &a[1])
|
||||
neg(&c[1], t[0])
|
||||
}
|
||||
|
||||
func (e *fp2) mulByFq(c, a *fe2, b *fe) {
|
||||
mul(&c[0], &a[0], b)
|
||||
mul(&c[1], &a[1], b)
|
||||
}
|
||||
|
||||
func (e *fp2) exp(c, a *fe2, s *big.Int) {
|
||||
z := e.one()
|
||||
for i := s.BitLen() - 1; i >= 0; i-- {
|
||||
e.square(z, z)
|
||||
if s.Bit(i) == 1 {
|
||||
e.mul(z, z, a)
|
||||
}
|
||||
}
|
||||
c.set(z)
|
||||
}
|
||||
|
||||
func (e *fp2) frobeniusMap(c, a *fe2, power uint) {
|
||||
c[0].set(&a[0])
|
||||
if power%2 == 1 {
|
||||
neg(&c[1], &a[1])
|
||||
return
|
||||
}
|
||||
c[1].set(&a[1])
|
||||
}
|
||||
|
||||
func (e *fp2) frobeniusMapAssign(a *fe2, power uint) {
|
||||
if power%2 == 1 {
|
||||
neg(&a[1], &a[1])
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (e *fp2) sqrt(c, a *fe2) bool {
|
||||
u, x0, a1, alpha := &fe2{}, &fe2{}, &fe2{}, &fe2{}
|
||||
u.set(a)
|
||||
e.exp(a1, a, pMinus3Over4)
|
||||
e.square(alpha, a1)
|
||||
e.mul(alpha, alpha, a)
|
||||
e.mul(x0, a1, a)
|
||||
if alpha.equal(negativeOne2) {
|
||||
neg(&c[0], &x0[1])
|
||||
c[1].set(&x0[0])
|
||||
return true
|
||||
}
|
||||
e.add(alpha, alpha, e.one())
|
||||
e.exp(alpha, alpha, pMinus1Over2)
|
||||
e.mul(c, alpha, x0)
|
||||
e.square(alpha, c)
|
||||
return alpha.equal(u)
|
||||
}
|
||||
|
||||
func (e *fp2) isQuadraticNonResidue(a *fe2) bool {
|
||||
// https://github.com/leovt/constructible/wiki/Taking-Square-Roots-in-quadratic-extension-Fields
|
||||
c0, c1 := new(fe), new(fe)
|
||||
square(c0, &a[0])
|
||||
square(c1, &a[1])
|
||||
add(c1, c1, c0)
|
||||
return isQuadraticNonResidue(c1)
|
||||
}
|
||||
351
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/fp6.go
generated
vendored
Normal file
351
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/fp6.go
generated
vendored
Normal file
@@ -0,0 +1,351 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
type fp6Temp struct {
|
||||
t [6]*fe2
|
||||
}
|
||||
|
||||
type fp6 struct {
|
||||
fp2 *fp2
|
||||
fp6Temp
|
||||
}
|
||||
|
||||
func newFp6Temp() fp6Temp {
|
||||
t := [6]*fe2{}
|
||||
for i := 0; i < len(t); i++ {
|
||||
t[i] = &fe2{}
|
||||
}
|
||||
return fp6Temp{t}
|
||||
}
|
||||
|
||||
func newFp6(f *fp2) *fp6 {
|
||||
t := newFp6Temp()
|
||||
if f == nil {
|
||||
return &fp6{newFp2(), t}
|
||||
}
|
||||
return &fp6{f, t}
|
||||
}
|
||||
|
||||
func (e *fp6) fromBytes(b []byte) (*fe6, error) {
|
||||
if len(b) < 288 {
|
||||
return nil, errors.New("input string should be larger than 288 bytes")
|
||||
}
|
||||
fp2 := e.fp2
|
||||
u2, err := fp2.fromBytes(b[:96])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
u1, err := fp2.fromBytes(b[96:192])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
u0, err := fp2.fromBytes(b[192:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fe6{*u0, *u1, *u2}, nil
|
||||
}
|
||||
|
||||
func (e *fp6) toBytes(a *fe6) []byte {
|
||||
fp2 := e.fp2
|
||||
out := make([]byte, 288)
|
||||
copy(out[:96], fp2.toBytes(&a[2]))
|
||||
copy(out[96:192], fp2.toBytes(&a[1]))
|
||||
copy(out[192:], fp2.toBytes(&a[0]))
|
||||
return out
|
||||
}
|
||||
|
||||
func (e *fp6) new() *fe6 {
|
||||
return new(fe6)
|
||||
}
|
||||
|
||||
func (e *fp6) zero() *fe6 {
|
||||
return new(fe6)
|
||||
}
|
||||
|
||||
func (e *fp6) one() *fe6 {
|
||||
return new(fe6).one()
|
||||
}
|
||||
|
||||
func (e *fp6) add(c, a, b *fe6) {
|
||||
fp2 := e.fp2
|
||||
fp2.add(&c[0], &a[0], &b[0])
|
||||
fp2.add(&c[1], &a[1], &b[1])
|
||||
fp2.add(&c[2], &a[2], &b[2])
|
||||
}
|
||||
|
||||
func (e *fp6) addAssign(a, b *fe6) {
|
||||
fp2 := e.fp2
|
||||
fp2.addAssign(&a[0], &b[0])
|
||||
fp2.addAssign(&a[1], &b[1])
|
||||
fp2.addAssign(&a[2], &b[2])
|
||||
}
|
||||
|
||||
func (e *fp6) double(c, a *fe6) {
|
||||
fp2 := e.fp2
|
||||
fp2.double(&c[0], &a[0])
|
||||
fp2.double(&c[1], &a[1])
|
||||
fp2.double(&c[2], &a[2])
|
||||
}
|
||||
|
||||
func (e *fp6) doubleAssign(a *fe6) {
|
||||
fp2 := e.fp2
|
||||
fp2.doubleAssign(&a[0])
|
||||
fp2.doubleAssign(&a[1])
|
||||
fp2.doubleAssign(&a[2])
|
||||
}
|
||||
|
||||
func (e *fp6) sub(c, a, b *fe6) {
|
||||
fp2 := e.fp2
|
||||
fp2.sub(&c[0], &a[0], &b[0])
|
||||
fp2.sub(&c[1], &a[1], &b[1])
|
||||
fp2.sub(&c[2], &a[2], &b[2])
|
||||
}
|
||||
|
||||
func (e *fp6) subAssign(a, b *fe6) {
|
||||
fp2 := e.fp2
|
||||
fp2.subAssign(&a[0], &b[0])
|
||||
fp2.subAssign(&a[1], &b[1])
|
||||
fp2.subAssign(&a[2], &b[2])
|
||||
}
|
||||
|
||||
func (e *fp6) neg(c, a *fe6) {
|
||||
fp2 := e.fp2
|
||||
fp2.neg(&c[0], &a[0])
|
||||
fp2.neg(&c[1], &a[1])
|
||||
fp2.neg(&c[2], &a[2])
|
||||
}
|
||||
|
||||
func (e *fp6) mul(c, a, b *fe6) {
|
||||
fp2, t := e.fp2, e.t
|
||||
fp2.mul(t[0], &a[0], &b[0])
|
||||
fp2.mul(t[1], &a[1], &b[1])
|
||||
fp2.mul(t[2], &a[2], &b[2])
|
||||
fp2.add(t[3], &a[1], &a[2])
|
||||
fp2.add(t[4], &b[1], &b[2])
|
||||
fp2.mulAssign(t[3], t[4])
|
||||
fp2.add(t[4], t[1], t[2])
|
||||
fp2.subAssign(t[3], t[4])
|
||||
fp2.mulByNonResidue(t[3], t[3])
|
||||
fp2.add(t[5], t[0], t[3])
|
||||
fp2.add(t[3], &a[0], &a[1])
|
||||
fp2.add(t[4], &b[0], &b[1])
|
||||
fp2.mulAssign(t[3], t[4])
|
||||
fp2.add(t[4], t[0], t[1])
|
||||
fp2.subAssign(t[3], t[4])
|
||||
fp2.mulByNonResidue(t[4], t[2])
|
||||
fp2.add(&c[1], t[3], t[4])
|
||||
fp2.add(t[3], &a[0], &a[2])
|
||||
fp2.add(t[4], &b[0], &b[2])
|
||||
fp2.mulAssign(t[3], t[4])
|
||||
fp2.add(t[4], t[0], t[2])
|
||||
fp2.subAssign(t[3], t[4])
|
||||
fp2.add(&c[2], t[1], t[3])
|
||||
c[0].set(t[5])
|
||||
}
|
||||
|
||||
func (e *fp6) mulAssign(a, b *fe6) {
|
||||
fp2, t := e.fp2, e.t
|
||||
fp2.mul(t[0], &a[0], &b[0])
|
||||
fp2.mul(t[1], &a[1], &b[1])
|
||||
fp2.mul(t[2], &a[2], &b[2])
|
||||
fp2.add(t[3], &a[1], &a[2])
|
||||
fp2.add(t[4], &b[1], &b[2])
|
||||
fp2.mulAssign(t[3], t[4])
|
||||
fp2.add(t[4], t[1], t[2])
|
||||
fp2.subAssign(t[3], t[4])
|
||||
fp2.mulByNonResidue(t[3], t[3])
|
||||
fp2.add(t[5], t[0], t[3])
|
||||
fp2.add(t[3], &a[0], &a[1])
|
||||
fp2.add(t[4], &b[0], &b[1])
|
||||
fp2.mulAssign(t[3], t[4])
|
||||
fp2.add(t[4], t[0], t[1])
|
||||
fp2.subAssign(t[3], t[4])
|
||||
fp2.mulByNonResidue(t[4], t[2])
|
||||
fp2.add(&a[1], t[3], t[4])
|
||||
fp2.add(t[3], &a[0], &a[2])
|
||||
fp2.add(t[4], &b[0], &b[2])
|
||||
fp2.mulAssign(t[3], t[4])
|
||||
fp2.add(t[4], t[0], t[2])
|
||||
fp2.subAssign(t[3], t[4])
|
||||
fp2.add(&a[2], t[1], t[3])
|
||||
a[0].set(t[5])
|
||||
}
|
||||
|
||||
func (e *fp6) square(c, a *fe6) {
|
||||
fp2, t := e.fp2, e.t
|
||||
fp2.square(t[0], &a[0])
|
||||
fp2.mul(t[1], &a[0], &a[1])
|
||||
fp2.doubleAssign(t[1])
|
||||
fp2.sub(t[2], &a[0], &a[1])
|
||||
fp2.addAssign(t[2], &a[2])
|
||||
fp2.squareAssign(t[2])
|
||||
fp2.mul(t[3], &a[1], &a[2])
|
||||
fp2.doubleAssign(t[3])
|
||||
fp2.square(t[4], &a[2])
|
||||
fp2.mulByNonResidue(t[5], t[3])
|
||||
fp2.add(&c[0], t[0], t[5])
|
||||
fp2.mulByNonResidue(t[5], t[4])
|
||||
fp2.add(&c[1], t[1], t[5])
|
||||
fp2.addAssign(t[1], t[2])
|
||||
fp2.addAssign(t[1], t[3])
|
||||
fp2.addAssign(t[0], t[4])
|
||||
fp2.sub(&c[2], t[1], t[0])
|
||||
}
|
||||
|
||||
func (e *fp6) mulBy01Assign(a *fe6, b0, b1 *fe2) {
|
||||
fp2, t := e.fp2, e.t
|
||||
fp2.mul(t[0], &a[0], b0)
|
||||
fp2.mul(t[1], &a[1], b1)
|
||||
fp2.add(t[5], &a[1], &a[2])
|
||||
fp2.mul(t[2], b1, t[5])
|
||||
fp2.subAssign(t[2], t[1])
|
||||
fp2.mulByNonResidue(t[2], t[2])
|
||||
fp2.add(t[5], &a[0], &a[2])
|
||||
fp2.mul(t[3], b0, t[5])
|
||||
fp2.subAssign(t[3], t[0])
|
||||
fp2.add(&a[2], t[3], t[1])
|
||||
fp2.add(t[4], b0, b1)
|
||||
fp2.add(t[5], &a[0], &a[1])
|
||||
fp2.mulAssign(t[4], t[5])
|
||||
fp2.subAssign(t[4], t[0])
|
||||
fp2.sub(&a[1], t[4], t[1])
|
||||
fp2.add(&a[0], t[2], t[0])
|
||||
}
|
||||
|
||||
func (e *fp6) mulBy01(c, a *fe6, b0, b1 *fe2) {
|
||||
fp2, t := e.fp2, e.t
|
||||
fp2.mul(t[0], &a[0], b0)
|
||||
fp2.mul(t[1], &a[1], b1)
|
||||
fp2.add(t[2], &a[1], &a[2])
|
||||
fp2.mulAssign(t[2], b1)
|
||||
fp2.subAssign(t[2], t[1])
|
||||
fp2.mulByNonResidue(t[2], t[2])
|
||||
fp2.add(t[3], &a[0], &a[2])
|
||||
fp2.mulAssign(t[3], b0)
|
||||
fp2.subAssign(t[3], t[0])
|
||||
fp2.add(&c[2], t[3], t[1])
|
||||
fp2.add(t[4], b0, b1)
|
||||
fp2.add(t[3], &a[0], &a[1])
|
||||
fp2.mulAssign(t[4], t[3])
|
||||
fp2.subAssign(t[4], t[0])
|
||||
fp2.sub(&c[1], t[4], t[1])
|
||||
fp2.add(&c[0], t[2], t[0])
|
||||
}
|
||||
|
||||
func (e *fp6) mulBy1(c, a *fe6, b1 *fe2) {
|
||||
fp2, t := e.fp2, e.t
|
||||
fp2.mul(t[0], &a[2], b1)
|
||||
fp2.mul(&c[2], &a[1], b1)
|
||||
fp2.mul(&c[1], &a[0], b1)
|
||||
fp2.mulByNonResidue(&c[0], t[0])
|
||||
}
|
||||
|
||||
func (e *fp6) mulByNonResidue(c, a *fe6) {
|
||||
fp2, t := e.fp2, e.t
|
||||
t[0].set(&a[0])
|
||||
fp2.mulByNonResidue(&c[0], &a[2])
|
||||
c[2].set(&a[1])
|
||||
c[1].set(t[0])
|
||||
}
|
||||
|
||||
func (e *fp6) mulByBaseField(c, a *fe6, b *fe2) {
|
||||
fp2 := e.fp2
|
||||
fp2.mul(&c[0], &a[0], b)
|
||||
fp2.mul(&c[1], &a[1], b)
|
||||
fp2.mul(&c[2], &a[2], b)
|
||||
}
|
||||
|
||||
func (e *fp6) exp(c, a *fe6, s *big.Int) {
|
||||
z := e.one()
|
||||
for i := s.BitLen() - 1; i >= 0; i-- {
|
||||
e.square(z, z)
|
||||
if s.Bit(i) == 1 {
|
||||
e.mul(z, z, a)
|
||||
}
|
||||
}
|
||||
c.set(z)
|
||||
}
|
||||
|
||||
func (e *fp6) inverse(c, a *fe6) {
|
||||
fp2, t := e.fp2, e.t
|
||||
fp2.square(t[0], &a[0])
|
||||
fp2.mul(t[1], &a[1], &a[2])
|
||||
fp2.mulByNonResidue(t[1], t[1])
|
||||
fp2.subAssign(t[0], t[1])
|
||||
fp2.square(t[1], &a[1])
|
||||
fp2.mul(t[2], &a[0], &a[2])
|
||||
fp2.subAssign(t[1], t[2])
|
||||
fp2.square(t[2], &a[2])
|
||||
fp2.mulByNonResidue(t[2], t[2])
|
||||
fp2.mul(t[3], &a[0], &a[1])
|
||||
fp2.subAssign(t[2], t[3])
|
||||
fp2.mul(t[3], &a[2], t[2])
|
||||
fp2.mul(t[4], &a[1], t[1])
|
||||
fp2.addAssign(t[3], t[4])
|
||||
fp2.mulByNonResidue(t[3], t[3])
|
||||
fp2.mul(t[4], &a[0], t[0])
|
||||
fp2.addAssign(t[3], t[4])
|
||||
fp2.inverse(t[3], t[3])
|
||||
fp2.mul(&c[0], t[0], t[3])
|
||||
fp2.mul(&c[1], t[2], t[3])
|
||||
fp2.mul(&c[2], t[1], t[3])
|
||||
}
|
||||
|
||||
func (e *fp6) frobeniusMap(c, a *fe6, power uint) {
|
||||
fp2 := e.fp2
|
||||
fp2.frobeniusMap(&c[0], &a[0], power)
|
||||
fp2.frobeniusMap(&c[1], &a[1], power)
|
||||
fp2.frobeniusMap(&c[2], &a[2], power)
|
||||
switch power % 6 {
|
||||
case 0:
|
||||
return
|
||||
case 3:
|
||||
neg(&c[0][0], &a[1][1])
|
||||
c[1][1].set(&a[1][0])
|
||||
fp2.neg(&a[2], &a[2])
|
||||
default:
|
||||
fp2.mul(&c[1], &c[1], &frobeniusCoeffs61[power%6])
|
||||
fp2.mul(&c[2], &c[2], &frobeniusCoeffs62[power%6])
|
||||
}
|
||||
}
|
||||
|
||||
func (e *fp6) frobeniusMapAssign(a *fe6, power uint) {
|
||||
fp2 := e.fp2
|
||||
fp2.frobeniusMapAssign(&a[0], power)
|
||||
fp2.frobeniusMapAssign(&a[1], power)
|
||||
fp2.frobeniusMapAssign(&a[2], power)
|
||||
t := e.t
|
||||
switch power % 6 {
|
||||
case 0:
|
||||
return
|
||||
case 3:
|
||||
neg(&t[0][0], &a[1][1])
|
||||
a[1][1].set(&a[1][0])
|
||||
a[1][0].set(&t[0][0])
|
||||
fp2.neg(&a[2], &a[2])
|
||||
default:
|
||||
fp2.mulAssign(&a[1], &frobeniusCoeffs61[power%6])
|
||||
fp2.mulAssign(&a[2], &frobeniusCoeffs62[power%6])
|
||||
}
|
||||
}
|
||||
434
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/g1.go
generated
vendored
Normal file
434
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/g1.go
generated
vendored
Normal file
@@ -0,0 +1,434 @@
|
||||
// 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"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// PointG1 is type for point in G1.
|
||||
// PointG1 is both used for Affine and Jacobian point representation.
|
||||
// If z is equal to one the point is considered as in affine form.
|
||||
type PointG1 [3]fe
|
||||
|
||||
func (p *PointG1) Set(p2 *PointG1) *PointG1 {
|
||||
p[0].set(&p2[0])
|
||||
p[1].set(&p2[1])
|
||||
p[2].set(&p2[2])
|
||||
return p
|
||||
}
|
||||
|
||||
// Zero returns G1 point in point at infinity representation
|
||||
func (p *PointG1) Zero() *PointG1 {
|
||||
p[0].zero()
|
||||
p[1].one()
|
||||
p[2].zero()
|
||||
return p
|
||||
}
|
||||
|
||||
type tempG1 struct {
|
||||
t [9]*fe
|
||||
}
|
||||
|
||||
// G1 is struct for G1 group.
|
||||
type G1 struct {
|
||||
tempG1
|
||||
}
|
||||
|
||||
// NewG1 constructs a new G1 instance.
|
||||
func NewG1() *G1 {
|
||||
t := newTempG1()
|
||||
return &G1{t}
|
||||
}
|
||||
|
||||
func newTempG1() tempG1 {
|
||||
t := [9]*fe{}
|
||||
for i := 0; i < 9; i++ {
|
||||
t[i] = &fe{}
|
||||
}
|
||||
return tempG1{t}
|
||||
}
|
||||
|
||||
// Q returns group order in big.Int.
|
||||
func (g *G1) Q() *big.Int {
|
||||
return new(big.Int).Set(q)
|
||||
}
|
||||
|
||||
func (g *G1) fromBytesUnchecked(in []byte) (*PointG1, error) {
|
||||
p0, err := fromBytes(in[:48])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p1, err := fromBytes(in[48:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p2 := new(fe).one()
|
||||
return &PointG1{*p0, *p1, *p2}, nil
|
||||
}
|
||||
|
||||
// FromBytes constructs a new point given uncompressed byte input.
|
||||
// FromBytes does not take zcash flags into account.
|
||||
// Byte input expected to be larger than 96 bytes.
|
||||
// First 96 bytes should be concatenation of x and y values.
|
||||
// Point (0, 0) is considered as infinity.
|
||||
func (g *G1) FromBytes(in []byte) (*PointG1, error) {
|
||||
if len(in) != 96 {
|
||||
return nil, errors.New("input string should be equal or larger than 96")
|
||||
}
|
||||
p0, err := fromBytes(in[:48])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p1, err := fromBytes(in[48:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// check if given input points to infinity
|
||||
if p0.isZero() && p1.isZero() {
|
||||
return g.Zero(), nil
|
||||
}
|
||||
p2 := new(fe).one()
|
||||
p := &PointG1{*p0, *p1, *p2}
|
||||
if !g.IsOnCurve(p) {
|
||||
return nil, errors.New("point is not on curve")
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// DecodePoint given encoded (x, y) coordinates in 128 bytes returns a valid G1 Point.
|
||||
func (g *G1) DecodePoint(in []byte) (*PointG1, error) {
|
||||
if len(in) != 128 {
|
||||
return nil, errors.New("invalid g1 point length")
|
||||
}
|
||||
pointBytes := make([]byte, 96)
|
||||
// decode x
|
||||
xBytes, err := decodeFieldElement(in[:64])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// decode y
|
||||
yBytes, err := decodeFieldElement(in[64:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(pointBytes[:48], xBytes)
|
||||
copy(pointBytes[48:], yBytes)
|
||||
return g.FromBytes(pointBytes)
|
||||
}
|
||||
|
||||
// ToBytes serializes a point into bytes in uncompressed form.
|
||||
// ToBytes does not take zcash flags into account.
|
||||
// ToBytes returns (0, 0) if point is infinity.
|
||||
func (g *G1) ToBytes(p *PointG1) []byte {
|
||||
out := make([]byte, 96)
|
||||
if g.IsZero(p) {
|
||||
return out
|
||||
}
|
||||
g.Affine(p)
|
||||
copy(out[:48], toBytes(&p[0]))
|
||||
copy(out[48:], toBytes(&p[1]))
|
||||
return out
|
||||
}
|
||||
|
||||
// EncodePoint encodes a point into 128 bytes.
|
||||
func (g *G1) EncodePoint(p *PointG1) []byte {
|
||||
outRaw := g.ToBytes(p)
|
||||
out := make([]byte, 128)
|
||||
// encode x
|
||||
copy(out[16:], outRaw[:48])
|
||||
// encode y
|
||||
copy(out[64+16:], outRaw[48:])
|
||||
return out
|
||||
}
|
||||
|
||||
// New creates a new G1 Point which is equal to zero in other words point at infinity.
|
||||
func (g *G1) New() *PointG1 {
|
||||
return g.Zero()
|
||||
}
|
||||
|
||||
// Zero returns a new G1 Point which is equal to point at infinity.
|
||||
func (g *G1) Zero() *PointG1 {
|
||||
return new(PointG1).Zero()
|
||||
}
|
||||
|
||||
// One returns a new G1 Point which is equal to generator point.
|
||||
func (g *G1) One() *PointG1 {
|
||||
p := &PointG1{}
|
||||
return p.Set(&g1One)
|
||||
}
|
||||
|
||||
// IsZero returns true if given point is equal to zero.
|
||||
func (g *G1) IsZero(p *PointG1) bool {
|
||||
return p[2].isZero()
|
||||
}
|
||||
|
||||
// Equal checks if given two G1 point is equal in their affine form.
|
||||
func (g *G1) Equal(p1, p2 *PointG1) bool {
|
||||
if g.IsZero(p1) {
|
||||
return g.IsZero(p2)
|
||||
}
|
||||
if g.IsZero(p2) {
|
||||
return g.IsZero(p1)
|
||||
}
|
||||
t := g.t
|
||||
square(t[0], &p1[2])
|
||||
square(t[1], &p2[2])
|
||||
mul(t[2], t[0], &p2[0])
|
||||
mul(t[3], t[1], &p1[0])
|
||||
mul(t[0], t[0], &p1[2])
|
||||
mul(t[1], t[1], &p2[2])
|
||||
mul(t[1], t[1], &p1[1])
|
||||
mul(t[0], t[0], &p2[1])
|
||||
return t[0].equal(t[1]) && t[2].equal(t[3])
|
||||
}
|
||||
|
||||
// InCorrectSubgroup checks whether given point is in correct subgroup.
|
||||
func (g *G1) InCorrectSubgroup(p *PointG1) bool {
|
||||
tmp := &PointG1{}
|
||||
g.MulScalar(tmp, p, q)
|
||||
return g.IsZero(tmp)
|
||||
}
|
||||
|
||||
// IsOnCurve checks a G1 point is on curve.
|
||||
func (g *G1) IsOnCurve(p *PointG1) bool {
|
||||
if g.IsZero(p) {
|
||||
return true
|
||||
}
|
||||
t := g.t
|
||||
square(t[0], &p[1])
|
||||
square(t[1], &p[0])
|
||||
mul(t[1], t[1], &p[0])
|
||||
square(t[2], &p[2])
|
||||
square(t[3], t[2])
|
||||
mul(t[2], t[2], t[3])
|
||||
mul(t[2], b, t[2])
|
||||
add(t[1], t[1], t[2])
|
||||
return t[0].equal(t[1])
|
||||
}
|
||||
|
||||
// IsAffine checks a G1 point whether it is in affine form.
|
||||
func (g *G1) IsAffine(p *PointG1) bool {
|
||||
return p[2].isOne()
|
||||
}
|
||||
|
||||
// Affine calculates affine form of given G1 point.
|
||||
func (g *G1) Affine(p *PointG1) *PointG1 {
|
||||
if g.IsZero(p) {
|
||||
return p
|
||||
}
|
||||
if !g.IsAffine(p) {
|
||||
t := g.t
|
||||
inverse(t[0], &p[2])
|
||||
square(t[1], t[0])
|
||||
mul(&p[0], &p[0], t[1])
|
||||
mul(t[0], t[0], t[1])
|
||||
mul(&p[1], &p[1], t[0])
|
||||
p[2].one()
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// Add adds two G1 points p1, p2 and assigns the result to point at first argument.
|
||||
func (g *G1) Add(r, p1, p2 *PointG1) *PointG1 {
|
||||
// http://www.hyperelliptic.org/EFD/gp/auto-shortw-jacobian-0.html#addition-add-2007-bl
|
||||
if g.IsZero(p1) {
|
||||
return r.Set(p2)
|
||||
}
|
||||
if g.IsZero(p2) {
|
||||
return r.Set(p1)
|
||||
}
|
||||
t := g.t
|
||||
square(t[7], &p1[2])
|
||||
mul(t[1], &p2[0], t[7])
|
||||
mul(t[2], &p1[2], t[7])
|
||||
mul(t[0], &p2[1], t[2])
|
||||
square(t[8], &p2[2])
|
||||
mul(t[3], &p1[0], t[8])
|
||||
mul(t[4], &p2[2], t[8])
|
||||
mul(t[2], &p1[1], t[4])
|
||||
if t[1].equal(t[3]) {
|
||||
if t[0].equal(t[2]) {
|
||||
return g.Double(r, p1)
|
||||
}
|
||||
return r.Zero()
|
||||
}
|
||||
sub(t[1], t[1], t[3])
|
||||
double(t[4], t[1])
|
||||
square(t[4], t[4])
|
||||
mul(t[5], t[1], t[4])
|
||||
sub(t[0], t[0], t[2])
|
||||
double(t[0], t[0])
|
||||
square(t[6], t[0])
|
||||
sub(t[6], t[6], t[5])
|
||||
mul(t[3], t[3], t[4])
|
||||
double(t[4], t[3])
|
||||
sub(&r[0], t[6], t[4])
|
||||
sub(t[4], t[3], &r[0])
|
||||
mul(t[6], t[2], t[5])
|
||||
double(t[6], t[6])
|
||||
mul(t[0], t[0], t[4])
|
||||
sub(&r[1], t[0], t[6])
|
||||
add(t[0], &p1[2], &p2[2])
|
||||
square(t[0], t[0])
|
||||
sub(t[0], t[0], t[7])
|
||||
sub(t[0], t[0], t[8])
|
||||
mul(&r[2], t[0], t[1])
|
||||
return r
|
||||
}
|
||||
|
||||
// Double doubles a G1 point p and assigns the result to the point at first argument.
|
||||
func (g *G1) Double(r, p *PointG1) *PointG1 {
|
||||
// http://www.hyperelliptic.org/EFD/gp/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
|
||||
if g.IsZero(p) {
|
||||
return r.Set(p)
|
||||
}
|
||||
t := g.t
|
||||
square(t[0], &p[0])
|
||||
square(t[1], &p[1])
|
||||
square(t[2], t[1])
|
||||
add(t[1], &p[0], t[1])
|
||||
square(t[1], t[1])
|
||||
sub(t[1], t[1], t[0])
|
||||
sub(t[1], t[1], t[2])
|
||||
double(t[1], t[1])
|
||||
double(t[3], t[0])
|
||||
add(t[0], t[3], t[0])
|
||||
square(t[4], t[0])
|
||||
double(t[3], t[1])
|
||||
sub(&r[0], t[4], t[3])
|
||||
sub(t[1], t[1], &r[0])
|
||||
double(t[2], t[2])
|
||||
double(t[2], t[2])
|
||||
double(t[2], t[2])
|
||||
mul(t[0], t[0], t[1])
|
||||
sub(t[1], t[0], t[2])
|
||||
mul(t[0], &p[1], &p[2])
|
||||
r[1].set(t[1])
|
||||
double(&r[2], t[0])
|
||||
return r
|
||||
}
|
||||
|
||||
// Neg negates a G1 point p and assigns the result to the point at first argument.
|
||||
func (g *G1) Neg(r, p *PointG1) *PointG1 {
|
||||
r[0].set(&p[0])
|
||||
r[2].set(&p[2])
|
||||
neg(&r[1], &p[1])
|
||||
return r
|
||||
}
|
||||
|
||||
// Sub subtracts two G1 points p1, p2 and assigns the result to point at first argument.
|
||||
func (g *G1) Sub(c, a, b *PointG1) *PointG1 {
|
||||
d := &PointG1{}
|
||||
g.Neg(d, b)
|
||||
g.Add(c, a, d)
|
||||
return c
|
||||
}
|
||||
|
||||
// MulScalar multiplies a point by given scalar value in big.Int and assigns the result to point at first argument.
|
||||
func (g *G1) MulScalar(c, p *PointG1, e *big.Int) *PointG1 {
|
||||
q, n := &PointG1{}, &PointG1{}
|
||||
n.Set(p)
|
||||
l := e.BitLen()
|
||||
for i := 0; i < l; i++ {
|
||||
if e.Bit(i) == 1 {
|
||||
g.Add(q, q, n)
|
||||
}
|
||||
g.Double(n, n)
|
||||
}
|
||||
return c.Set(q)
|
||||
}
|
||||
|
||||
// ClearCofactor maps given a G1 point to correct subgroup
|
||||
func (g *G1) ClearCofactor(p *PointG1) {
|
||||
g.MulScalar(p, p, cofactorEFFG1)
|
||||
}
|
||||
|
||||
// MultiExp calculates multi exponentiation. Given pairs of G1 point and scalar values
|
||||
// (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n
|
||||
// Length of points and scalars are expected to be equal, otherwise an error is returned.
|
||||
// Result is assigned to point at first argument.
|
||||
func (g *G1) MultiExp(r *PointG1, points []*PointG1, powers []*big.Int) (*PointG1, error) {
|
||||
if len(points) != len(powers) {
|
||||
return nil, errors.New("point and scalar vectors should be in same length")
|
||||
}
|
||||
var c uint32 = 3
|
||||
if len(powers) >= 32 {
|
||||
c = uint32(math.Ceil(math.Log10(float64(len(powers)))))
|
||||
}
|
||||
bucketSize, numBits := (1<<c)-1, uint32(g.Q().BitLen())
|
||||
windows := make([]*PointG1, numBits/c+1)
|
||||
bucket := make([]*PointG1, bucketSize)
|
||||
acc, sum := g.New(), g.New()
|
||||
for i := 0; i < bucketSize; i++ {
|
||||
bucket[i] = g.New()
|
||||
}
|
||||
mask := (uint64(1) << c) - 1
|
||||
j := 0
|
||||
var cur uint32
|
||||
for cur <= numBits {
|
||||
acc.Zero()
|
||||
bucket = make([]*PointG1, (1<<c)-1)
|
||||
for i := 0; i < len(bucket); i++ {
|
||||
bucket[i] = g.New()
|
||||
}
|
||||
for i := 0; i < len(powers); i++ {
|
||||
s0 := powers[i].Uint64()
|
||||
index := uint(s0 & mask)
|
||||
if index != 0 {
|
||||
g.Add(bucket[index-1], bucket[index-1], points[i])
|
||||
}
|
||||
powers[i] = new(big.Int).Rsh(powers[i], uint(c))
|
||||
}
|
||||
sum.Zero()
|
||||
for i := len(bucket) - 1; i >= 0; i-- {
|
||||
g.Add(sum, sum, bucket[i])
|
||||
g.Add(acc, acc, sum)
|
||||
}
|
||||
windows[j] = g.New()
|
||||
windows[j].Set(acc)
|
||||
j++
|
||||
cur += c
|
||||
}
|
||||
acc.Zero()
|
||||
for i := len(windows) - 1; i >= 0; i-- {
|
||||
for j := uint32(0); j < c; j++ {
|
||||
g.Double(acc, acc)
|
||||
}
|
||||
g.Add(acc, acc, windows[i])
|
||||
}
|
||||
return r.Set(acc), nil
|
||||
}
|
||||
|
||||
// MapToCurve given a byte slice returns a valid G1 point.
|
||||
// This mapping function implements the Simplified Shallue-van de Woestijne-Ulas method.
|
||||
// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06
|
||||
// Input byte slice should be a valid field element, otherwise an error is returned.
|
||||
func (g *G1) MapToCurve(in []byte) (*PointG1, error) {
|
||||
u, err := fromBytes(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x, y := swuMapG1(u)
|
||||
isogenyMapG1(x, y)
|
||||
one := new(fe).one()
|
||||
p := &PointG1{*x, *y, *one}
|
||||
g.ClearCofactor(p)
|
||||
return g.Affine(p), nil
|
||||
}
|
||||
455
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/g2.go
generated
vendored
Normal file
455
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/g2.go
generated
vendored
Normal file
@@ -0,0 +1,455 @@
|
||||
// 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"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// PointG2 is type for point in G2.
|
||||
// PointG2 is both used for Affine and Jacobian point representation.
|
||||
// If z is equal to one the point is considered as in affine form.
|
||||
type PointG2 [3]fe2
|
||||
|
||||
// Set copies valeus of one point to another.
|
||||
func (p *PointG2) Set(p2 *PointG2) *PointG2 {
|
||||
p[0].set(&p2[0])
|
||||
p[1].set(&p2[1])
|
||||
p[2].set(&p2[2])
|
||||
return p
|
||||
}
|
||||
|
||||
// Zero returns G2 point in point at infinity representation
|
||||
func (p *PointG2) Zero() *PointG2 {
|
||||
p[0].zero()
|
||||
p[1].one()
|
||||
p[2].zero()
|
||||
return p
|
||||
}
|
||||
|
||||
type tempG2 struct {
|
||||
t [9]*fe2
|
||||
}
|
||||
|
||||
// G2 is struct for G2 group.
|
||||
type G2 struct {
|
||||
f *fp2
|
||||
tempG2
|
||||
}
|
||||
|
||||
// NewG2 constructs a new G2 instance.
|
||||
func NewG2() *G2 {
|
||||
return newG2(nil)
|
||||
}
|
||||
|
||||
func newG2(f *fp2) *G2 {
|
||||
if f == nil {
|
||||
f = newFp2()
|
||||
}
|
||||
t := newTempG2()
|
||||
return &G2{f, t}
|
||||
}
|
||||
|
||||
func newTempG2() tempG2 {
|
||||
t := [9]*fe2{}
|
||||
for i := 0; i < 9; i++ {
|
||||
t[i] = &fe2{}
|
||||
}
|
||||
return tempG2{t}
|
||||
}
|
||||
|
||||
// Q returns group order in big.Int.
|
||||
func (g *G2) Q() *big.Int {
|
||||
return new(big.Int).Set(q)
|
||||
}
|
||||
|
||||
func (g *G2) fromBytesUnchecked(in []byte) (*PointG2, error) {
|
||||
p0, err := g.f.fromBytes(in[:96])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p1, err := g.f.fromBytes(in[96:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p2 := new(fe2).one()
|
||||
return &PointG2{*p0, *p1, *p2}, nil
|
||||
}
|
||||
|
||||
// FromBytes constructs a new point given uncompressed byte input.
|
||||
// FromBytes does not take zcash flags into account.
|
||||
// Byte input expected to be larger than 96 bytes.
|
||||
// First 192 bytes should be concatenation of x and y values
|
||||
// Point (0, 0) is considered as infinity.
|
||||
func (g *G2) FromBytes(in []byte) (*PointG2, error) {
|
||||
if len(in) != 192 {
|
||||
return nil, errors.New("input string should be equal or larger than 192")
|
||||
}
|
||||
p0, err := g.f.fromBytes(in[:96])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p1, err := g.f.fromBytes(in[96:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// check if given input points to infinity
|
||||
if p0.isZero() && p1.isZero() {
|
||||
return g.Zero(), nil
|
||||
}
|
||||
p2 := new(fe2).one()
|
||||
p := &PointG2{*p0, *p1, *p2}
|
||||
if !g.IsOnCurve(p) {
|
||||
return nil, errors.New("point is not on curve")
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// DecodePoint given encoded (x, y) coordinates in 256 bytes returns a valid G1 Point.
|
||||
func (g *G2) DecodePoint(in []byte) (*PointG2, error) {
|
||||
if len(in) != 256 {
|
||||
return nil, errors.New("invalid g2 point length")
|
||||
}
|
||||
pointBytes := make([]byte, 192)
|
||||
x0Bytes, err := decodeFieldElement(in[:64])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x1Bytes, err := decodeFieldElement(in[64:128])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
y0Bytes, err := decodeFieldElement(in[128:192])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
y1Bytes, err := decodeFieldElement(in[192:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(pointBytes[:48], x1Bytes)
|
||||
copy(pointBytes[48:96], x0Bytes)
|
||||
copy(pointBytes[96:144], y1Bytes)
|
||||
copy(pointBytes[144:192], y0Bytes)
|
||||
return g.FromBytes(pointBytes)
|
||||
}
|
||||
|
||||
// ToBytes serializes a point into bytes in uncompressed form,
|
||||
// does not take zcash flags into account,
|
||||
// returns (0, 0) if point is infinity.
|
||||
func (g *G2) ToBytes(p *PointG2) []byte {
|
||||
out := make([]byte, 192)
|
||||
if g.IsZero(p) {
|
||||
return out
|
||||
}
|
||||
g.Affine(p)
|
||||
copy(out[:96], g.f.toBytes(&p[0]))
|
||||
copy(out[96:], g.f.toBytes(&p[1]))
|
||||
return out
|
||||
}
|
||||
|
||||
// EncodePoint encodes a point into 256 bytes.
|
||||
func (g *G2) EncodePoint(p *PointG2) []byte {
|
||||
// outRaw is 96 bytes
|
||||
outRaw := g.ToBytes(p)
|
||||
out := make([]byte, 256)
|
||||
// encode x
|
||||
copy(out[16:16+48], outRaw[48:96])
|
||||
copy(out[80:80+48], outRaw[:48])
|
||||
// encode y
|
||||
copy(out[144:144+48], outRaw[144:])
|
||||
copy(out[208:208+48], outRaw[96:144])
|
||||
return out
|
||||
}
|
||||
|
||||
// New creates a new G2 Point which is equal to zero in other words point at infinity.
|
||||
func (g *G2) New() *PointG2 {
|
||||
return new(PointG2).Zero()
|
||||
}
|
||||
|
||||
// Zero returns a new G2 Point which is equal to point at infinity.
|
||||
func (g *G2) Zero() *PointG2 {
|
||||
return new(PointG2).Zero()
|
||||
}
|
||||
|
||||
// One returns a new G2 Point which is equal to generator point.
|
||||
func (g *G2) One() *PointG2 {
|
||||
p := &PointG2{}
|
||||
return p.Set(&g2One)
|
||||
}
|
||||
|
||||
// IsZero returns true if given point is equal to zero.
|
||||
func (g *G2) IsZero(p *PointG2) bool {
|
||||
return p[2].isZero()
|
||||
}
|
||||
|
||||
// Equal checks if given two G2 point is equal in their affine form.
|
||||
func (g *G2) Equal(p1, p2 *PointG2) bool {
|
||||
if g.IsZero(p1) {
|
||||
return g.IsZero(p2)
|
||||
}
|
||||
if g.IsZero(p2) {
|
||||
return g.IsZero(p1)
|
||||
}
|
||||
t := g.t
|
||||
g.f.square(t[0], &p1[2])
|
||||
g.f.square(t[1], &p2[2])
|
||||
g.f.mul(t[2], t[0], &p2[0])
|
||||
g.f.mul(t[3], t[1], &p1[0])
|
||||
g.f.mul(t[0], t[0], &p1[2])
|
||||
g.f.mul(t[1], t[1], &p2[2])
|
||||
g.f.mul(t[1], t[1], &p1[1])
|
||||
g.f.mul(t[0], t[0], &p2[1])
|
||||
return t[0].equal(t[1]) && t[2].equal(t[3])
|
||||
}
|
||||
|
||||
// InCorrectSubgroup checks whether given point is in correct subgroup.
|
||||
func (g *G2) InCorrectSubgroup(p *PointG2) bool {
|
||||
tmp := &PointG2{}
|
||||
g.MulScalar(tmp, p, q)
|
||||
return g.IsZero(tmp)
|
||||
}
|
||||
|
||||
// IsOnCurve checks a G2 point is on curve.
|
||||
func (g *G2) IsOnCurve(p *PointG2) bool {
|
||||
if g.IsZero(p) {
|
||||
return true
|
||||
}
|
||||
t := g.t
|
||||
g.f.square(t[0], &p[1])
|
||||
g.f.square(t[1], &p[0])
|
||||
g.f.mul(t[1], t[1], &p[0])
|
||||
g.f.square(t[2], &p[2])
|
||||
g.f.square(t[3], t[2])
|
||||
g.f.mul(t[2], t[2], t[3])
|
||||
g.f.mul(t[2], b2, t[2])
|
||||
g.f.add(t[1], t[1], t[2])
|
||||
return t[0].equal(t[1])
|
||||
}
|
||||
|
||||
// IsAffine checks a G2 point whether it is in affine form.
|
||||
func (g *G2) IsAffine(p *PointG2) bool {
|
||||
return p[2].isOne()
|
||||
}
|
||||
|
||||
// Affine calculates affine form of given G2 point.
|
||||
func (g *G2) Affine(p *PointG2) *PointG2 {
|
||||
if g.IsZero(p) {
|
||||
return p
|
||||
}
|
||||
if !g.IsAffine(p) {
|
||||
t := g.t
|
||||
g.f.inverse(t[0], &p[2])
|
||||
g.f.square(t[1], t[0])
|
||||
g.f.mul(&p[0], &p[0], t[1])
|
||||
g.f.mul(t[0], t[0], t[1])
|
||||
g.f.mul(&p[1], &p[1], t[0])
|
||||
p[2].one()
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// Add adds two G2 points p1, p2 and assigns the result to point at first argument.
|
||||
func (g *G2) Add(r, p1, p2 *PointG2) *PointG2 {
|
||||
// http://www.hyperelliptic.org/EFD/gp/auto-shortw-jacobian-0.html#addition-add-2007-bl
|
||||
if g.IsZero(p1) {
|
||||
return r.Set(p2)
|
||||
}
|
||||
if g.IsZero(p2) {
|
||||
return r.Set(p1)
|
||||
}
|
||||
t := g.t
|
||||
g.f.square(t[7], &p1[2])
|
||||
g.f.mul(t[1], &p2[0], t[7])
|
||||
g.f.mul(t[2], &p1[2], t[7])
|
||||
g.f.mul(t[0], &p2[1], t[2])
|
||||
g.f.square(t[8], &p2[2])
|
||||
g.f.mul(t[3], &p1[0], t[8])
|
||||
g.f.mul(t[4], &p2[2], t[8])
|
||||
g.f.mul(t[2], &p1[1], t[4])
|
||||
if t[1].equal(t[3]) {
|
||||
if t[0].equal(t[2]) {
|
||||
return g.Double(r, p1)
|
||||
}
|
||||
return r.Zero()
|
||||
}
|
||||
g.f.sub(t[1], t[1], t[3])
|
||||
g.f.double(t[4], t[1])
|
||||
g.f.square(t[4], t[4])
|
||||
g.f.mul(t[5], t[1], t[4])
|
||||
g.f.sub(t[0], t[0], t[2])
|
||||
g.f.double(t[0], t[0])
|
||||
g.f.square(t[6], t[0])
|
||||
g.f.sub(t[6], t[6], t[5])
|
||||
g.f.mul(t[3], t[3], t[4])
|
||||
g.f.double(t[4], t[3])
|
||||
g.f.sub(&r[0], t[6], t[4])
|
||||
g.f.sub(t[4], t[3], &r[0])
|
||||
g.f.mul(t[6], t[2], t[5])
|
||||
g.f.double(t[6], t[6])
|
||||
g.f.mul(t[0], t[0], t[4])
|
||||
g.f.sub(&r[1], t[0], t[6])
|
||||
g.f.add(t[0], &p1[2], &p2[2])
|
||||
g.f.square(t[0], t[0])
|
||||
g.f.sub(t[0], t[0], t[7])
|
||||
g.f.sub(t[0], t[0], t[8])
|
||||
g.f.mul(&r[2], t[0], t[1])
|
||||
return r
|
||||
}
|
||||
|
||||
// Double doubles a G2 point p and assigns the result to the point at first argument.
|
||||
func (g *G2) Double(r, p *PointG2) *PointG2 {
|
||||
// http://www.hyperelliptic.org/EFD/gp/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
|
||||
if g.IsZero(p) {
|
||||
return r.Set(p)
|
||||
}
|
||||
t := g.t
|
||||
g.f.square(t[0], &p[0])
|
||||
g.f.square(t[1], &p[1])
|
||||
g.f.square(t[2], t[1])
|
||||
g.f.add(t[1], &p[0], t[1])
|
||||
g.f.square(t[1], t[1])
|
||||
g.f.sub(t[1], t[1], t[0])
|
||||
g.f.sub(t[1], t[1], t[2])
|
||||
g.f.double(t[1], t[1])
|
||||
g.f.double(t[3], t[0])
|
||||
g.f.add(t[0], t[3], t[0])
|
||||
g.f.square(t[4], t[0])
|
||||
g.f.double(t[3], t[1])
|
||||
g.f.sub(&r[0], t[4], t[3])
|
||||
g.f.sub(t[1], t[1], &r[0])
|
||||
g.f.double(t[2], t[2])
|
||||
g.f.double(t[2], t[2])
|
||||
g.f.double(t[2], t[2])
|
||||
g.f.mul(t[0], t[0], t[1])
|
||||
g.f.sub(t[1], t[0], t[2])
|
||||
g.f.mul(t[0], &p[1], &p[2])
|
||||
r[1].set(t[1])
|
||||
g.f.double(&r[2], t[0])
|
||||
return r
|
||||
}
|
||||
|
||||
// Neg negates a G2 point p and assigns the result to the point at first argument.
|
||||
func (g *G2) Neg(r, p *PointG2) *PointG2 {
|
||||
r[0].set(&p[0])
|
||||
g.f.neg(&r[1], &p[1])
|
||||
r[2].set(&p[2])
|
||||
return r
|
||||
}
|
||||
|
||||
// Sub subtracts two G2 points p1, p2 and assigns the result to point at first argument.
|
||||
func (g *G2) Sub(c, a, b *PointG2) *PointG2 {
|
||||
d := &PointG2{}
|
||||
g.Neg(d, b)
|
||||
g.Add(c, a, d)
|
||||
return c
|
||||
}
|
||||
|
||||
// MulScalar multiplies a point by given scalar value in big.Int and assigns the result to point at first argument.
|
||||
func (g *G2) MulScalar(c, p *PointG2, e *big.Int) *PointG2 {
|
||||
q, n := &PointG2{}, &PointG2{}
|
||||
n.Set(p)
|
||||
l := e.BitLen()
|
||||
for i := 0; i < l; i++ {
|
||||
if e.Bit(i) == 1 {
|
||||
g.Add(q, q, n)
|
||||
}
|
||||
g.Double(n, n)
|
||||
}
|
||||
return c.Set(q)
|
||||
}
|
||||
|
||||
// ClearCofactor maps given a G2 point to correct subgroup
|
||||
func (g *G2) ClearCofactor(p *PointG2) {
|
||||
g.MulScalar(p, p, cofactorEFFG2)
|
||||
}
|
||||
|
||||
// MultiExp calculates multi exponentiation. Given pairs of G2 point and scalar values
|
||||
// (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n
|
||||
// Length of points and scalars are expected to be equal, otherwise an error is returned.
|
||||
// Result is assigned to point at first argument.
|
||||
func (g *G2) MultiExp(r *PointG2, points []*PointG2, powers []*big.Int) (*PointG2, error) {
|
||||
if len(points) != len(powers) {
|
||||
return nil, errors.New("point and scalar vectors should be in same length")
|
||||
}
|
||||
var c uint32 = 3
|
||||
if len(powers) >= 32 {
|
||||
c = uint32(math.Ceil(math.Log10(float64(len(powers)))))
|
||||
}
|
||||
bucketSize, numBits := (1<<c)-1, uint32(g.Q().BitLen())
|
||||
windows := make([]*PointG2, numBits/c+1)
|
||||
bucket := make([]*PointG2, bucketSize)
|
||||
acc, sum := g.New(), g.New()
|
||||
for i := 0; i < bucketSize; i++ {
|
||||
bucket[i] = g.New()
|
||||
}
|
||||
mask := (uint64(1) << c) - 1
|
||||
j := 0
|
||||
var cur uint32
|
||||
for cur <= numBits {
|
||||
acc.Zero()
|
||||
bucket = make([]*PointG2, (1<<c)-1)
|
||||
for i := 0; i < len(bucket); i++ {
|
||||
bucket[i] = g.New()
|
||||
}
|
||||
for i := 0; i < len(powers); i++ {
|
||||
s0 := powers[i].Uint64()
|
||||
index := uint(s0 & mask)
|
||||
if index != 0 {
|
||||
g.Add(bucket[index-1], bucket[index-1], points[i])
|
||||
}
|
||||
powers[i] = new(big.Int).Rsh(powers[i], uint(c))
|
||||
}
|
||||
sum.Zero()
|
||||
for i := len(bucket) - 1; i >= 0; i-- {
|
||||
g.Add(sum, sum, bucket[i])
|
||||
g.Add(acc, acc, sum)
|
||||
}
|
||||
windows[j] = g.New()
|
||||
windows[j].Set(acc)
|
||||
j++
|
||||
cur += c
|
||||
}
|
||||
acc.Zero()
|
||||
for i := len(windows) - 1; i >= 0; i-- {
|
||||
for j := uint32(0); j < c; j++ {
|
||||
g.Double(acc, acc)
|
||||
}
|
||||
g.Add(acc, acc, windows[i])
|
||||
}
|
||||
return r.Set(acc), nil
|
||||
}
|
||||
|
||||
// MapToCurve given a byte slice returns a valid G2 point.
|
||||
// This mapping function implements the Simplified Shallue-van de Woestijne-Ulas method.
|
||||
// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-05#section-6.6.2
|
||||
// Input byte slice should be a valid field element, otherwise an error is returned.
|
||||
func (g *G2) MapToCurve(in []byte) (*PointG2, error) {
|
||||
fp2 := g.f
|
||||
u, err := fp2.fromBytes(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x, y := swuMapG2(fp2, u)
|
||||
isogenyMapG2(fp2, x, y)
|
||||
z := new(fe2).one()
|
||||
q := &PointG2{*x, *y, *z}
|
||||
g.ClearCofactor(q)
|
||||
return g.Affine(q), nil
|
||||
}
|
||||
121
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/gt.go
generated
vendored
Normal file
121
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/gt.go
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// E is type for target group element
|
||||
type E = fe12
|
||||
|
||||
// GT is type for target multiplicative group GT.
|
||||
type GT struct {
|
||||
fp12 *fp12
|
||||
}
|
||||
|
||||
func (e *E) Set(e2 *E) *E {
|
||||
return e.set(e2)
|
||||
}
|
||||
|
||||
// One sets a new target group element to one
|
||||
func (e *E) One() *E {
|
||||
e = new(fe12).one()
|
||||
return e
|
||||
}
|
||||
|
||||
// IsOne returns true if given element equals to one
|
||||
func (e *E) IsOne() bool {
|
||||
return e.isOne()
|
||||
}
|
||||
|
||||
// Equal returns true if given two element is equal, otherwise returns false
|
||||
func (g *E) Equal(g2 *E) bool {
|
||||
return g.equal(g2)
|
||||
}
|
||||
|
||||
// NewGT constructs new target group instance.
|
||||
func NewGT() *GT {
|
||||
fp12 := newFp12(nil)
|
||||
return >{fp12}
|
||||
}
|
||||
|
||||
// Q returns group order in big.Int.
|
||||
func (g *GT) Q() *big.Int {
|
||||
return new(big.Int).Set(q)
|
||||
}
|
||||
|
||||
// FromBytes expects 576 byte input and returns target group element
|
||||
// FromBytes returns error if given element is not on correct subgroup.
|
||||
func (g *GT) FromBytes(in []byte) (*E, error) {
|
||||
e, err := g.fp12.fromBytes(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !g.IsValid(e) {
|
||||
return e, errors.New("invalid element")
|
||||
}
|
||||
return e, nil
|
||||
}
|
||||
|
||||
// ToBytes serializes target group element.
|
||||
func (g *GT) ToBytes(e *E) []byte {
|
||||
return g.fp12.toBytes(e)
|
||||
}
|
||||
|
||||
// IsValid checks whether given target group element is in correct subgroup.
|
||||
func (g *GT) IsValid(e *E) bool {
|
||||
r := g.New()
|
||||
g.fp12.exp(r, e, q)
|
||||
return r.isOne()
|
||||
}
|
||||
|
||||
// New initializes a new target group element which is equal to one
|
||||
func (g *GT) New() *E {
|
||||
return new(E).One()
|
||||
}
|
||||
|
||||
// Add adds two field element `a` and `b` and assigns the result to the element in first argument.
|
||||
func (g *GT) Add(c, a, b *E) {
|
||||
g.fp12.add(c, a, b)
|
||||
}
|
||||
|
||||
// Sub subtracts two field element `a` and `b`, and assigns the result to the element in first argument.
|
||||
func (g *GT) Sub(c, a, b *E) {
|
||||
g.fp12.sub(c, a, b)
|
||||
}
|
||||
|
||||
// Mul multiplies two field element `a` and `b` and assigns the result to the element in first argument.
|
||||
func (g *GT) Mul(c, a, b *E) {
|
||||
g.fp12.mul(c, a, b)
|
||||
}
|
||||
|
||||
// Square squares an element `a` and assigns the result to the element in first argument.
|
||||
func (g *GT) Square(c, a *E) {
|
||||
g.fp12.cyclotomicSquare(c, a)
|
||||
}
|
||||
|
||||
// Exp exponents an element `a` by a scalar `s` and assigns the result to the element in first argument.
|
||||
func (g *GT) Exp(c, a *E, s *big.Int) {
|
||||
g.fp12.cyclotomicExp(c, a, s)
|
||||
}
|
||||
|
||||
// Inverse inverses an element `a` and assigns the result to the element in first argument.
|
||||
func (g *GT) Inverse(c, a *E) {
|
||||
g.fp12.inverse(c, a)
|
||||
}
|
||||
227
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/isogeny.go
generated
vendored
Normal file
227
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/isogeny.go
generated
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
// 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
|
||||
|
||||
// isogenyMapG1 applies 11-isogeny map for BLS12-381 G1 defined at draft-irtf-cfrg-hash-to-curve-06.
|
||||
func isogenyMapG1(x, y *fe) {
|
||||
// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#appendix-C.2
|
||||
params := isogenyConstantsG1
|
||||
degree := 15
|
||||
xNum, xDen, yNum, yDen := new(fe), new(fe), new(fe), new(fe)
|
||||
xNum.set(params[0][degree])
|
||||
xDen.set(params[1][degree])
|
||||
yNum.set(params[2][degree])
|
||||
yDen.set(params[3][degree])
|
||||
for i := degree - 1; i >= 0; i-- {
|
||||
mul(xNum, xNum, x)
|
||||
mul(xDen, xDen, x)
|
||||
mul(yNum, yNum, x)
|
||||
mul(yDen, yDen, x)
|
||||
add(xNum, xNum, params[0][i])
|
||||
add(xDen, xDen, params[1][i])
|
||||
add(yNum, yNum, params[2][i])
|
||||
add(yDen, yDen, params[3][i])
|
||||
}
|
||||
inverse(xDen, xDen)
|
||||
inverse(yDen, yDen)
|
||||
mul(xNum, xNum, xDen)
|
||||
mul(yNum, yNum, yDen)
|
||||
mul(yNum, yNum, y)
|
||||
x.set(xNum)
|
||||
y.set(yNum)
|
||||
}
|
||||
|
||||
// isogenyMapG2 applies 11-isogeny map for BLS12-381 G1 defined at draft-irtf-cfrg-hash-to-curve-06.
|
||||
func isogenyMapG2(e *fp2, x, y *fe2) {
|
||||
if e == nil {
|
||||
e = newFp2()
|
||||
}
|
||||
// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#appendix-C.2
|
||||
params := isogenyConstantsG2
|
||||
degree := 3
|
||||
xNum := new(fe2).set(params[0][degree])
|
||||
xDen := new(fe2).set(params[1][degree])
|
||||
yNum := new(fe2).set(params[2][degree])
|
||||
yDen := new(fe2).set(params[3][degree])
|
||||
for i := degree - 1; i >= 0; i-- {
|
||||
e.mul(xNum, xNum, x)
|
||||
e.mul(xDen, xDen, x)
|
||||
e.mul(yNum, yNum, x)
|
||||
e.mul(yDen, yDen, x)
|
||||
e.add(xNum, xNum, params[0][i])
|
||||
e.add(xDen, xDen, params[1][i])
|
||||
e.add(yNum, yNum, params[2][i])
|
||||
e.add(yDen, yDen, params[3][i])
|
||||
}
|
||||
e.inverse(xDen, xDen)
|
||||
e.inverse(yDen, yDen)
|
||||
e.mul(xNum, xNum, xDen)
|
||||
e.mul(yNum, yNum, yDen)
|
||||
e.mul(yNum, yNum, y)
|
||||
x.set(xNum)
|
||||
y.set(yNum)
|
||||
}
|
||||
|
||||
var isogenyConstantsG1 = [4][16]*fe{
|
||||
{
|
||||
{0x4d18b6f3af00131c, 0x19fa219793fee28c, 0x3f2885f1467f19ae, 0x23dcea34f2ffb304, 0xd15b58d2ffc00054, 0x0913be200a20bef4},
|
||||
{0x898985385cdbbd8b, 0x3c79e43cc7d966aa, 0x1597e193f4cd233a, 0x8637ef1e4d6623ad, 0x11b22deed20d827b, 0x07097bc5998784ad},
|
||||
{0xa542583a480b664b, 0xfc7169c026e568c6, 0x5ba2ef314ed8b5a6, 0x5b5491c05102f0e7, 0xdf6e99707d2a0079, 0x0784151ed7605524},
|
||||
{0x494e212870f72741, 0xab9be52fbda43021, 0x26f5577994e34c3d, 0x049dfee82aefbd60, 0x65dadd7828505289, 0x0e93d431ea011aeb},
|
||||
{0x90ee774bd6a74d45, 0x7ada1c8a41bfb185, 0x0f1a8953b325f464, 0x104c24211be4805c, 0x169139d319ea7a8f, 0x09f20ead8e532bf6},
|
||||
{0x6ddd93e2f43626b7, 0xa5482c9aa1ccd7bd, 0x143245631883f4bd, 0x2e0a94ccf77ec0db, 0xb0282d480e56489f, 0x18f4bfcbb4368929},
|
||||
{0x23c5f0c953402dfd, 0x7a43ff6958ce4fe9, 0x2c390d3d2da5df63, 0xd0df5c98e1f9d70f, 0xffd89869a572b297, 0x1277ffc72f25e8fe},
|
||||
{0x79f4f0490f06a8a6, 0x85f894a88030fd81, 0x12da3054b18b6410, 0xe2a57f6505880d65, 0xbba074f260e400f1, 0x08b76279f621d028},
|
||||
{0xe67245ba78d5b00b, 0x8456ba9a1f186475, 0x7888bff6e6b33bb4, 0xe21585b9a30f86cb, 0x05a69cdcef55feee, 0x09e699dd9adfa5ac},
|
||||
{0x0de5c357bff57107, 0x0a0db4ae6b1a10b2, 0xe256bb67b3b3cd8d, 0x8ad456574e9db24f, 0x0443915f50fd4179, 0x098c4bf7de8b6375},
|
||||
{0xe6b0617e7dd929c7, 0xfe6e37d442537375, 0x1dafdeda137a489e, 0xe4efd1ad3f767ceb, 0x4a51d8667f0fe1cf, 0x054fdf4bbf1d821c},
|
||||
{0x72db2a50658d767b, 0x8abf91faa257b3d5, 0xe969d6833764ab47, 0x464170142a1009eb, 0xb14f01aadb30be2f, 0x18ae6a856f40715d},
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
{0xb962a077fdb0f945, 0xa6a9740fefda13a0, 0xc14d568c3ed6c544, 0xb43fc37b908b133e, 0x9c0b3ac929599016, 0x0165aa6c93ad115f},
|
||||
{0x23279a3ba506c1d9, 0x92cfca0a9465176a, 0x3b294ab13755f0ff, 0x116dda1c5070ae93, 0xed4530924cec2045, 0x083383d6ed81f1ce},
|
||||
{0x9885c2a6449fecfc, 0x4a2b54ccd37733f0, 0x17da9ffd8738c142, 0xa0fba72732b3fafd, 0xff364f36e54b6812, 0x0f29c13c660523e2},
|
||||
{0xe349cc118278f041, 0xd487228f2f3204fb, 0xc9d325849ade5150, 0x43a92bd69c15c2df, 0x1c2c7844bc417be4, 0x12025184f407440c},
|
||||
{0x587f65ae6acb057b, 0x1444ef325140201f, 0xfbf995e71270da49, 0xccda066072436a42, 0x7408904f0f186bb2, 0x13b93c63edf6c015},
|
||||
{0xfb918622cd141920, 0x4a4c64423ecaddb4, 0x0beb232927f7fb26, 0x30f94df6f83a3dc2, 0xaeedd424d780f388, 0x06cc402dd594bbeb},
|
||||
{0xd41f761151b23f8f, 0x32a92465435719b3, 0x64f436e888c62cb9, 0xdf70a9a1f757c6e4, 0x6933a38d5b594c81, 0x0c6f7f7237b46606},
|
||||
{0x693c08747876c8f7, 0x22c9850bf9cf80f0, 0x8e9071dab950c124, 0x89bc62d61c7baf23, 0xbc6be2d8dad57c23, 0x17916987aa14a122},
|
||||
{0x1be3ff439c1316fd, 0x9965243a7571dfa7, 0xc7f7f62962f5cd81, 0x32c6aa9af394361c, 0xbbc2ee18e1c227f4, 0x0c102cbac531bb34},
|
||||
{0x997614c97bacbf07, 0x61f86372b99192c0, 0x5b8c95fc14353fc3, 0xca2b066c2a87492f, 0x16178f5bbf698711, 0x12a6dcd7f0f4e0e8},
|
||||
{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
{0x2b567ff3e2837267, 0x1d4d9e57b958a767, 0xce028fea04bd7373, 0xcc31a30a0b6cd3df, 0x7d7b18a682692693, 0x0d300744d42a0310},
|
||||
{0x99c2555fa542493f, 0xfe7f53cc4874f878, 0x5df0608b8f97608a, 0x14e03832052b49c8, 0x706326a6957dd5a4, 0x0a8dadd9c2414555},
|
||||
{0x13d942922a5cf63a, 0x357e33e36e261e7d, 0xcf05a27c8456088d, 0x0000bd1de7ba50f0, 0x83d0c7532f8c1fde, 0x13f70bf38bbf2905},
|
||||
{0x5c57fd95bfafbdbb, 0x28a359a65e541707, 0x3983ceb4f6360b6d, 0xafe19ff6f97e6d53, 0xb3468f4550192bf7, 0x0bb6cde49d8ba257},
|
||||
{0x590b62c7ff8a513f, 0x314b4ce372cacefd, 0x6bef32ce94b8a800, 0x6ddf84a095713d5f, 0x64eace4cb0982191, 0x0386213c651b888d},
|
||||
{0xa5310a31111bbcdd, 0xa14ac0f5da148982, 0xf9ad9cc95423d2e9, 0xaa6ec095283ee4a7, 0xcf5b1f022e1c9107, 0x01fddf5aed881793},
|
||||
{0x65a572b0d7a7d950, 0xe25c2d8183473a19, 0xc2fcebe7cb877dbd, 0x05b2d36c769a89b0, 0xba12961be86e9efb, 0x07eb1b29c1dfde1f},
|
||||
{0x93e09572f7c4cd24, 0x364e929076795091, 0x8569467e68af51b5, 0xa47da89439f5340f, 0xf4fa918082e44d64, 0x0ad52ba3e6695a79},
|
||||
{0x911429844e0d5f54, 0xd03f51a3516bb233, 0x3d587e5640536e66, 0xfa86d2a3a9a73482, 0xa90ed5adf1ed5537, 0x149c9c326a5e7393},
|
||||
{0x462bbeb03c12921a, 0xdc9af5fa0a274a17, 0x9a558ebde836ebed, 0x649ef8f11a4fae46, 0x8100e1652b3cdc62, 0x1862bd62c291dacb},
|
||||
{0x05c9b8ca89f12c26, 0x0194160fa9b9ac4f, 0x6a643d5a6879fa2c, 0x14665bdd8846e19d, 0xbb1d0d53af3ff6bf, 0x12c7e1c3b28962e5},
|
||||
{0xb55ebf900b8a3e17, 0xfedc77ec1a9201c4, 0x1f07db10ea1a4df4, 0x0dfbd15dc41a594d, 0x389547f2334a5391, 0x02419f98165871a4},
|
||||
{0xb416af000745fc20, 0x8e563e9d1ea6d0f5, 0x7c763e17763a0652, 0x01458ef0159ebbef, 0x8346fe421f96bb13, 0x0d2d7b829ce324d2},
|
||||
{0x93096bb538d64615, 0x6f2a2619951d823a, 0x8f66b3ea59514fa4, 0xf563e63704f7092f, 0x724b136c4cf2d9fa, 0x046959cfcfd0bf49},
|
||||
{0xea748d4b6e405346, 0x91e9079c2c02d58f, 0x41064965946d9b59, 0xa06731f1d2bbe1ee, 0x07f897e267a33f1b, 0x1017290919210e5f},
|
||||
{0x872aa6c17d985097, 0xeecc53161264562a, 0x07afe37afff55002, 0x54759078e5be6838, 0xc4b92d15db8acca8, 0x106d87d1b51d13b9},
|
||||
},
|
||||
{
|
||||
{0xeb6c359d47e52b1c, 0x18ef5f8a10634d60, 0xddfa71a0889d5b7e, 0x723e71dcc5fc1323, 0x52f45700b70d5c69, 0x0a8b981ee47691f1},
|
||||
{0x616a3c4f5535b9fb, 0x6f5f037395dbd911, 0xf25f4cc5e35c65da, 0x3e50dffea3c62658, 0x6a33dca523560776, 0x0fadeff77b6bfe3e},
|
||||
{0x2be9b66df470059c, 0x24a2c159a3d36742, 0x115dbe7ad10c2a37, 0xb6634a652ee5884d, 0x04fe8bb2b8d81af4, 0x01c2a7a256fe9c41},
|
||||
{0xf27bf8ef3b75a386, 0x898b367476c9073f, 0x24482e6b8c2f4e5f, 0xc8e0bbd6fe110806, 0x59b0c17f7631448a, 0x11037cd58b3dbfbd},
|
||||
{0x31c7912ea267eec6, 0x1dbf6f1c5fcdb700, 0xd30d4fe3ba86fdb1, 0x3cae528fbee9a2a4, 0xb1cce69b6aa9ad9a, 0x044393bb632d94fb},
|
||||
{0xc66ef6efeeb5c7e8, 0x9824c289dd72bb55, 0x71b1a4d2f119981d, 0x104fc1aafb0919cc, 0x0e49df01d942a628, 0x096c3a09773272d4},
|
||||
{0x9abc11eb5fadeff4, 0x32dca50a885728f0, 0xfb1fa3721569734c, 0xc4b76271ea6506b3, 0xd466a75599ce728e, 0x0c81d4645f4cb6ed},
|
||||
{0x4199f10e5b8be45b, 0xda64e495b1e87930, 0xcb353efe9b33e4ff, 0x9e9efb24aa6424c6, 0xf08d33680a237465, 0x0d3378023e4c7406},
|
||||
{0x7eb4ae92ec74d3a5, 0xc341b4aa9fac3497, 0x5be603899e907687, 0x03bfd9cca75cbdeb, 0x564c2935a96bfa93, 0x0ef3c33371e2fdb5},
|
||||
{0x7ee91fd449f6ac2e, 0xe5d5bd5cb9357a30, 0x773a8ca5196b1380, 0xd0fda172174ed023, 0x6cb95e0fa776aead, 0x0d22d5a40cec7cff},
|
||||
{0xf727e09285fd8519, 0xdc9d55a83017897b, 0x7549d8bd057894ae, 0x178419613d90d8f8, 0xfce95ebdeb5b490a, 0x0467ffaef23fc49e},
|
||||
{0xc1769e6a7c385f1b, 0x79bc930deac01c03, 0x5461c75a23ede3b5, 0x6e20829e5c230c45, 0x828e0f1e772a53cd, 0x116aefa749127bff},
|
||||
{0x101c10bf2744c10a, 0xbbf18d053a6a3154, 0xa0ecf39ef026f602, 0xfc009d4996dc5153, 0xb9000209d5bd08d3, 0x189e5fe4470cd73c},
|
||||
{0x7ebd546ca1575ed2, 0xe47d5a981d081b55, 0x57b2b625b6d4ca21, 0xb0a1ba04228520cc, 0x98738983c2107ff3, 0x13dddbc4799d81d6},
|
||||
{0x09319f2e39834935, 0x039e952cbdb05c21, 0x55ba77a9a2f76493, 0xfd04e3dfc6086467, 0xfb95832e7d78742e, 0x0ef9c24eccaf5e0e},
|
||||
{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
|
||||
},
|
||||
}
|
||||
|
||||
var isogenyConstantsG2 = [4][4]*fe2{
|
||||
{
|
||||
{
|
||||
fe{0x47f671c71ce05e62, 0x06dd57071206393e, 0x7c80cd2af3fd71a2, 0x048103ea9e6cd062, 0xc54516acc8d037f6, 0x13808f550920ea41},
|
||||
fe{0x47f671c71ce05e62, 0x06dd57071206393e, 0x7c80cd2af3fd71a2, 0x048103ea9e6cd062, 0xc54516acc8d037f6, 0x13808f550920ea41},
|
||||
},
|
||||
{
|
||||
fe{0, 0, 0, 0, 0, 0},
|
||||
fe{0x5fe55555554c71d0, 0x873fffdd236aaaa3, 0x6a6b4619b26ef918, 0x21c2888408874945, 0x2836cda7028cabc5, 0x0ac73310a7fd5abd},
|
||||
},
|
||||
{
|
||||
fe{0x0a0c5555555971c3, 0xdb0c00101f9eaaae, 0xb1fb2f941d797997, 0xd3960742ef416e1c, 0xb70040e2c20556f4, 0x149d7861e581393b},
|
||||
fe{0xaff2aaaaaaa638e8, 0x439fffee91b55551, 0xb535a30cd9377c8c, 0x90e144420443a4a2, 0x941b66d3814655e2, 0x0563998853fead5e},
|
||||
},
|
||||
{
|
||||
fe{0x40aac71c71c725ed, 0x190955557a84e38e, 0xd817050a8f41abc3, 0xd86485d4c87f6fb1, 0x696eb479f885d059, 0x198e1a74328002d2},
|
||||
fe{0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
fe{0, 0, 0, 0, 0, 0},
|
||||
fe{0x1f3affffff13ab97, 0xf25bfc611da3ff3e, 0xca3757cb3819b208, 0x3e6427366f8cec18, 0x03977bc86095b089, 0x04f69db13f39a952},
|
||||
},
|
||||
{
|
||||
fe{0x447600000027552e, 0xdcb8009a43480020, 0x6f7ee9ce4a6e8b59, 0xb10330b7c0a95bc6, 0x6140b1fcfb1e54b7, 0x0381be097f0bb4e1},
|
||||
fe{0x7588ffffffd8557d, 0x41f3ff646e0bffdf, 0xf7b1e8d2ac426aca, 0xb3741acd32dbb6f8, 0xe9daf5b9482d581f, 0x167f53e0ba7431b8},
|
||||
},
|
||||
{
|
||||
fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
|
||||
fe{0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
fe{0, 0, 0, 0, 0, 0},
|
||||
fe{0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
fe{0x96d8f684bdfc77be, 0xb530e4f43b66d0e2, 0x184a88ff379652fd, 0x57cb23ecfae804e1, 0x0fd2e39eada3eba9, 0x08c8055e31c5d5c3},
|
||||
fe{0x96d8f684bdfc77be, 0xb530e4f43b66d0e2, 0x184a88ff379652fd, 0x57cb23ecfae804e1, 0x0fd2e39eada3eba9, 0x08c8055e31c5d5c3},
|
||||
},
|
||||
{
|
||||
fe{0, 0, 0, 0, 0, 0},
|
||||
fe{0xbf0a71c71c91b406, 0x4d6d55d28b7638fd, 0x9d82f98e5f205aee, 0xa27aa27b1d1a18d5, 0x02c3b2b2d2938e86, 0x0c7d13420b09807f},
|
||||
},
|
||||
{
|
||||
fe{0xd7f9555555531c74, 0x21cffff748daaaa8, 0x5a9ad1866c9bbe46, 0x4870a2210221d251, 0x4a0db369c0a32af1, 0x02b1ccc429ff56af},
|
||||
fe{0xe205aaaaaaac8e37, 0xfcdc000768795556, 0x0c96011a8a1537dd, 0x1c06a963f163406e, 0x010df44c82a881e6, 0x174f45260f808feb},
|
||||
},
|
||||
{
|
||||
fe{0xa470bda12f67f35c, 0xc0fe38e23327b425, 0xc9d3d0f2c6f0678d, 0x1c55c9935b5a982e, 0x27f6c0e2f0746764, 0x117c5e6e28aa9054},
|
||||
fe{0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
fe{0x0162fffffa765adf, 0x8f7bea480083fb75, 0x561b3c2259e93611, 0x11e19fc1a9c875d5, 0xca713efc00367660, 0x03c6a03d41da1151},
|
||||
fe{0x0162fffffa765adf, 0x8f7bea480083fb75, 0x561b3c2259e93611, 0x11e19fc1a9c875d5, 0xca713efc00367660, 0x03c6a03d41da1151},
|
||||
},
|
||||
{
|
||||
fe{0, 0, 0, 0, 0, 0},
|
||||
fe{0x5db0fffffd3b02c5, 0xd713f52358ebfdba, 0x5ea60761a84d161a, 0xbb2c75a34ea6c44a, 0x0ac6735921c1119b, 0x0ee3d913bdacfbf6},
|
||||
},
|
||||
{
|
||||
fe{0x66b10000003affc5, 0xcb1400e764ec0030, 0xa73e5eb56fa5d106, 0x8984c913a0fe09a9, 0x11e10afb78ad7f13, 0x05429d0e3e918f52},
|
||||
fe{0x534dffffffc4aae6, 0x5397ff174c67ffcf, 0xbff273eb870b251d, 0xdaf2827152870915, 0x393a9cbaca9e2dc3, 0x14be74dbfaee5748},
|
||||
},
|
||||
{
|
||||
fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
|
||||
fe{0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
},
|
||||
}
|
||||
282
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/pairing.go
generated
vendored
Normal file
282
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/pairing.go
generated
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
// 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
|
||||
|
||||
type pair struct {
|
||||
g1 *PointG1
|
||||
g2 *PointG2
|
||||
}
|
||||
|
||||
func newPair(g1 *PointG1, g2 *PointG2) pair {
|
||||
return pair{g1, g2}
|
||||
}
|
||||
|
||||
// Engine is BLS12-381 elliptic curve pairing engine
|
||||
type Engine struct {
|
||||
G1 *G1
|
||||
G2 *G2
|
||||
fp12 *fp12
|
||||
fp2 *fp2
|
||||
pairingEngineTemp
|
||||
pairs []pair
|
||||
}
|
||||
|
||||
// NewPairingEngine creates new pairing engine instance.
|
||||
func NewPairingEngine() *Engine {
|
||||
fp2 := newFp2()
|
||||
fp6 := newFp6(fp2)
|
||||
fp12 := newFp12(fp6)
|
||||
g1 := NewG1()
|
||||
g2 := newG2(fp2)
|
||||
return &Engine{
|
||||
fp2: fp2,
|
||||
fp12: fp12,
|
||||
G1: g1,
|
||||
G2: g2,
|
||||
pairingEngineTemp: newEngineTemp(),
|
||||
}
|
||||
}
|
||||
|
||||
type pairingEngineTemp struct {
|
||||
t2 [10]*fe2
|
||||
t12 [9]fe12
|
||||
}
|
||||
|
||||
func newEngineTemp() pairingEngineTemp {
|
||||
t2 := [10]*fe2{}
|
||||
for i := 0; i < 10; i++ {
|
||||
t2[i] = &fe2{}
|
||||
}
|
||||
t12 := [9]fe12{}
|
||||
return pairingEngineTemp{t2, t12}
|
||||
}
|
||||
|
||||
// AddPair adds a g1, g2 point pair to pairing engine
|
||||
func (e *Engine) AddPair(g1 *PointG1, g2 *PointG2) *Engine {
|
||||
p := newPair(g1, g2)
|
||||
if !e.isZero(p) {
|
||||
e.affine(p)
|
||||
e.pairs = append(e.pairs, p)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// AddPairInv adds a G1, G2 point pair to pairing engine. G1 point is negated.
|
||||
func (e *Engine) AddPairInv(g1 *PointG1, g2 *PointG2) *Engine {
|
||||
e.G1.Neg(g1, g1)
|
||||
e.AddPair(g1, g2)
|
||||
return e
|
||||
}
|
||||
|
||||
// Reset deletes added pairs.
|
||||
func (e *Engine) Reset() *Engine {
|
||||
e.pairs = []pair{}
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Engine) isZero(p pair) bool {
|
||||
return e.G1.IsZero(p.g1) || e.G2.IsZero(p.g2)
|
||||
}
|
||||
|
||||
func (e *Engine) affine(p pair) {
|
||||
e.G1.Affine(p.g1)
|
||||
e.G2.Affine(p.g2)
|
||||
}
|
||||
|
||||
func (e *Engine) doublingStep(coeff *[3]fe2, r *PointG2) {
|
||||
// Adaptation of Formula 3 in https://eprint.iacr.org/2010/526.pdf
|
||||
fp2 := e.fp2
|
||||
t := e.t2
|
||||
fp2.mul(t[0], &r[0], &r[1])
|
||||
fp2.mulByFq(t[0], t[0], twoInv)
|
||||
fp2.square(t[1], &r[1])
|
||||
fp2.square(t[2], &r[2])
|
||||
fp2.double(t[7], t[2])
|
||||
fp2.add(t[7], t[7], t[2])
|
||||
fp2.mulByB(t[3], t[7])
|
||||
fp2.double(t[4], t[3])
|
||||
fp2.add(t[4], t[4], t[3])
|
||||
fp2.add(t[5], t[1], t[4])
|
||||
fp2.mulByFq(t[5], t[5], twoInv)
|
||||
fp2.add(t[6], &r[1], &r[2])
|
||||
fp2.square(t[6], t[6])
|
||||
fp2.add(t[7], t[2], t[1])
|
||||
fp2.sub(t[6], t[6], t[7])
|
||||
fp2.sub(&coeff[0], t[3], t[1])
|
||||
fp2.square(t[7], &r[0])
|
||||
fp2.sub(t[4], t[1], t[4])
|
||||
fp2.mul(&r[0], t[4], t[0])
|
||||
fp2.square(t[2], t[3])
|
||||
fp2.double(t[3], t[2])
|
||||
fp2.add(t[3], t[3], t[2])
|
||||
fp2.square(t[5], t[5])
|
||||
fp2.sub(&r[1], t[5], t[3])
|
||||
fp2.mul(&r[2], t[1], t[6])
|
||||
fp2.double(t[0], t[7])
|
||||
fp2.add(&coeff[1], t[0], t[7])
|
||||
fp2.neg(&coeff[2], t[6])
|
||||
}
|
||||
|
||||
func (e *Engine) additionStep(coeff *[3]fe2, r, q *PointG2) {
|
||||
// Algorithm 12 in https://eprint.iacr.org/2010/526.pdf
|
||||
fp2 := e.fp2
|
||||
t := e.t2
|
||||
fp2.mul(t[0], &q[1], &r[2])
|
||||
fp2.neg(t[0], t[0])
|
||||
fp2.add(t[0], t[0], &r[1])
|
||||
fp2.mul(t[1], &q[0], &r[2])
|
||||
fp2.neg(t[1], t[1])
|
||||
fp2.add(t[1], t[1], &r[0])
|
||||
fp2.square(t[2], t[0])
|
||||
fp2.square(t[3], t[1])
|
||||
fp2.mul(t[4], t[1], t[3])
|
||||
fp2.mul(t[2], &r[2], t[2])
|
||||
fp2.mul(t[3], &r[0], t[3])
|
||||
fp2.double(t[5], t[3])
|
||||
fp2.sub(t[5], t[4], t[5])
|
||||
fp2.add(t[5], t[5], t[2])
|
||||
fp2.mul(&r[0], t[1], t[5])
|
||||
fp2.sub(t[2], t[3], t[5])
|
||||
fp2.mul(t[2], t[2], t[0])
|
||||
fp2.mul(t[3], &r[1], t[4])
|
||||
fp2.sub(&r[1], t[2], t[3])
|
||||
fp2.mul(&r[2], &r[2], t[4])
|
||||
fp2.mul(t[2], t[1], &q[1])
|
||||
fp2.mul(t[3], t[0], &q[0])
|
||||
fp2.sub(&coeff[0], t[3], t[2])
|
||||
fp2.neg(&coeff[1], t[0])
|
||||
coeff[2].set(t[1])
|
||||
}
|
||||
|
||||
func (e *Engine) preCompute(ellCoeffs *[68][3]fe2, twistPoint *PointG2) {
|
||||
// Algorithm 5 in https://eprint.iacr.org/2019/077.pdf
|
||||
if e.G2.IsZero(twistPoint) {
|
||||
return
|
||||
}
|
||||
r := new(PointG2).Set(twistPoint)
|
||||
j := 0
|
||||
for i := x.BitLen() - 2; i >= 0; i-- {
|
||||
e.doublingStep(&ellCoeffs[j], r)
|
||||
if x.Bit(i) != 0 {
|
||||
j++
|
||||
ellCoeffs[j] = fe6{}
|
||||
e.additionStep(&ellCoeffs[j], r, twistPoint)
|
||||
}
|
||||
j++
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Engine) millerLoop(f *fe12) {
|
||||
pairs := e.pairs
|
||||
ellCoeffs := make([][68][3]fe2, len(pairs))
|
||||
for i := 0; i < len(pairs); i++ {
|
||||
e.preCompute(&ellCoeffs[i], pairs[i].g2)
|
||||
}
|
||||
fp12, fp2 := e.fp12, e.fp2
|
||||
t := e.t2
|
||||
f.one()
|
||||
j := 0
|
||||
for i := 62; /* x.BitLen() - 2 */ i >= 0; i-- {
|
||||
if i != 62 {
|
||||
fp12.square(f, f)
|
||||
}
|
||||
for i := 0; i <= len(pairs)-1; i++ {
|
||||
fp2.mulByFq(t[0], &ellCoeffs[i][j][2], &pairs[i].g1[1])
|
||||
fp2.mulByFq(t[1], &ellCoeffs[i][j][1], &pairs[i].g1[0])
|
||||
fp12.mulBy014Assign(f, &ellCoeffs[i][j][0], t[1], t[0])
|
||||
}
|
||||
if x.Bit(i) != 0 {
|
||||
j++
|
||||
for i := 0; i <= len(pairs)-1; i++ {
|
||||
fp2.mulByFq(t[0], &ellCoeffs[i][j][2], &pairs[i].g1[1])
|
||||
fp2.mulByFq(t[1], &ellCoeffs[i][j][1], &pairs[i].g1[0])
|
||||
fp12.mulBy014Assign(f, &ellCoeffs[i][j][0], t[1], t[0])
|
||||
}
|
||||
}
|
||||
j++
|
||||
}
|
||||
fp12.conjugate(f, f)
|
||||
}
|
||||
|
||||
func (e *Engine) exp(c, a *fe12) {
|
||||
fp12 := e.fp12
|
||||
fp12.cyclotomicExp(c, a, x)
|
||||
fp12.conjugate(c, c)
|
||||
}
|
||||
|
||||
func (e *Engine) finalExp(f *fe12) {
|
||||
fp12 := e.fp12
|
||||
t := e.t12
|
||||
// easy part
|
||||
fp12.frobeniusMap(&t[0], f, 6)
|
||||
fp12.inverse(&t[1], f)
|
||||
fp12.mul(&t[2], &t[0], &t[1])
|
||||
t[1].set(&t[2])
|
||||
fp12.frobeniusMapAssign(&t[2], 2)
|
||||
fp12.mulAssign(&t[2], &t[1])
|
||||
fp12.cyclotomicSquare(&t[1], &t[2])
|
||||
fp12.conjugate(&t[1], &t[1])
|
||||
// hard part
|
||||
e.exp(&t[3], &t[2])
|
||||
fp12.cyclotomicSquare(&t[4], &t[3])
|
||||
fp12.mul(&t[5], &t[1], &t[3])
|
||||
e.exp(&t[1], &t[5])
|
||||
e.exp(&t[0], &t[1])
|
||||
e.exp(&t[6], &t[0])
|
||||
fp12.mulAssign(&t[6], &t[4])
|
||||
e.exp(&t[4], &t[6])
|
||||
fp12.conjugate(&t[5], &t[5])
|
||||
fp12.mulAssign(&t[4], &t[5])
|
||||
fp12.mulAssign(&t[4], &t[2])
|
||||
fp12.conjugate(&t[5], &t[2])
|
||||
fp12.mulAssign(&t[1], &t[2])
|
||||
fp12.frobeniusMapAssign(&t[1], 3)
|
||||
fp12.mulAssign(&t[6], &t[5])
|
||||
fp12.frobeniusMapAssign(&t[6], 1)
|
||||
fp12.mulAssign(&t[3], &t[0])
|
||||
fp12.frobeniusMapAssign(&t[3], 2)
|
||||
fp12.mulAssign(&t[3], &t[1])
|
||||
fp12.mulAssign(&t[3], &t[6])
|
||||
fp12.mul(f, &t[3], &t[4])
|
||||
}
|
||||
|
||||
func (e *Engine) calculate() *fe12 {
|
||||
f := e.fp12.one()
|
||||
if len(e.pairs) == 0 {
|
||||
return f
|
||||
}
|
||||
e.millerLoop(f)
|
||||
e.finalExp(f)
|
||||
return f
|
||||
}
|
||||
|
||||
// Check computes pairing and checks if result is equal to one
|
||||
func (e *Engine) Check() bool {
|
||||
return e.calculate().isOne()
|
||||
}
|
||||
|
||||
// Result computes pairing and returns target group element as result.
|
||||
func (e *Engine) Result() *E {
|
||||
r := e.calculate()
|
||||
e.Reset()
|
||||
return r
|
||||
}
|
||||
|
||||
// GT returns target group instance.
|
||||
func (e *Engine) GT() *GT {
|
||||
return NewGT()
|
||||
}
|
||||
158
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/swu.go
generated
vendored
Normal file
158
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/swu.go
generated
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
// 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
|
||||
|
||||
// swuMapG1 is implementation of Simplified Shallue-van de Woestijne-Ulas Method
|
||||
// follows the implementation at draft-irtf-cfrg-hash-to-curve-06.
|
||||
func swuMapG1(u *fe) (*fe, *fe) {
|
||||
var params = swuParamsForG1
|
||||
var tv [4]*fe
|
||||
for i := 0; i < 4; i++ {
|
||||
tv[i] = new(fe)
|
||||
}
|
||||
square(tv[0], u)
|
||||
mul(tv[0], tv[0], params.z)
|
||||
square(tv[1], tv[0])
|
||||
x1 := new(fe)
|
||||
add(x1, tv[0], tv[1])
|
||||
inverse(x1, x1)
|
||||
e1 := x1.isZero()
|
||||
one := new(fe).one()
|
||||
add(x1, x1, one)
|
||||
if e1 {
|
||||
x1.set(params.zInv)
|
||||
}
|
||||
mul(x1, x1, params.minusBOverA)
|
||||
gx1 := new(fe)
|
||||
square(gx1, x1)
|
||||
add(gx1, gx1, params.a)
|
||||
mul(gx1, gx1, x1)
|
||||
add(gx1, gx1, params.b)
|
||||
x2 := new(fe)
|
||||
mul(x2, tv[0], x1)
|
||||
mul(tv[1], tv[0], tv[1])
|
||||
gx2 := new(fe)
|
||||
mul(gx2, gx1, tv[1])
|
||||
e2 := !isQuadraticNonResidue(gx1)
|
||||
x, y2 := new(fe), new(fe)
|
||||
if e2 {
|
||||
x.set(x1)
|
||||
y2.set(gx1)
|
||||
} else {
|
||||
x.set(x2)
|
||||
y2.set(gx2)
|
||||
}
|
||||
y := new(fe)
|
||||
sqrt(y, y2)
|
||||
if y.sign() != u.sign() {
|
||||
neg(y, y)
|
||||
}
|
||||
return x, y
|
||||
}
|
||||
|
||||
// swuMapG2 is implementation of Simplified Shallue-van de Woestijne-Ulas Method
|
||||
// defined at draft-irtf-cfrg-hash-to-curve-06.
|
||||
func swuMapG2(e *fp2, u *fe2) (*fe2, *fe2) {
|
||||
if e == nil {
|
||||
e = newFp2()
|
||||
}
|
||||
params := swuParamsForG2
|
||||
var tv [4]*fe2
|
||||
for i := 0; i < 4; i++ {
|
||||
tv[i] = e.new()
|
||||
}
|
||||
e.square(tv[0], u)
|
||||
e.mul(tv[0], tv[0], params.z)
|
||||
e.square(tv[1], tv[0])
|
||||
x1 := e.new()
|
||||
e.add(x1, tv[0], tv[1])
|
||||
e.inverse(x1, x1)
|
||||
e1 := x1.isZero()
|
||||
e.add(x1, x1, e.one())
|
||||
if e1 {
|
||||
x1.set(params.zInv)
|
||||
}
|
||||
e.mul(x1, x1, params.minusBOverA)
|
||||
gx1 := e.new()
|
||||
e.square(gx1, x1)
|
||||
e.add(gx1, gx1, params.a)
|
||||
e.mul(gx1, gx1, x1)
|
||||
e.add(gx1, gx1, params.b)
|
||||
x2 := e.new()
|
||||
e.mul(x2, tv[0], x1)
|
||||
e.mul(tv[1], tv[0], tv[1])
|
||||
gx2 := e.new()
|
||||
e.mul(gx2, gx1, tv[1])
|
||||
e2 := !e.isQuadraticNonResidue(gx1)
|
||||
x, y2 := e.new(), e.new()
|
||||
if e2 {
|
||||
x.set(x1)
|
||||
y2.set(gx1)
|
||||
} else {
|
||||
x.set(x2)
|
||||
y2.set(gx2)
|
||||
}
|
||||
y := e.new()
|
||||
e.sqrt(y, y2)
|
||||
if y.sign() != u.sign() {
|
||||
e.neg(y, y)
|
||||
}
|
||||
return x, y
|
||||
}
|
||||
|
||||
var swuParamsForG1 = struct {
|
||||
z *fe
|
||||
zInv *fe
|
||||
a *fe
|
||||
b *fe
|
||||
minusBOverA *fe
|
||||
}{
|
||||
a: &fe{0x2f65aa0e9af5aa51, 0x86464c2d1e8416c3, 0xb85ce591b7bd31e2, 0x27e11c91b5f24e7c, 0x28376eda6bfc1835, 0x155455c3e5071d85},
|
||||
b: &fe{0xfb996971fe22a1e0, 0x9aa93eb35b742d6f, 0x8c476013de99c5c4, 0x873e27c3a221e571, 0xca72b5e45a52d888, 0x06824061418a386b},
|
||||
z: &fe{0x886c00000023ffdc, 0x0f70008d3090001d, 0x77672417ed5828c3, 0x9dac23e943dc1740, 0x50553f1b9c131521, 0x078c712fbe0ab6e8},
|
||||
zInv: &fe{0x0e8a2e8ba2e83e10, 0x5b28ba2ca4d745d1, 0x678cd5473847377a, 0x4c506dd8a8076116, 0x9bcb227d79284139, 0x0e8d3154b0ba099a},
|
||||
minusBOverA: &fe{0x052583c93555a7fe, 0x3b40d72430f93c82, 0x1b75faa0105ec983, 0x2527e7dc63851767, 0x99fffd1f34fc181d, 0x097cab54770ca0d3},
|
||||
}
|
||||
|
||||
var swuParamsForG2 = struct {
|
||||
z *fe2
|
||||
zInv *fe2
|
||||
a *fe2
|
||||
b *fe2
|
||||
minusBOverA *fe2
|
||||
}{
|
||||
a: &fe2{
|
||||
fe{0, 0, 0, 0, 0, 0},
|
||||
fe{0xe53a000003135242, 0x01080c0fdef80285, 0xe7889edbe340f6bd, 0x0b51375126310601, 0x02d6985717c744ab, 0x1220b4e979ea5467},
|
||||
},
|
||||
b: &fe2{
|
||||
fe{0x22ea00000cf89db2, 0x6ec832df71380aa4, 0x6e1b94403db5a66e, 0x75bf3c53a79473ba, 0x3dd3a569412c0a34, 0x125cdb5e74dc4fd1},
|
||||
fe{0x22ea00000cf89db2, 0x6ec832df71380aa4, 0x6e1b94403db5a66e, 0x75bf3c53a79473ba, 0x3dd3a569412c0a34, 0x125cdb5e74dc4fd1},
|
||||
},
|
||||
z: &fe2{
|
||||
fe{0x87ebfffffff9555c, 0x656fffe5da8ffffa, 0x0fd0749345d33ad2, 0xd951e663066576f4, 0xde291a3d41e980d3, 0x0815664c7dfe040d},
|
||||
fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206},
|
||||
},
|
||||
zInv: &fe2{
|
||||
fe{0xacd0000000011110, 0x9dd9999dc88ccccd, 0xb5ca2ac9b76352bf, 0xf1b574bcf4bc90ce, 0x42dab41f28a77081, 0x132fc6ac14cd1e12},
|
||||
fe{0xe396ffffffff2223, 0x4fbf332fcd0d9998, 0x0c4bbd3c1aff4cc4, 0x6b9c91267926ca58, 0x29ae4da6aef7f496, 0x10692e942f195791},
|
||||
},
|
||||
minusBOverA: &fe2{
|
||||
fe{0x903c555555474fb3, 0x5f98cc95ce451105, 0x9f8e582eefe0fade, 0xc68946b6aebbd062, 0x467a4ad10ee6de53, 0x0e7146f483e23a05},
|
||||
fe{0x29c2aaaaaab85af8, 0xbf133368e30eeefa, 0xc7a27a7206cffb45, 0x9dee04ce44c9425c, 0x04a15ce53464ce83, 0x0b8fcaf5b59dac95},
|
||||
},
|
||||
}
|
||||
45
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/utils.go
generated
vendored
Normal file
45
vendor/github.com/ethereum/go-ethereum/crypto/bls12381/utils.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
// 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"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
func bigFromHex(hex string) *big.Int {
|
||||
return new(big.Int).SetBytes(common.FromHex(hex))
|
||||
}
|
||||
|
||||
// decodeFieldElement expects 64 byte input with zero top 16 bytes,
|
||||
// returns lower 48 bytes.
|
||||
func decodeFieldElement(in []byte) ([]byte, error) {
|
||||
if len(in) != 64 {
|
||||
return nil, errors.New("invalid field element length")
|
||||
}
|
||||
// check top bytes
|
||||
for i := 0; i < 16; i++ {
|
||||
if in[i] != byte(0x00) {
|
||||
return nil, errors.New("invalid field element top bytes")
|
||||
}
|
||||
}
|
||||
out := make([]byte, 48)
|
||||
copy(out[:], in[16:])
|
||||
return out, nil
|
||||
}
|
||||
28
vendor/github.com/ethereum/go-ethereum/crypto/bn256/LICENSE
generated
vendored
Normal file
28
vendor/github.com/ethereum/go-ethereum/crypto/bn256/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
Copyright (c) 2018 Péter Szilágyi. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
26
vendor/github.com/ethereum/go-ethereum/crypto/bn256/bn256_fast.go
generated
vendored
Normal file
26
vendor/github.com/ethereum/go-ethereum/crypto/bn256/bn256_fast.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright 2018 Péter Szilágyi. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be found
|
||||
// in the LICENSE file.
|
||||
|
||||
//go:build amd64 || arm64
|
||||
// +build amd64 arm64
|
||||
|
||||
// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve.
|
||||
package bn256
|
||||
|
||||
import (
|
||||
bn256cf "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
|
||||
)
|
||||
|
||||
// G1 is an abstract cyclic group. The zero value is suitable for use as the
|
||||
// output of an operation, but cannot be used as an input.
|
||||
type G1 = bn256cf.G1
|
||||
|
||||
// G2 is an abstract cyclic group. The zero value is suitable for use as the
|
||||
// output of an operation, but cannot be used as an input.
|
||||
type G2 = bn256cf.G2
|
||||
|
||||
// PairingCheck calculates the Optimal Ate pairing for a set of points.
|
||||
func PairingCheck(a []*G1, b []*G2) bool {
|
||||
return bn256cf.PairingCheck(a, b)
|
||||
}
|
||||
24
vendor/github.com/ethereum/go-ethereum/crypto/bn256/bn256_slow.go
generated
vendored
Normal file
24
vendor/github.com/ethereum/go-ethereum/crypto/bn256/bn256_slow.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright 2018 Péter Szilágyi. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be found
|
||||
// in the LICENSE file.
|
||||
|
||||
//go:build !amd64 && !arm64
|
||||
// +build !amd64,!arm64
|
||||
|
||||
// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve.
|
||||
package bn256
|
||||
|
||||
import bn256 "github.com/ethereum/go-ethereum/crypto/bn256/google"
|
||||
|
||||
// G1 is an abstract cyclic group. The zero value is suitable for use as the
|
||||
// output of an operation, but cannot be used as an input.
|
||||
type G1 = bn256.G1
|
||||
|
||||
// G2 is an abstract cyclic group. The zero value is suitable for use as the
|
||||
// output of an operation, but cannot be used as an input.
|
||||
type G2 = bn256.G2
|
||||
|
||||
// PairingCheck calculates the Optimal Ate pairing for a set of points.
|
||||
func PairingCheck(a []*G1, b []*G2) bool {
|
||||
return bn256.PairingCheck(a, b)
|
||||
}
|
||||
27
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/LICENSE
generated
vendored
Normal file
27
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
495
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/bn256.go
generated
vendored
Normal file
495
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/bn256.go
generated
vendored
Normal file
@@ -0,0 +1,495 @@
|
||||
// Package bn256 implements a particular bilinear group at the 128-bit security
|
||||
// level.
|
||||
//
|
||||
// Bilinear groups are the basis of many of the new cryptographic protocols that
|
||||
// have been proposed over the past decade. They consist of a triplet of groups
|
||||
// (G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ (where gₓ
|
||||
// is a generator of the respective group). That function is called a pairing
|
||||
// function.
|
||||
//
|
||||
// This package specifically implements the Optimal Ate pairing over a 256-bit
|
||||
// Barreto-Naehrig curve as described in
|
||||
// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is not
|
||||
// compatible with the implementation described in that paper, as different
|
||||
// parameters are chosen.
|
||||
//
|
||||
// (This package previously claimed to operate at a 128-bit security level.
|
||||
// However, recent improvements in attacks mean that is no longer true. See
|
||||
// https://moderncrypto.org/mail-archive/curves/2016/000740.html.)
|
||||
package bn256
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func randomK(r io.Reader) (k *big.Int, err error) {
|
||||
for {
|
||||
k, err = rand.Int(r, Order)
|
||||
if err != nil || k.Sign() > 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// G1 is an abstract cyclic group. The zero value is suitable for use as the
|
||||
// output of an operation, but cannot be used as an input.
|
||||
type G1 struct {
|
||||
p *curvePoint
|
||||
}
|
||||
|
||||
// RandomG1 returns x and g₁ˣ where x is a random, non-zero number read from r.
|
||||
func RandomG1(r io.Reader) (*big.Int, *G1, error) {
|
||||
k, err := randomK(r)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return k, new(G1).ScalarBaseMult(k), nil
|
||||
}
|
||||
|
||||
func (g *G1) String() string {
|
||||
return "bn256.G1" + g.p.String()
|
||||
}
|
||||
|
||||
// ScalarBaseMult sets e to g*k where g is the generator of the group and then
|
||||
// returns e.
|
||||
func (e *G1) ScalarBaseMult(k *big.Int) *G1 {
|
||||
if e.p == nil {
|
||||
e.p = &curvePoint{}
|
||||
}
|
||||
e.p.Mul(curveGen, k)
|
||||
return e
|
||||
}
|
||||
|
||||
// ScalarMult sets e to a*k and then returns e.
|
||||
func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 {
|
||||
if e.p == nil {
|
||||
e.p = &curvePoint{}
|
||||
}
|
||||
e.p.Mul(a.p, k)
|
||||
return e
|
||||
}
|
||||
|
||||
// Add sets e to a+b and then returns e.
|
||||
func (e *G1) Add(a, b *G1) *G1 {
|
||||
if e.p == nil {
|
||||
e.p = &curvePoint{}
|
||||
}
|
||||
e.p.Add(a.p, b.p)
|
||||
return e
|
||||
}
|
||||
|
||||
// Neg sets e to -a and then returns e.
|
||||
func (e *G1) Neg(a *G1) *G1 {
|
||||
if e.p == nil {
|
||||
e.p = &curvePoint{}
|
||||
}
|
||||
e.p.Neg(a.p)
|
||||
return e
|
||||
}
|
||||
|
||||
// Set sets e to a and then returns e.
|
||||
func (e *G1) Set(a *G1) *G1 {
|
||||
if e.p == nil {
|
||||
e.p = &curvePoint{}
|
||||
}
|
||||
e.p.Set(a.p)
|
||||
return e
|
||||
}
|
||||
|
||||
// Marshal converts e to a byte slice.
|
||||
func (e *G1) Marshal() []byte {
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8
|
||||
|
||||
if e.p == nil {
|
||||
e.p = &curvePoint{}
|
||||
}
|
||||
|
||||
e.p.MakeAffine()
|
||||
ret := make([]byte, numBytes*2)
|
||||
if e.p.IsInfinity() {
|
||||
return ret
|
||||
}
|
||||
temp := &gfP{}
|
||||
|
||||
montDecode(temp, &e.p.x)
|
||||
temp.Marshal(ret)
|
||||
montDecode(temp, &e.p.y)
|
||||
temp.Marshal(ret[numBytes:])
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Unmarshal sets e to the result of converting the output of Marshal back into
|
||||
// a group element and then returns e.
|
||||
func (e *G1) Unmarshal(m []byte) ([]byte, error) {
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8
|
||||
if len(m) < 2*numBytes {
|
||||
return nil, errors.New("bn256: not enough data")
|
||||
}
|
||||
// Unmarshal the points and check their caps
|
||||
if e.p == nil {
|
||||
e.p = &curvePoint{}
|
||||
} else {
|
||||
e.p.x, e.p.y = gfP{0}, gfP{0}
|
||||
}
|
||||
var err error
|
||||
if err = e.p.x.Unmarshal(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.y.Unmarshal(m[numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Encode into Montgomery form and ensure it's on the curve
|
||||
montEncode(&e.p.x, &e.p.x)
|
||||
montEncode(&e.p.y, &e.p.y)
|
||||
|
||||
zero := gfP{0}
|
||||
if e.p.x == zero && e.p.y == zero {
|
||||
// This is the point at infinity.
|
||||
e.p.y = *newGFp(1)
|
||||
e.p.z = gfP{0}
|
||||
e.p.t = gfP{0}
|
||||
} else {
|
||||
e.p.z = *newGFp(1)
|
||||
e.p.t = *newGFp(1)
|
||||
|
||||
if !e.p.IsOnCurve() {
|
||||
return nil, errors.New("bn256: malformed point")
|
||||
}
|
||||
}
|
||||
return m[2*numBytes:], nil
|
||||
}
|
||||
|
||||
// G2 is an abstract cyclic group. The zero value is suitable for use as the
|
||||
// output of an operation, but cannot be used as an input.
|
||||
type G2 struct {
|
||||
p *twistPoint
|
||||
}
|
||||
|
||||
// RandomG2 returns x and g₂ˣ where x is a random, non-zero number read from r.
|
||||
func RandomG2(r io.Reader) (*big.Int, *G2, error) {
|
||||
k, err := randomK(r)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return k, new(G2).ScalarBaseMult(k), nil
|
||||
}
|
||||
|
||||
func (e *G2) String() string {
|
||||
return "bn256.G2" + e.p.String()
|
||||
}
|
||||
|
||||
// ScalarBaseMult sets e to g*k where g is the generator of the group and then
|
||||
// returns out.
|
||||
func (e *G2) ScalarBaseMult(k *big.Int) *G2 {
|
||||
if e.p == nil {
|
||||
e.p = &twistPoint{}
|
||||
}
|
||||
e.p.Mul(twistGen, k)
|
||||
return e
|
||||
}
|
||||
|
||||
// ScalarMult sets e to a*k and then returns e.
|
||||
func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 {
|
||||
if e.p == nil {
|
||||
e.p = &twistPoint{}
|
||||
}
|
||||
e.p.Mul(a.p, k)
|
||||
return e
|
||||
}
|
||||
|
||||
// Add sets e to a+b and then returns e.
|
||||
func (e *G2) Add(a, b *G2) *G2 {
|
||||
if e.p == nil {
|
||||
e.p = &twistPoint{}
|
||||
}
|
||||
e.p.Add(a.p, b.p)
|
||||
return e
|
||||
}
|
||||
|
||||
// Neg sets e to -a and then returns e.
|
||||
func (e *G2) Neg(a *G2) *G2 {
|
||||
if e.p == nil {
|
||||
e.p = &twistPoint{}
|
||||
}
|
||||
e.p.Neg(a.p)
|
||||
return e
|
||||
}
|
||||
|
||||
// Set sets e to a and then returns e.
|
||||
func (e *G2) Set(a *G2) *G2 {
|
||||
if e.p == nil {
|
||||
e.p = &twistPoint{}
|
||||
}
|
||||
e.p.Set(a.p)
|
||||
return e
|
||||
}
|
||||
|
||||
// Marshal converts e into a byte slice.
|
||||
func (e *G2) Marshal() []byte {
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8
|
||||
|
||||
if e.p == nil {
|
||||
e.p = &twistPoint{}
|
||||
}
|
||||
|
||||
e.p.MakeAffine()
|
||||
ret := make([]byte, numBytes*4)
|
||||
if e.p.IsInfinity() {
|
||||
return ret
|
||||
}
|
||||
temp := &gfP{}
|
||||
|
||||
montDecode(temp, &e.p.x.x)
|
||||
temp.Marshal(ret)
|
||||
montDecode(temp, &e.p.x.y)
|
||||
temp.Marshal(ret[numBytes:])
|
||||
montDecode(temp, &e.p.y.x)
|
||||
temp.Marshal(ret[2*numBytes:])
|
||||
montDecode(temp, &e.p.y.y)
|
||||
temp.Marshal(ret[3*numBytes:])
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Unmarshal sets e to the result of converting the output of Marshal back into
|
||||
// a group element and then returns e.
|
||||
func (e *G2) Unmarshal(m []byte) ([]byte, error) {
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8
|
||||
if len(m) < 4*numBytes {
|
||||
return nil, errors.New("bn256: not enough data")
|
||||
}
|
||||
// Unmarshal the points and check their caps
|
||||
if e.p == nil {
|
||||
e.p = &twistPoint{}
|
||||
}
|
||||
var err error
|
||||
if err = e.p.x.x.Unmarshal(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.x.y.Unmarshal(m[numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.y.x.Unmarshal(m[2*numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.y.y.Unmarshal(m[3*numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Encode into Montgomery form and ensure it's on the curve
|
||||
montEncode(&e.p.x.x, &e.p.x.x)
|
||||
montEncode(&e.p.x.y, &e.p.x.y)
|
||||
montEncode(&e.p.y.x, &e.p.y.x)
|
||||
montEncode(&e.p.y.y, &e.p.y.y)
|
||||
|
||||
if e.p.x.IsZero() && e.p.y.IsZero() {
|
||||
// This is the point at infinity.
|
||||
e.p.y.SetOne()
|
||||
e.p.z.SetZero()
|
||||
e.p.t.SetZero()
|
||||
} else {
|
||||
e.p.z.SetOne()
|
||||
e.p.t.SetOne()
|
||||
|
||||
if !e.p.IsOnCurve() {
|
||||
return nil, errors.New("bn256: malformed point")
|
||||
}
|
||||
}
|
||||
return m[4*numBytes:], nil
|
||||
}
|
||||
|
||||
// GT is an abstract cyclic group. The zero value is suitable for use as the
|
||||
// output of an operation, but cannot be used as an input.
|
||||
type GT struct {
|
||||
p *gfP12
|
||||
}
|
||||
|
||||
// Pair calculates an Optimal Ate pairing.
|
||||
func Pair(g1 *G1, g2 *G2) *GT {
|
||||
return >{optimalAte(g2.p, g1.p)}
|
||||
}
|
||||
|
||||
// PairingCheck calculates the Optimal Ate pairing for a set of points.
|
||||
func PairingCheck(a []*G1, b []*G2) bool {
|
||||
acc := new(gfP12)
|
||||
acc.SetOne()
|
||||
|
||||
for i := 0; i < len(a); i++ {
|
||||
if a[i].p.IsInfinity() || b[i].p.IsInfinity() {
|
||||
continue
|
||||
}
|
||||
acc.Mul(acc, miller(b[i].p, a[i].p))
|
||||
}
|
||||
return finalExponentiation(acc).IsOne()
|
||||
}
|
||||
|
||||
// Miller applies Miller's algorithm, which is a bilinear function from the
|
||||
// source groups to F_p^12. Miller(g1, g2).Finalize() is equivalent to Pair(g1,
|
||||
// g2).
|
||||
func Miller(g1 *G1, g2 *G2) *GT {
|
||||
return >{miller(g2.p, g1.p)}
|
||||
}
|
||||
|
||||
func (g *GT) String() string {
|
||||
return "bn256.GT" + g.p.String()
|
||||
}
|
||||
|
||||
// ScalarMult sets e to a*k and then returns e.
|
||||
func (e *GT) ScalarMult(a *GT, k *big.Int) *GT {
|
||||
if e.p == nil {
|
||||
e.p = &gfP12{}
|
||||
}
|
||||
e.p.Exp(a.p, k)
|
||||
return e
|
||||
}
|
||||
|
||||
// Add sets e to a+b and then returns e.
|
||||
func (e *GT) Add(a, b *GT) *GT {
|
||||
if e.p == nil {
|
||||
e.p = &gfP12{}
|
||||
}
|
||||
e.p.Mul(a.p, b.p)
|
||||
return e
|
||||
}
|
||||
|
||||
// Neg sets e to -a and then returns e.
|
||||
func (e *GT) Neg(a *GT) *GT {
|
||||
if e.p == nil {
|
||||
e.p = &gfP12{}
|
||||
}
|
||||
e.p.Conjugate(a.p)
|
||||
return e
|
||||
}
|
||||
|
||||
// Set sets e to a and then returns e.
|
||||
func (e *GT) Set(a *GT) *GT {
|
||||
if e.p == nil {
|
||||
e.p = &gfP12{}
|
||||
}
|
||||
e.p.Set(a.p)
|
||||
return e
|
||||
}
|
||||
|
||||
// Finalize is a linear function from F_p^12 to GT.
|
||||
func (e *GT) Finalize() *GT {
|
||||
ret := finalExponentiation(e.p)
|
||||
e.p.Set(ret)
|
||||
return e
|
||||
}
|
||||
|
||||
// Marshal converts e into a byte slice.
|
||||
func (e *GT) Marshal() []byte {
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8
|
||||
|
||||
if e.p == nil {
|
||||
e.p = &gfP12{}
|
||||
e.p.SetOne()
|
||||
}
|
||||
|
||||
ret := make([]byte, numBytes*12)
|
||||
temp := &gfP{}
|
||||
|
||||
montDecode(temp, &e.p.x.x.x)
|
||||
temp.Marshal(ret)
|
||||
montDecode(temp, &e.p.x.x.y)
|
||||
temp.Marshal(ret[numBytes:])
|
||||
montDecode(temp, &e.p.x.y.x)
|
||||
temp.Marshal(ret[2*numBytes:])
|
||||
montDecode(temp, &e.p.x.y.y)
|
||||
temp.Marshal(ret[3*numBytes:])
|
||||
montDecode(temp, &e.p.x.z.x)
|
||||
temp.Marshal(ret[4*numBytes:])
|
||||
montDecode(temp, &e.p.x.z.y)
|
||||
temp.Marshal(ret[5*numBytes:])
|
||||
montDecode(temp, &e.p.y.x.x)
|
||||
temp.Marshal(ret[6*numBytes:])
|
||||
montDecode(temp, &e.p.y.x.y)
|
||||
temp.Marshal(ret[7*numBytes:])
|
||||
montDecode(temp, &e.p.y.y.x)
|
||||
temp.Marshal(ret[8*numBytes:])
|
||||
montDecode(temp, &e.p.y.y.y)
|
||||
temp.Marshal(ret[9*numBytes:])
|
||||
montDecode(temp, &e.p.y.z.x)
|
||||
temp.Marshal(ret[10*numBytes:])
|
||||
montDecode(temp, &e.p.y.z.y)
|
||||
temp.Marshal(ret[11*numBytes:])
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Unmarshal sets e to the result of converting the output of Marshal back into
|
||||
// a group element and then returns e.
|
||||
func (e *GT) Unmarshal(m []byte) ([]byte, error) {
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8
|
||||
|
||||
if len(m) < 12*numBytes {
|
||||
return nil, errors.New("bn256: not enough data")
|
||||
}
|
||||
|
||||
if e.p == nil {
|
||||
e.p = &gfP12{}
|
||||
}
|
||||
|
||||
var err error
|
||||
if err = e.p.x.x.x.Unmarshal(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.x.x.y.Unmarshal(m[numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.x.y.x.Unmarshal(m[2*numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.x.y.y.Unmarshal(m[3*numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.x.z.x.Unmarshal(m[4*numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.x.z.y.Unmarshal(m[5*numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.y.x.x.Unmarshal(m[6*numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.y.x.y.Unmarshal(m[7*numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.y.y.x.Unmarshal(m[8*numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.y.y.y.Unmarshal(m[9*numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.y.z.x.Unmarshal(m[10*numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = e.p.y.z.y.Unmarshal(m[11*numBytes:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
montEncode(&e.p.x.x.x, &e.p.x.x.x)
|
||||
montEncode(&e.p.x.x.y, &e.p.x.x.y)
|
||||
montEncode(&e.p.x.y.x, &e.p.x.y.x)
|
||||
montEncode(&e.p.x.y.y, &e.p.x.y.y)
|
||||
montEncode(&e.p.x.z.x, &e.p.x.z.x)
|
||||
montEncode(&e.p.x.z.y, &e.p.x.z.y)
|
||||
montEncode(&e.p.y.x.x, &e.p.y.x.x)
|
||||
montEncode(&e.p.y.x.y, &e.p.y.x.y)
|
||||
montEncode(&e.p.y.y.x, &e.p.y.y.x)
|
||||
montEncode(&e.p.y.y.y, &e.p.y.y.y)
|
||||
montEncode(&e.p.y.z.x, &e.p.y.z.x)
|
||||
montEncode(&e.p.y.z.y, &e.p.y.z.y)
|
||||
|
||||
return m[12*numBytes:], nil
|
||||
}
|
||||
62
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/constants.go
generated
vendored
Normal file
62
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/constants.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func bigFromBase10(s string) *big.Int {
|
||||
n, _ := new(big.Int).SetString(s, 10)
|
||||
return n
|
||||
}
|
||||
|
||||
// u is the BN parameter.
|
||||
var u = bigFromBase10("4965661367192848881")
|
||||
|
||||
// Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1.
|
||||
// Needs to be highly 2-adic for efficient SNARK key and proof generation.
|
||||
// Order - 1 = 2^28 * 3^2 * 13 * 29 * 983 * 11003 * 237073 * 405928799 * 1670836401704629 * 13818364434197438864469338081.
|
||||
// Refer to https://eprint.iacr.org/2013/879.pdf and https://eprint.iacr.org/2013/507.pdf for more information on these parameters.
|
||||
var Order = bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617")
|
||||
|
||||
// P is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1.
|
||||
var P = bigFromBase10("21888242871839275222246405745257275088696311157297823662689037894645226208583")
|
||||
|
||||
// p2 is p, represented as little-endian 64-bit words.
|
||||
var p2 = [4]uint64{0x3c208c16d87cfd47, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029}
|
||||
|
||||
// np is the negative inverse of p, mod 2^256.
|
||||
var np = [4]uint64{0x87d20782e4866389, 0x9ede7d651eca6ac9, 0xd8afcbd01833da80, 0xf57a22b791888c6b}
|
||||
|
||||
// rN1 is R^-1 where R = 2^256 mod p.
|
||||
var rN1 = &gfP{0xed84884a014afa37, 0xeb2022850278edf8, 0xcf63e9cfb74492d9, 0x2e67157159e5c639}
|
||||
|
||||
// r2 is R^2 where R = 2^256 mod p.
|
||||
var r2 = &gfP{0xf32cfc5b538afa89, 0xb5e71911d44501fb, 0x47ab1eff0a417ff6, 0x06d89f71cab8351f}
|
||||
|
||||
// r3 is R^3 where R = 2^256 mod p.
|
||||
var r3 = &gfP{0xb1cd6dafda1530df, 0x62f210e6a7283db6, 0xef7f0b0c0ada0afb, 0x20fd6e902d592544}
|
||||
|
||||
// xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+9.
|
||||
var xiToPMinus1Over6 = &gfP2{gfP{0xa222ae234c492d72, 0xd00f02a4565de15b, 0xdc2ff3a253dfc926, 0x10a75716b3899551}, gfP{0xaf9ba69633144907, 0xca6b1d7387afb78a, 0x11bded5ef08a2087, 0x02f34d751a1f3a7c}}
|
||||
|
||||
// xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+9.
|
||||
var xiToPMinus1Over3 = &gfP2{gfP{0x6e849f1ea0aa4757, 0xaa1c7b6d89f89141, 0xb6e713cdfae0ca3a, 0x26694fbb4e82ebc3}, gfP{0xb5773b104563ab30, 0x347f91c8a9aa6454, 0x7a007127242e0991, 0x1956bcd8118214ec}}
|
||||
|
||||
// xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+9.
|
||||
var xiToPMinus1Over2 = &gfP2{gfP{0xa1d77ce45ffe77c7, 0x07affd117826d1db, 0x6d16bd27bb7edc6b, 0x2c87200285defecc}, gfP{0xe4bbdd0c2936b629, 0xbb30f162e133bacb, 0x31a9d1b6f9645366, 0x253570bea500f8dd}}
|
||||
|
||||
// xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+9.
|
||||
var xiToPSquaredMinus1Over3 = &gfP{0x3350c88e13e80b9c, 0x7dce557cdb5e56b9, 0x6001b4b8b615564a, 0x2682e617020217e0}
|
||||
|
||||
// xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+9 (a cubic root of unity, mod p).
|
||||
var xiTo2PSquaredMinus2Over3 = &gfP{0x71930c11d782e155, 0xa6bb947cffbe3323, 0xaa303344d4741444, 0x2c3b3f0d26594943}
|
||||
|
||||
// xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+9 (a cubic root of -1, mod p).
|
||||
var xiToPSquaredMinus1Over6 = &gfP{0xca8d800500fa1bf2, 0xf0c5d61468b39769, 0x0e201271ad0d4418, 0x04290f65bad856e6}
|
||||
|
||||
// xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+9.
|
||||
var xiTo2PMinus2Over3 = &gfP2{gfP{0x5dddfd154bd8c949, 0x62cb29a5a4445b60, 0x37bc870a0c7dd2b9, 0x24830a9d3171f0fd}, gfP{0x7361d77f843abe92, 0xa5bb2bd3273411fb, 0x9c941f314b3e2399, 0x15df9cddbb9fd3ec}}
|
||||
238
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/curve.go
generated
vendored
Normal file
238
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/curve.go
generated
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
package bn256
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// curvePoint implements the elliptic curve y²=x³+3. Points are kept in Jacobian
|
||||
// form and t=z² when valid. G₁ is the set of points of this curve on GF(p).
|
||||
type curvePoint struct {
|
||||
x, y, z, t gfP
|
||||
}
|
||||
|
||||
var curveB = newGFp(3)
|
||||
|
||||
// curveGen is the generator of G₁.
|
||||
var curveGen = &curvePoint{
|
||||
x: *newGFp(1),
|
||||
y: *newGFp(2),
|
||||
z: *newGFp(1),
|
||||
t: *newGFp(1),
|
||||
}
|
||||
|
||||
func (c *curvePoint) String() string {
|
||||
c.MakeAffine()
|
||||
x, y := &gfP{}, &gfP{}
|
||||
montDecode(x, &c.x)
|
||||
montDecode(y, &c.y)
|
||||
return "(" + x.String() + ", " + y.String() + ")"
|
||||
}
|
||||
|
||||
func (c *curvePoint) Set(a *curvePoint) {
|
||||
c.x.Set(&a.x)
|
||||
c.y.Set(&a.y)
|
||||
c.z.Set(&a.z)
|
||||
c.t.Set(&a.t)
|
||||
}
|
||||
|
||||
// IsOnCurve returns true iff c is on the curve.
|
||||
func (c *curvePoint) IsOnCurve() bool {
|
||||
c.MakeAffine()
|
||||
if c.IsInfinity() {
|
||||
return true
|
||||
}
|
||||
|
||||
y2, x3 := &gfP{}, &gfP{}
|
||||
gfpMul(y2, &c.y, &c.y)
|
||||
gfpMul(x3, &c.x, &c.x)
|
||||
gfpMul(x3, x3, &c.x)
|
||||
gfpAdd(x3, x3, curveB)
|
||||
|
||||
return *y2 == *x3
|
||||
}
|
||||
|
||||
func (c *curvePoint) SetInfinity() {
|
||||
c.x = gfP{0}
|
||||
c.y = *newGFp(1)
|
||||
c.z = gfP{0}
|
||||
c.t = gfP{0}
|
||||
}
|
||||
|
||||
func (c *curvePoint) IsInfinity() bool {
|
||||
return c.z == gfP{0}
|
||||
}
|
||||
|
||||
func (c *curvePoint) Add(a, b *curvePoint) {
|
||||
if a.IsInfinity() {
|
||||
c.Set(b)
|
||||
return
|
||||
}
|
||||
if b.IsInfinity() {
|
||||
c.Set(a)
|
||||
return
|
||||
}
|
||||
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
|
||||
|
||||
// Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2]
|
||||
// by [u1:s1:z1·z2] and [u2:s2:z1·z2]
|
||||
// where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³
|
||||
z12, z22 := &gfP{}, &gfP{}
|
||||
gfpMul(z12, &a.z, &a.z)
|
||||
gfpMul(z22, &b.z, &b.z)
|
||||
|
||||
u1, u2 := &gfP{}, &gfP{}
|
||||
gfpMul(u1, &a.x, z22)
|
||||
gfpMul(u2, &b.x, z12)
|
||||
|
||||
t, s1 := &gfP{}, &gfP{}
|
||||
gfpMul(t, &b.z, z22)
|
||||
gfpMul(s1, &a.y, t)
|
||||
|
||||
s2 := &gfP{}
|
||||
gfpMul(t, &a.z, z12)
|
||||
gfpMul(s2, &b.y, t)
|
||||
|
||||
// Compute x = (2h)²(s²-u1-u2)
|
||||
// where s = (s2-s1)/(u2-u1) is the slope of the line through
|
||||
// (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below.
|
||||
// This is also:
|
||||
// 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1)
|
||||
// = r² - j - 2v
|
||||
// with the notations below.
|
||||
h := &gfP{}
|
||||
gfpSub(h, u2, u1)
|
||||
xEqual := *h == gfP{0}
|
||||
|
||||
gfpAdd(t, h, h)
|
||||
// i = 4h²
|
||||
i := &gfP{}
|
||||
gfpMul(i, t, t)
|
||||
// j = 4h³
|
||||
j := &gfP{}
|
||||
gfpMul(j, h, i)
|
||||
|
||||
gfpSub(t, s2, s1)
|
||||
yEqual := *t == gfP{0}
|
||||
if xEqual && yEqual {
|
||||
c.Double(a)
|
||||
return
|
||||
}
|
||||
r := &gfP{}
|
||||
gfpAdd(r, t, t)
|
||||
|
||||
v := &gfP{}
|
||||
gfpMul(v, u1, i)
|
||||
|
||||
// t4 = 4(s2-s1)²
|
||||
t4, t6 := &gfP{}, &gfP{}
|
||||
gfpMul(t4, r, r)
|
||||
gfpAdd(t, v, v)
|
||||
gfpSub(t6, t4, j)
|
||||
|
||||
gfpSub(&c.x, t6, t)
|
||||
|
||||
// Set y = -(2h)³(s1 + s*(x/4h²-u1))
|
||||
// This is also
|
||||
// y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j
|
||||
gfpSub(t, v, &c.x) // t7
|
||||
gfpMul(t4, s1, j) // t8
|
||||
gfpAdd(t6, t4, t4) // t9
|
||||
gfpMul(t4, r, t) // t10
|
||||
gfpSub(&c.y, t4, t6)
|
||||
|
||||
// Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2
|
||||
gfpAdd(t, &a.z, &b.z) // t11
|
||||
gfpMul(t4, t, t) // t12
|
||||
gfpSub(t, t4, z12) // t13
|
||||
gfpSub(t4, t, z22) // t14
|
||||
gfpMul(&c.z, t4, h)
|
||||
}
|
||||
|
||||
func (c *curvePoint) Double(a *curvePoint) {
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
|
||||
A, B, C := &gfP{}, &gfP{}, &gfP{}
|
||||
gfpMul(A, &a.x, &a.x)
|
||||
gfpMul(B, &a.y, &a.y)
|
||||
gfpMul(C, B, B)
|
||||
|
||||
t, t2 := &gfP{}, &gfP{}
|
||||
gfpAdd(t, &a.x, B)
|
||||
gfpMul(t2, t, t)
|
||||
gfpSub(t, t2, A)
|
||||
gfpSub(t2, t, C)
|
||||
|
||||
d, e, f := &gfP{}, &gfP{}, &gfP{}
|
||||
gfpAdd(d, t2, t2)
|
||||
gfpAdd(t, A, A)
|
||||
gfpAdd(e, t, A)
|
||||
gfpMul(f, e, e)
|
||||
|
||||
gfpAdd(t, d, d)
|
||||
gfpSub(&c.x, f, t)
|
||||
|
||||
gfpMul(&c.z, &a.y, &a.z)
|
||||
gfpAdd(&c.z, &c.z, &c.z)
|
||||
|
||||
gfpAdd(t, C, C)
|
||||
gfpAdd(t2, t, t)
|
||||
gfpAdd(t, t2, t2)
|
||||
gfpSub(&c.y, d, &c.x)
|
||||
gfpMul(t2, e, &c.y)
|
||||
gfpSub(&c.y, t2, t)
|
||||
}
|
||||
|
||||
func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int) {
|
||||
precomp := [1 << 2]*curvePoint{nil, {}, {}, {}}
|
||||
precomp[1].Set(a)
|
||||
precomp[2].Set(a)
|
||||
gfpMul(&precomp[2].x, &precomp[2].x, xiTo2PSquaredMinus2Over3)
|
||||
precomp[3].Add(precomp[1], precomp[2])
|
||||
|
||||
multiScalar := curveLattice.Multi(scalar)
|
||||
|
||||
sum := &curvePoint{}
|
||||
sum.SetInfinity()
|
||||
t := &curvePoint{}
|
||||
|
||||
for i := len(multiScalar) - 1; i >= 0; i-- {
|
||||
t.Double(sum)
|
||||
if multiScalar[i] == 0 {
|
||||
sum.Set(t)
|
||||
} else {
|
||||
sum.Add(t, precomp[multiScalar[i]])
|
||||
}
|
||||
}
|
||||
c.Set(sum)
|
||||
}
|
||||
|
||||
func (c *curvePoint) MakeAffine() {
|
||||
if c.z == *newGFp(1) {
|
||||
return
|
||||
} else if c.z == *newGFp(0) {
|
||||
c.x = gfP{0}
|
||||
c.y = *newGFp(1)
|
||||
c.t = gfP{0}
|
||||
return
|
||||
}
|
||||
|
||||
zInv := &gfP{}
|
||||
zInv.Invert(&c.z)
|
||||
|
||||
t, zInv2 := &gfP{}, &gfP{}
|
||||
gfpMul(t, &c.y, zInv)
|
||||
gfpMul(zInv2, zInv, zInv)
|
||||
|
||||
gfpMul(&c.x, &c.x, zInv2)
|
||||
gfpMul(&c.y, t, zInv2)
|
||||
|
||||
c.z = *newGFp(1)
|
||||
c.t = *newGFp(1)
|
||||
}
|
||||
|
||||
func (c *curvePoint) Neg(a *curvePoint) {
|
||||
c.x.Set(&a.x)
|
||||
gfpNeg(&c.y, &a.y)
|
||||
c.z.Set(&a.z)
|
||||
c.t = gfP{0}
|
||||
}
|
||||
82
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp.go
generated
vendored
Normal file
82
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
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++ {
|
||||
e[3-w] = 0
|
||||
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}) }
|
||||
160
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp12.go
generated
vendored
Normal file
160
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp12.go
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
package bn256
|
||||
|
||||
// For details of the algorithms used, see "Multiplication and Squaring on
|
||||
// Pairing-Friendly Fields, Devegili et al.
|
||||
// http://eprint.iacr.org/2006/471.pdf.
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// gfP12 implements the field of size p¹² as a quadratic extension of gfP6
|
||||
// where ω²=τ.
|
||||
type gfP12 struct {
|
||||
x, y gfP6 // value is xω + y
|
||||
}
|
||||
|
||||
func (e *gfP12) String() string {
|
||||
return "(" + e.x.String() + "," + e.y.String() + ")"
|
||||
}
|
||||
|
||||
func (e *gfP12) Set(a *gfP12) *gfP12 {
|
||||
e.x.Set(&a.x)
|
||||
e.y.Set(&a.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) SetZero() *gfP12 {
|
||||
e.x.SetZero()
|
||||
e.y.SetZero()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) SetOne() *gfP12 {
|
||||
e.x.SetZero()
|
||||
e.y.SetOne()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) IsZero() bool {
|
||||
return e.x.IsZero() && e.y.IsZero()
|
||||
}
|
||||
|
||||
func (e *gfP12) IsOne() bool {
|
||||
return e.x.IsZero() && e.y.IsOne()
|
||||
}
|
||||
|
||||
func (e *gfP12) Conjugate(a *gfP12) *gfP12 {
|
||||
e.x.Neg(&a.x)
|
||||
e.y.Set(&a.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) Neg(a *gfP12) *gfP12 {
|
||||
e.x.Neg(&a.x)
|
||||
e.y.Neg(&a.y)
|
||||
return e
|
||||
}
|
||||
|
||||
// Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p
|
||||
func (e *gfP12) Frobenius(a *gfP12) *gfP12 {
|
||||
e.x.Frobenius(&a.x)
|
||||
e.y.Frobenius(&a.y)
|
||||
e.x.MulScalar(&e.x, xiToPMinus1Over6)
|
||||
return e
|
||||
}
|
||||
|
||||
// FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p²
|
||||
func (e *gfP12) FrobeniusP2(a *gfP12) *gfP12 {
|
||||
e.x.FrobeniusP2(&a.x)
|
||||
e.x.MulGFP(&e.x, xiToPSquaredMinus1Over6)
|
||||
e.y.FrobeniusP2(&a.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) FrobeniusP4(a *gfP12) *gfP12 {
|
||||
e.x.FrobeniusP4(&a.x)
|
||||
e.x.MulGFP(&e.x, xiToPSquaredMinus1Over3)
|
||||
e.y.FrobeniusP4(&a.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) Add(a, b *gfP12) *gfP12 {
|
||||
e.x.Add(&a.x, &b.x)
|
||||
e.y.Add(&a.y, &b.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) Sub(a, b *gfP12) *gfP12 {
|
||||
e.x.Sub(&a.x, &b.x)
|
||||
e.y.Sub(&a.y, &b.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) Mul(a, b *gfP12) *gfP12 {
|
||||
tx := (&gfP6{}).Mul(&a.x, &b.y)
|
||||
t := (&gfP6{}).Mul(&b.x, &a.y)
|
||||
tx.Add(tx, t)
|
||||
|
||||
ty := (&gfP6{}).Mul(&a.y, &b.y)
|
||||
t.Mul(&a.x, &b.x).MulTau(t)
|
||||
|
||||
e.x.Set(tx)
|
||||
e.y.Add(ty, t)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) MulScalar(a *gfP12, b *gfP6) *gfP12 {
|
||||
e.x.Mul(&e.x, b)
|
||||
e.y.Mul(&e.y, b)
|
||||
return e
|
||||
}
|
||||
|
||||
func (c *gfP12) Exp(a *gfP12, power *big.Int) *gfP12 {
|
||||
sum := (&gfP12{}).SetOne()
|
||||
t := &gfP12{}
|
||||
|
||||
for i := power.BitLen() - 1; i >= 0; i-- {
|
||||
t.Square(sum)
|
||||
if power.Bit(i) != 0 {
|
||||
sum.Mul(t, a)
|
||||
} else {
|
||||
sum.Set(t)
|
||||
}
|
||||
}
|
||||
|
||||
c.Set(sum)
|
||||
return c
|
||||
}
|
||||
|
||||
func (e *gfP12) Square(a *gfP12) *gfP12 {
|
||||
// Complex squaring algorithm
|
||||
v0 := (&gfP6{}).Mul(&a.x, &a.y)
|
||||
|
||||
t := (&gfP6{}).MulTau(&a.x)
|
||||
t.Add(&a.y, t)
|
||||
ty := (&gfP6{}).Add(&a.x, &a.y)
|
||||
ty.Mul(ty, t).Sub(ty, v0)
|
||||
t.MulTau(v0)
|
||||
ty.Sub(ty, t)
|
||||
|
||||
e.x.Add(v0, v0)
|
||||
e.y.Set(ty)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) Invert(a *gfP12) *gfP12 {
|
||||
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
||||
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
||||
t1, t2 := &gfP6{}, &gfP6{}
|
||||
|
||||
t1.Square(&a.x)
|
||||
t2.Square(&a.y)
|
||||
t1.MulTau(t1).Sub(t2, t1)
|
||||
t2.Invert(t1)
|
||||
|
||||
e.x.Neg(&a.x)
|
||||
e.y.Set(&a.y)
|
||||
e.MulScalar(e, t2)
|
||||
return e
|
||||
}
|
||||
156
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp2.go
generated
vendored
Normal file
156
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp2.go
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
package bn256
|
||||
|
||||
// For details of the algorithms used, see "Multiplication and Squaring on
|
||||
// Pairing-Friendly Fields, Devegili et al.
|
||||
// http://eprint.iacr.org/2006/471.pdf.
|
||||
|
||||
// gfP2 implements a field of size p² as a quadratic extension of the base field
|
||||
// where i²=-1.
|
||||
type gfP2 struct {
|
||||
x, y gfP // value is xi+y.
|
||||
}
|
||||
|
||||
func gfP2Decode(in *gfP2) *gfP2 {
|
||||
out := &gfP2{}
|
||||
montDecode(&out.x, &in.x)
|
||||
montDecode(&out.y, &in.y)
|
||||
return out
|
||||
}
|
||||
|
||||
func (e *gfP2) String() string {
|
||||
return "(" + e.x.String() + ", " + e.y.String() + ")"
|
||||
}
|
||||
|
||||
func (e *gfP2) Set(a *gfP2) *gfP2 {
|
||||
e.x.Set(&a.x)
|
||||
e.y.Set(&a.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) SetZero() *gfP2 {
|
||||
e.x = gfP{0}
|
||||
e.y = gfP{0}
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) SetOne() *gfP2 {
|
||||
e.x = gfP{0}
|
||||
e.y = *newGFp(1)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) IsZero() bool {
|
||||
zero := gfP{0}
|
||||
return e.x == zero && e.y == zero
|
||||
}
|
||||
|
||||
func (e *gfP2) IsOne() bool {
|
||||
zero, one := gfP{0}, *newGFp(1)
|
||||
return e.x == zero && e.y == one
|
||||
}
|
||||
|
||||
func (e *gfP2) Conjugate(a *gfP2) *gfP2 {
|
||||
e.y.Set(&a.y)
|
||||
gfpNeg(&e.x, &a.x)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Neg(a *gfP2) *gfP2 {
|
||||
gfpNeg(&e.x, &a.x)
|
||||
gfpNeg(&e.y, &a.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Add(a, b *gfP2) *gfP2 {
|
||||
gfpAdd(&e.x, &a.x, &b.x)
|
||||
gfpAdd(&e.y, &a.y, &b.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Sub(a, b *gfP2) *gfP2 {
|
||||
gfpSub(&e.x, &a.x, &b.x)
|
||||
gfpSub(&e.y, &a.y, &b.y)
|
||||
return e
|
||||
}
|
||||
|
||||
// See "Multiplication and Squaring in Pairing-Friendly Fields",
|
||||
// http://eprint.iacr.org/2006/471.pdf
|
||||
func (e *gfP2) Mul(a, b *gfP2) *gfP2 {
|
||||
tx, t := &gfP{}, &gfP{}
|
||||
gfpMul(tx, &a.x, &b.y)
|
||||
gfpMul(t, &b.x, &a.y)
|
||||
gfpAdd(tx, tx, t)
|
||||
|
||||
ty := &gfP{}
|
||||
gfpMul(ty, &a.y, &b.y)
|
||||
gfpMul(t, &a.x, &b.x)
|
||||
gfpSub(ty, ty, t)
|
||||
|
||||
e.x.Set(tx)
|
||||
e.y.Set(ty)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) MulScalar(a *gfP2, b *gfP) *gfP2 {
|
||||
gfpMul(&e.x, &a.x, b)
|
||||
gfpMul(&e.y, &a.y, b)
|
||||
return e
|
||||
}
|
||||
|
||||
// MulXi sets e=ξa where ξ=i+9 and then returns e.
|
||||
func (e *gfP2) MulXi(a *gfP2) *gfP2 {
|
||||
// (xi+y)(i+9) = (9x+y)i+(9y-x)
|
||||
tx := &gfP{}
|
||||
gfpAdd(tx, &a.x, &a.x)
|
||||
gfpAdd(tx, tx, tx)
|
||||
gfpAdd(tx, tx, tx)
|
||||
gfpAdd(tx, tx, &a.x)
|
||||
|
||||
gfpAdd(tx, tx, &a.y)
|
||||
|
||||
ty := &gfP{}
|
||||
gfpAdd(ty, &a.y, &a.y)
|
||||
gfpAdd(ty, ty, ty)
|
||||
gfpAdd(ty, ty, ty)
|
||||
gfpAdd(ty, ty, &a.y)
|
||||
|
||||
gfpSub(ty, ty, &a.x)
|
||||
|
||||
e.x.Set(tx)
|
||||
e.y.Set(ty)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Square(a *gfP2) *gfP2 {
|
||||
// Complex squaring algorithm:
|
||||
// (xi+y)² = (x+y)(y-x) + 2*i*x*y
|
||||
tx, ty := &gfP{}, &gfP{}
|
||||
gfpSub(tx, &a.y, &a.x)
|
||||
gfpAdd(ty, &a.x, &a.y)
|
||||
gfpMul(ty, tx, ty)
|
||||
|
||||
gfpMul(tx, &a.x, &a.y)
|
||||
gfpAdd(tx, tx, tx)
|
||||
|
||||
e.x.Set(tx)
|
||||
e.y.Set(ty)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Invert(a *gfP2) *gfP2 {
|
||||
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
||||
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
||||
t1, t2 := &gfP{}, &gfP{}
|
||||
gfpMul(t1, &a.x, &a.x)
|
||||
gfpMul(t2, &a.y, &a.y)
|
||||
gfpAdd(t1, t1, t2)
|
||||
|
||||
inv := &gfP{}
|
||||
inv.Invert(t1)
|
||||
|
||||
gfpNeg(t1, &a.x)
|
||||
|
||||
gfpMul(&e.x, t1, inv)
|
||||
gfpMul(&e.y, &a.y, inv)
|
||||
return e
|
||||
}
|
||||
213
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp6.go
generated
vendored
Normal file
213
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp6.go
generated
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
package bn256
|
||||
|
||||
// For details of the algorithms used, see "Multiplication and Squaring on
|
||||
// Pairing-Friendly Fields, Devegili et al.
|
||||
// http://eprint.iacr.org/2006/471.pdf.
|
||||
|
||||
// gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ
|
||||
// and ξ=i+9.
|
||||
type gfP6 struct {
|
||||
x, y, z gfP2 // value is xτ² + yτ + z
|
||||
}
|
||||
|
||||
func (e *gfP6) String() string {
|
||||
return "(" + e.x.String() + ", " + e.y.String() + ", " + e.z.String() + ")"
|
||||
}
|
||||
|
||||
func (e *gfP6) Set(a *gfP6) *gfP6 {
|
||||
e.x.Set(&a.x)
|
||||
e.y.Set(&a.y)
|
||||
e.z.Set(&a.z)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) SetZero() *gfP6 {
|
||||
e.x.SetZero()
|
||||
e.y.SetZero()
|
||||
e.z.SetZero()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) SetOne() *gfP6 {
|
||||
e.x.SetZero()
|
||||
e.y.SetZero()
|
||||
e.z.SetOne()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) IsZero() bool {
|
||||
return e.x.IsZero() && e.y.IsZero() && e.z.IsZero()
|
||||
}
|
||||
|
||||
func (e *gfP6) IsOne() bool {
|
||||
return e.x.IsZero() && e.y.IsZero() && e.z.IsOne()
|
||||
}
|
||||
|
||||
func (e *gfP6) Neg(a *gfP6) *gfP6 {
|
||||
e.x.Neg(&a.x)
|
||||
e.y.Neg(&a.y)
|
||||
e.z.Neg(&a.z)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) Frobenius(a *gfP6) *gfP6 {
|
||||
e.x.Conjugate(&a.x)
|
||||
e.y.Conjugate(&a.y)
|
||||
e.z.Conjugate(&a.z)
|
||||
|
||||
e.x.Mul(&e.x, xiTo2PMinus2Over3)
|
||||
e.y.Mul(&e.y, xiToPMinus1Over3)
|
||||
return e
|
||||
}
|
||||
|
||||
// FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z
|
||||
func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 {
|
||||
// τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3)
|
||||
e.x.MulScalar(&a.x, xiTo2PSquaredMinus2Over3)
|
||||
// τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3)
|
||||
e.y.MulScalar(&a.y, xiToPSquaredMinus1Over3)
|
||||
e.z.Set(&a.z)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) FrobeniusP4(a *gfP6) *gfP6 {
|
||||
e.x.MulScalar(&a.x, xiToPSquaredMinus1Over3)
|
||||
e.y.MulScalar(&a.y, xiTo2PSquaredMinus2Over3)
|
||||
e.z.Set(&a.z)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) Add(a, b *gfP6) *gfP6 {
|
||||
e.x.Add(&a.x, &b.x)
|
||||
e.y.Add(&a.y, &b.y)
|
||||
e.z.Add(&a.z, &b.z)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) Sub(a, b *gfP6) *gfP6 {
|
||||
e.x.Sub(&a.x, &b.x)
|
||||
e.y.Sub(&a.y, &b.y)
|
||||
e.z.Sub(&a.z, &b.z)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) Mul(a, b *gfP6) *gfP6 {
|
||||
// "Multiplication and Squaring on Pairing-Friendly Fields"
|
||||
// Section 4, Karatsuba method.
|
||||
// http://eprint.iacr.org/2006/471.pdf
|
||||
v0 := (&gfP2{}).Mul(&a.z, &b.z)
|
||||
v1 := (&gfP2{}).Mul(&a.y, &b.y)
|
||||
v2 := (&gfP2{}).Mul(&a.x, &b.x)
|
||||
|
||||
t0 := (&gfP2{}).Add(&a.x, &a.y)
|
||||
t1 := (&gfP2{}).Add(&b.x, &b.y)
|
||||
tz := (&gfP2{}).Mul(t0, t1)
|
||||
tz.Sub(tz, v1).Sub(tz, v2).MulXi(tz).Add(tz, v0)
|
||||
|
||||
t0.Add(&a.y, &a.z)
|
||||
t1.Add(&b.y, &b.z)
|
||||
ty := (&gfP2{}).Mul(t0, t1)
|
||||
t0.MulXi(v2)
|
||||
ty.Sub(ty, v0).Sub(ty, v1).Add(ty, t0)
|
||||
|
||||
t0.Add(&a.x, &a.z)
|
||||
t1.Add(&b.x, &b.z)
|
||||
tx := (&gfP2{}).Mul(t0, t1)
|
||||
tx.Sub(tx, v0).Add(tx, v1).Sub(tx, v2)
|
||||
|
||||
e.x.Set(tx)
|
||||
e.y.Set(ty)
|
||||
e.z.Set(tz)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) MulScalar(a *gfP6, b *gfP2) *gfP6 {
|
||||
e.x.Mul(&a.x, b)
|
||||
e.y.Mul(&a.y, b)
|
||||
e.z.Mul(&a.z, b)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) MulGFP(a *gfP6, b *gfP) *gfP6 {
|
||||
e.x.MulScalar(&a.x, b)
|
||||
e.y.MulScalar(&a.y, b)
|
||||
e.z.MulScalar(&a.z, b)
|
||||
return e
|
||||
}
|
||||
|
||||
// MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ
|
||||
func (e *gfP6) MulTau(a *gfP6) *gfP6 {
|
||||
tz := (&gfP2{}).MulXi(&a.x)
|
||||
ty := (&gfP2{}).Set(&a.y)
|
||||
|
||||
e.y.Set(&a.z)
|
||||
e.x.Set(ty)
|
||||
e.z.Set(tz)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) Square(a *gfP6) *gfP6 {
|
||||
v0 := (&gfP2{}).Square(&a.z)
|
||||
v1 := (&gfP2{}).Square(&a.y)
|
||||
v2 := (&gfP2{}).Square(&a.x)
|
||||
|
||||
c0 := (&gfP2{}).Add(&a.x, &a.y)
|
||||
c0.Square(c0).Sub(c0, v1).Sub(c0, v2).MulXi(c0).Add(c0, v0)
|
||||
|
||||
c1 := (&gfP2{}).Add(&a.y, &a.z)
|
||||
c1.Square(c1).Sub(c1, v0).Sub(c1, v1)
|
||||
xiV2 := (&gfP2{}).MulXi(v2)
|
||||
c1.Add(c1, xiV2)
|
||||
|
||||
c2 := (&gfP2{}).Add(&a.x, &a.z)
|
||||
c2.Square(c2).Sub(c2, v0).Add(c2, v1).Sub(c2, v2)
|
||||
|
||||
e.x.Set(c2)
|
||||
e.y.Set(c1)
|
||||
e.z.Set(c0)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) Invert(a *gfP6) *gfP6 {
|
||||
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
||||
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
||||
|
||||
// Here we can give a short explanation of how it works: let j be a cubic root of
|
||||
// unity in GF(p²) so that 1+j+j²=0.
|
||||
// Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
|
||||
// = (xτ² + yτ + z)(Cτ²+Bτ+A)
|
||||
// = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm).
|
||||
//
|
||||
// On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
|
||||
// = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy)
|
||||
//
|
||||
// So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz)
|
||||
t1 := (&gfP2{}).Mul(&a.x, &a.y)
|
||||
t1.MulXi(t1)
|
||||
|
||||
A := (&gfP2{}).Square(&a.z)
|
||||
A.Sub(A, t1)
|
||||
|
||||
B := (&gfP2{}).Square(&a.x)
|
||||
B.MulXi(B)
|
||||
t1.Mul(&a.y, &a.z)
|
||||
B.Sub(B, t1)
|
||||
|
||||
C := (&gfP2{}).Square(&a.y)
|
||||
t1.Mul(&a.x, &a.z)
|
||||
C.Sub(C, t1)
|
||||
|
||||
F := (&gfP2{}).Mul(C, &a.y)
|
||||
F.MulXi(F)
|
||||
t1.Mul(A, &a.z)
|
||||
F.Add(F, t1)
|
||||
t1.Mul(B, &a.x).MulXi(t1)
|
||||
F.Add(F, t1)
|
||||
|
||||
F.Invert(F)
|
||||
|
||||
e.x.Mul(C, F)
|
||||
e.y.Mul(B, F)
|
||||
e.z.Mul(A, F)
|
||||
return e
|
||||
}
|
||||
129
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_amd64.s
generated
vendored
Normal file
129
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_amd64.s
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
// +build amd64,!generic
|
||||
|
||||
#define storeBlock(a0,a1,a2,a3, r) \
|
||||
MOVQ a0, 0+r \
|
||||
MOVQ a1, 8+r \
|
||||
MOVQ a2, 16+r \
|
||||
MOVQ a3, 24+r
|
||||
|
||||
#define loadBlock(r, a0,a1,a2,a3) \
|
||||
MOVQ 0+r, a0 \
|
||||
MOVQ 8+r, a1 \
|
||||
MOVQ 16+r, a2 \
|
||||
MOVQ 24+r, a3
|
||||
|
||||
#define gfpCarry(a0,a1,a2,a3,a4, b0,b1,b2,b3,b4) \
|
||||
\ // b = a-p
|
||||
MOVQ a0, b0 \
|
||||
MOVQ a1, b1 \
|
||||
MOVQ a2, b2 \
|
||||
MOVQ a3, b3 \
|
||||
MOVQ a4, b4 \
|
||||
\
|
||||
SUBQ ·p2+0(SB), b0 \
|
||||
SBBQ ·p2+8(SB), b1 \
|
||||
SBBQ ·p2+16(SB), b2 \
|
||||
SBBQ ·p2+24(SB), b3 \
|
||||
SBBQ $0, b4 \
|
||||
\
|
||||
\ // if b is negative then return a
|
||||
\ // else return b
|
||||
CMOVQCC b0, a0 \
|
||||
CMOVQCC b1, a1 \
|
||||
CMOVQCC b2, a2 \
|
||||
CMOVQCC b3, a3
|
||||
|
||||
#include "mul_amd64.h"
|
||||
#include "mul_bmi2_amd64.h"
|
||||
|
||||
TEXT ·gfpNeg(SB),0,$0-16
|
||||
MOVQ ·p2+0(SB), R8
|
||||
MOVQ ·p2+8(SB), R9
|
||||
MOVQ ·p2+16(SB), R10
|
||||
MOVQ ·p2+24(SB), R11
|
||||
|
||||
MOVQ a+8(FP), DI
|
||||
SUBQ 0(DI), R8
|
||||
SBBQ 8(DI), R9
|
||||
SBBQ 16(DI), R10
|
||||
SBBQ 24(DI), R11
|
||||
|
||||
MOVQ $0, AX
|
||||
gfpCarry(R8,R9,R10,R11,AX, R12,R13,R14,CX,BX)
|
||||
|
||||
MOVQ c+0(FP), DI
|
||||
storeBlock(R8,R9,R10,R11, 0(DI))
|
||||
RET
|
||||
|
||||
TEXT ·gfpAdd(SB),0,$0-24
|
||||
MOVQ a+8(FP), DI
|
||||
MOVQ b+16(FP), SI
|
||||
|
||||
loadBlock(0(DI), R8,R9,R10,R11)
|
||||
MOVQ $0, R12
|
||||
|
||||
ADDQ 0(SI), R8
|
||||
ADCQ 8(SI), R9
|
||||
ADCQ 16(SI), R10
|
||||
ADCQ 24(SI), R11
|
||||
ADCQ $0, R12
|
||||
|
||||
gfpCarry(R8,R9,R10,R11,R12, R13,R14,CX,AX,BX)
|
||||
|
||||
MOVQ c+0(FP), DI
|
||||
storeBlock(R8,R9,R10,R11, 0(DI))
|
||||
RET
|
||||
|
||||
TEXT ·gfpSub(SB),0,$0-24
|
||||
MOVQ a+8(FP), DI
|
||||
MOVQ b+16(FP), SI
|
||||
|
||||
loadBlock(0(DI), R8,R9,R10,R11)
|
||||
|
||||
MOVQ ·p2+0(SB), R12
|
||||
MOVQ ·p2+8(SB), R13
|
||||
MOVQ ·p2+16(SB), R14
|
||||
MOVQ ·p2+24(SB), CX
|
||||
MOVQ $0, AX
|
||||
|
||||
SUBQ 0(SI), R8
|
||||
SBBQ 8(SI), R9
|
||||
SBBQ 16(SI), R10
|
||||
SBBQ 24(SI), R11
|
||||
|
||||
CMOVQCC AX, R12
|
||||
CMOVQCC AX, R13
|
||||
CMOVQCC AX, R14
|
||||
CMOVQCC AX, CX
|
||||
|
||||
ADDQ R12, R8
|
||||
ADCQ R13, R9
|
||||
ADCQ R14, R10
|
||||
ADCQ CX, R11
|
||||
|
||||
MOVQ c+0(FP), DI
|
||||
storeBlock(R8,R9,R10,R11, 0(DI))
|
||||
RET
|
||||
|
||||
TEXT ·gfpMul(SB),0,$160-24
|
||||
MOVQ a+8(FP), DI
|
||||
MOVQ b+16(FP), SI
|
||||
|
||||
// Jump to a slightly different implementation if MULX isn't supported.
|
||||
CMPB ·hasBMI2(SB), $0
|
||||
JE nobmi2Mul
|
||||
|
||||
mulBMI2(0(DI),8(DI),16(DI),24(DI), 0(SI))
|
||||
storeBlock( R8, R9,R10,R11, 0(SP))
|
||||
storeBlock(R12,R13,R14,CX, 32(SP))
|
||||
gfpReduceBMI2()
|
||||
JMP end
|
||||
|
||||
nobmi2Mul:
|
||||
mul(0(DI),8(DI),16(DI),24(DI), 0(SI), 0(SP))
|
||||
gfpReduce(0(SP))
|
||||
|
||||
end:
|
||||
MOVQ c+0(FP), DI
|
||||
storeBlock(R12,R13,R14,CX, 0(DI))
|
||||
RET
|
||||
113
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_arm64.s
generated
vendored
Normal file
113
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_arm64.s
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
// +build arm64,!generic
|
||||
|
||||
#define storeBlock(a0,a1,a2,a3, r) \
|
||||
MOVD a0, 0+r \
|
||||
MOVD a1, 8+r \
|
||||
MOVD a2, 16+r \
|
||||
MOVD a3, 24+r
|
||||
|
||||
#define loadBlock(r, a0,a1,a2,a3) \
|
||||
MOVD 0+r, a0 \
|
||||
MOVD 8+r, a1 \
|
||||
MOVD 16+r, a2 \
|
||||
MOVD 24+r, a3
|
||||
|
||||
#define loadModulus(p0,p1,p2,p3) \
|
||||
MOVD ·p2+0(SB), p0 \
|
||||
MOVD ·p2+8(SB), p1 \
|
||||
MOVD ·p2+16(SB), p2 \
|
||||
MOVD ·p2+24(SB), p3
|
||||
|
||||
#include "mul_arm64.h"
|
||||
|
||||
TEXT ·gfpNeg(SB),0,$0-16
|
||||
MOVD a+8(FP), R0
|
||||
loadBlock(0(R0), R1,R2,R3,R4)
|
||||
loadModulus(R5,R6,R7,R8)
|
||||
|
||||
SUBS R1, R5, R1
|
||||
SBCS R2, R6, R2
|
||||
SBCS R3, R7, R3
|
||||
SBCS R4, R8, R4
|
||||
|
||||
SUBS R5, R1, R5
|
||||
SBCS R6, R2, R6
|
||||
SBCS R7, R3, R7
|
||||
SBCS R8, R4, R8
|
||||
|
||||
CSEL CS, R5, R1, R1
|
||||
CSEL CS, R6, R2, R2
|
||||
CSEL CS, R7, R3, R3
|
||||
CSEL CS, R8, R4, R4
|
||||
|
||||
MOVD c+0(FP), R0
|
||||
storeBlock(R1,R2,R3,R4, 0(R0))
|
||||
RET
|
||||
|
||||
TEXT ·gfpAdd(SB),0,$0-24
|
||||
MOVD a+8(FP), R0
|
||||
loadBlock(0(R0), R1,R2,R3,R4)
|
||||
MOVD b+16(FP), R0
|
||||
loadBlock(0(R0), R5,R6,R7,R8)
|
||||
loadModulus(R9,R10,R11,R12)
|
||||
MOVD ZR, R0
|
||||
|
||||
ADDS R5, R1
|
||||
ADCS R6, R2
|
||||
ADCS R7, R3
|
||||
ADCS R8, R4
|
||||
ADCS ZR, R0
|
||||
|
||||
SUBS R9, R1, R5
|
||||
SBCS R10, R2, R6
|
||||
SBCS R11, R3, R7
|
||||
SBCS R12, R4, R8
|
||||
SBCS ZR, R0, R0
|
||||
|
||||
CSEL CS, R5, R1, R1
|
||||
CSEL CS, R6, R2, R2
|
||||
CSEL CS, R7, R3, R3
|
||||
CSEL CS, R8, R4, R4
|
||||
|
||||
MOVD c+0(FP), R0
|
||||
storeBlock(R1,R2,R3,R4, 0(R0))
|
||||
RET
|
||||
|
||||
TEXT ·gfpSub(SB),0,$0-24
|
||||
MOVD a+8(FP), R0
|
||||
loadBlock(0(R0), R1,R2,R3,R4)
|
||||
MOVD b+16(FP), R0
|
||||
loadBlock(0(R0), R5,R6,R7,R8)
|
||||
loadModulus(R9,R10,R11,R12)
|
||||
|
||||
SUBS R5, R1
|
||||
SBCS R6, R2
|
||||
SBCS R7, R3
|
||||
SBCS R8, R4
|
||||
|
||||
CSEL CS, ZR, R9, R9
|
||||
CSEL CS, ZR, R10, R10
|
||||
CSEL CS, ZR, R11, R11
|
||||
CSEL CS, ZR, R12, R12
|
||||
|
||||
ADDS R9, R1
|
||||
ADCS R10, R2
|
||||
ADCS R11, R3
|
||||
ADCS R12, R4
|
||||
|
||||
MOVD c+0(FP), R0
|
||||
storeBlock(R1,R2,R3,R4, 0(R0))
|
||||
RET
|
||||
|
||||
TEXT ·gfpMul(SB),0,$0-24
|
||||
MOVD a+8(FP), R0
|
||||
loadBlock(0(R0), R1,R2,R3,R4)
|
||||
MOVD b+16(FP), R0
|
||||
loadBlock(0(R0), R5,R6,R7,R8)
|
||||
|
||||
mul(R9,R10,R11,R12,R13,R14,R15,R16)
|
||||
gfpReduce()
|
||||
|
||||
MOVD c+0(FP), R0
|
||||
storeBlock(R1,R2,R3,R4, 0(R0))
|
||||
RET
|
||||
26
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_decl.go
generated
vendored
Normal file
26
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_decl.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
//go:build (amd64 && !generic) || (arm64 && !generic)
|
||||
// +build amd64,!generic arm64,!generic
|
||||
|
||||
package bn256
|
||||
|
||||
// This file contains forward declarations for the architecture-specific
|
||||
// assembly implementations of these functions, provided that they exist.
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/cpu"
|
||||
)
|
||||
|
||||
//nolint:varcheck,unused,deadcode
|
||||
var hasBMI2 = cpu.X86.HasBMI2
|
||||
|
||||
// go:noescape
|
||||
func gfpNeg(c, a *gfP)
|
||||
|
||||
//go:noescape
|
||||
func gfpAdd(c, a, b *gfP)
|
||||
|
||||
//go:noescape
|
||||
func gfpSub(c, a, b *gfP)
|
||||
|
||||
//go:noescape
|
||||
func gfpMul(c, a, b *gfP)
|
||||
174
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_generic.go
generated
vendored
Normal file
174
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp_generic.go
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
//go:build (!amd64 && !arm64) || generic
|
||||
// +build !amd64,!arm64 generic
|
||||
|
||||
package bn256
|
||||
|
||||
func gfpCarry(a *gfP, head uint64) {
|
||||
b := &gfP{}
|
||||
|
||||
var carry uint64
|
||||
for i, pi := range p2 {
|
||||
ai := a[i]
|
||||
bi := ai - pi - carry
|
||||
b[i] = bi
|
||||
carry = (pi&^ai | (pi|^ai)&bi) >> 63
|
||||
}
|
||||
carry = carry &^ head
|
||||
|
||||
// If b is negative, then return a.
|
||||
// Else return b.
|
||||
carry = -carry
|
||||
ncarry := ^carry
|
||||
for i := 0; i < 4; i++ {
|
||||
a[i] = (a[i] & carry) | (b[i] & ncarry)
|
||||
}
|
||||
}
|
||||
|
||||
func gfpNeg(c, a *gfP) {
|
||||
var carry uint64
|
||||
for i, pi := range p2 {
|
||||
ai := a[i]
|
||||
ci := pi - ai - carry
|
||||
c[i] = ci
|
||||
carry = (ai&^pi | (ai|^pi)&ci) >> 63
|
||||
}
|
||||
gfpCarry(c, 0)
|
||||
}
|
||||
|
||||
func gfpAdd(c, a, b *gfP) {
|
||||
var carry uint64
|
||||
for i, ai := range a {
|
||||
bi := b[i]
|
||||
ci := ai + bi + carry
|
||||
c[i] = ci
|
||||
carry = (ai&bi | (ai|bi)&^ci) >> 63
|
||||
}
|
||||
gfpCarry(c, carry)
|
||||
}
|
||||
|
||||
func gfpSub(c, a, b *gfP) {
|
||||
t := &gfP{}
|
||||
|
||||
var carry uint64
|
||||
for i, pi := range p2 {
|
||||
bi := b[i]
|
||||
ti := pi - bi - carry
|
||||
t[i] = ti
|
||||
carry = (bi&^pi | (bi|^pi)&ti) >> 63
|
||||
}
|
||||
|
||||
carry = 0
|
||||
for i, ai := range a {
|
||||
ti := t[i]
|
||||
ci := ai + ti + carry
|
||||
c[i] = ci
|
||||
carry = (ai&ti | (ai|ti)&^ci) >> 63
|
||||
}
|
||||
gfpCarry(c, carry)
|
||||
}
|
||||
|
||||
func mul(a, b [4]uint64) [8]uint64 {
|
||||
const (
|
||||
mask16 uint64 = 0x0000ffff
|
||||
mask32 uint64 = 0xffffffff
|
||||
)
|
||||
|
||||
var buff [32]uint64
|
||||
for i, ai := range a {
|
||||
a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48
|
||||
|
||||
for j, bj := range b {
|
||||
b0, b2 := bj&mask32, bj>>32
|
||||
|
||||
off := 4 * (i + j)
|
||||
buff[off+0] += a0 * b0
|
||||
buff[off+1] += a1 * b0
|
||||
buff[off+2] += a2*b0 + a0*b2
|
||||
buff[off+3] += a3*b0 + a1*b2
|
||||
buff[off+4] += a2 * b2
|
||||
buff[off+5] += a3 * b2
|
||||
}
|
||||
}
|
||||
|
||||
for i := uint(1); i < 4; i++ {
|
||||
shift := 16 * i
|
||||
|
||||
var head, carry uint64
|
||||
for j := uint(0); j < 8; j++ {
|
||||
block := 4 * j
|
||||
|
||||
xi := buff[block]
|
||||
yi := (buff[block+i] << shift) + head
|
||||
zi := xi + yi + carry
|
||||
buff[block] = zi
|
||||
carry = (xi&yi | (xi|yi)&^zi) >> 63
|
||||
|
||||
head = buff[block+i] >> (64 - shift)
|
||||
}
|
||||
}
|
||||
|
||||
return [8]uint64{buff[0], buff[4], buff[8], buff[12], buff[16], buff[20], buff[24], buff[28]}
|
||||
}
|
||||
|
||||
func halfMul(a, b [4]uint64) [4]uint64 {
|
||||
const (
|
||||
mask16 uint64 = 0x0000ffff
|
||||
mask32 uint64 = 0xffffffff
|
||||
)
|
||||
|
||||
var buff [18]uint64
|
||||
for i, ai := range a {
|
||||
a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48
|
||||
|
||||
for j, bj := range b {
|
||||
if i+j > 3 {
|
||||
break
|
||||
}
|
||||
b0, b2 := bj&mask32, bj>>32
|
||||
|
||||
off := 4 * (i + j)
|
||||
buff[off+0] += a0 * b0
|
||||
buff[off+1] += a1 * b0
|
||||
buff[off+2] += a2*b0 + a0*b2
|
||||
buff[off+3] += a3*b0 + a1*b2
|
||||
buff[off+4] += a2 * b2
|
||||
buff[off+5] += a3 * b2
|
||||
}
|
||||
}
|
||||
|
||||
for i := uint(1); i < 4; i++ {
|
||||
shift := 16 * i
|
||||
|
||||
var head, carry uint64
|
||||
for j := uint(0); j < 4; j++ {
|
||||
block := 4 * j
|
||||
|
||||
xi := buff[block]
|
||||
yi := (buff[block+i] << shift) + head
|
||||
zi := xi + yi + carry
|
||||
buff[block] = zi
|
||||
carry = (xi&yi | (xi|yi)&^zi) >> 63
|
||||
|
||||
head = buff[block+i] >> (64 - shift)
|
||||
}
|
||||
}
|
||||
|
||||
return [4]uint64{buff[0], buff[4], buff[8], buff[12]}
|
||||
}
|
||||
|
||||
func gfpMul(c, a, b *gfP) {
|
||||
T := mul(*a, *b)
|
||||
m := halfMul([4]uint64{T[0], T[1], T[2], T[3]}, np)
|
||||
t := mul([4]uint64{m[0], m[1], m[2], m[3]}, p2)
|
||||
|
||||
var carry uint64
|
||||
for i, Ti := range T {
|
||||
ti := t[i]
|
||||
zi := Ti + ti + carry
|
||||
T[i] = zi
|
||||
carry = (Ti&ti | (Ti|ti)&^zi) >> 63
|
||||
}
|
||||
|
||||
*c = gfP{T[4], T[5], T[6], T[7]}
|
||||
gfpCarry(c, carry)
|
||||
}
|
||||
115
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/lattice.go
generated
vendored
Normal file
115
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/lattice.go
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
package bn256
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
var half = new(big.Int).Rsh(Order, 1)
|
||||
|
||||
var curveLattice = &lattice{
|
||||
vectors: [][]*big.Int{
|
||||
{bigFromBase10("147946756881789319000765030803803410728"), bigFromBase10("147946756881789319010696353538189108491")},
|
||||
{bigFromBase10("147946756881789319020627676272574806254"), bigFromBase10("-147946756881789318990833708069417712965")},
|
||||
},
|
||||
inverse: []*big.Int{
|
||||
bigFromBase10("147946756881789318990833708069417712965"),
|
||||
bigFromBase10("147946756881789319010696353538189108491"),
|
||||
},
|
||||
det: bigFromBase10("43776485743678550444492811490514550177096728800832068687396408373151616991234"),
|
||||
}
|
||||
|
||||
var targetLattice = &lattice{
|
||||
vectors: [][]*big.Int{
|
||||
{bigFromBase10("9931322734385697761"), bigFromBase10("9931322734385697761"), bigFromBase10("9931322734385697763"), bigFromBase10("9931322734385697764")},
|
||||
{bigFromBase10("4965661367192848881"), bigFromBase10("4965661367192848881"), bigFromBase10("4965661367192848882"), bigFromBase10("-9931322734385697762")},
|
||||
{bigFromBase10("-9931322734385697762"), bigFromBase10("-4965661367192848881"), bigFromBase10("4965661367192848881"), bigFromBase10("-4965661367192848882")},
|
||||
{bigFromBase10("9931322734385697763"), bigFromBase10("-4965661367192848881"), bigFromBase10("-4965661367192848881"), bigFromBase10("-4965661367192848881")},
|
||||
},
|
||||
inverse: []*big.Int{
|
||||
bigFromBase10("734653495049373973658254490726798021314063399421879442165"),
|
||||
bigFromBase10("147946756881789319000765030803803410728"),
|
||||
bigFromBase10("-147946756881789319005730692170996259609"),
|
||||
bigFromBase10("1469306990098747947464455738335385361643788813749140841702"),
|
||||
},
|
||||
det: new(big.Int).Set(Order),
|
||||
}
|
||||
|
||||
type lattice struct {
|
||||
vectors [][]*big.Int
|
||||
inverse []*big.Int
|
||||
det *big.Int
|
||||
}
|
||||
|
||||
// decompose takes a scalar mod Order as input and finds a short, positive decomposition of it wrt to the lattice basis.
|
||||
func (l *lattice) decompose(k *big.Int) []*big.Int {
|
||||
n := len(l.inverse)
|
||||
|
||||
// Calculate closest vector in lattice to <k,0,0,...> with Babai's rounding.
|
||||
c := make([]*big.Int, n)
|
||||
for i := 0; i < n; i++ {
|
||||
c[i] = new(big.Int).Mul(k, l.inverse[i])
|
||||
round(c[i], l.det)
|
||||
}
|
||||
|
||||
// Transform vectors according to c and subtract <k,0,0,...>.
|
||||
out := make([]*big.Int, n)
|
||||
temp := new(big.Int)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
out[i] = new(big.Int)
|
||||
|
||||
for j := 0; j < n; j++ {
|
||||
temp.Mul(c[j], l.vectors[j][i])
|
||||
out[i].Add(out[i], temp)
|
||||
}
|
||||
|
||||
out[i].Neg(out[i])
|
||||
out[i].Add(out[i], l.vectors[0][i]).Add(out[i], l.vectors[0][i])
|
||||
}
|
||||
out[0].Add(out[0], k)
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (l *lattice) Precompute(add func(i, j uint)) {
|
||||
n := uint(len(l.vectors))
|
||||
total := uint(1) << n
|
||||
|
||||
for i := uint(0); i < n; i++ {
|
||||
for j := uint(0); j < total; j++ {
|
||||
if (j>>i)&1 == 1 {
|
||||
add(i, j)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *lattice) Multi(scalar *big.Int) []uint8 {
|
||||
decomp := l.decompose(scalar)
|
||||
|
||||
maxLen := 0
|
||||
for _, x := range decomp {
|
||||
if x.BitLen() > maxLen {
|
||||
maxLen = x.BitLen()
|
||||
}
|
||||
}
|
||||
|
||||
out := make([]uint8, maxLen)
|
||||
for j, x := range decomp {
|
||||
for i := 0; i < maxLen; i++ {
|
||||
out[i] += uint8(x.Bit(i)) << uint(j)
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// round sets num to num/denom rounded to the nearest integer.
|
||||
func round(num, denom *big.Int) {
|
||||
r := new(big.Int)
|
||||
num.DivMod(num, denom, r)
|
||||
|
||||
if r.Cmp(half) == 1 {
|
||||
num.Add(num, big.NewInt(1))
|
||||
}
|
||||
}
|
||||
181
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_amd64.h
generated
vendored
Normal file
181
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_amd64.h
generated
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
#define mul(a0,a1,a2,a3, rb, stack) \
|
||||
MOVQ a0, AX \
|
||||
MULQ 0+rb \
|
||||
MOVQ AX, R8 \
|
||||
MOVQ DX, R9 \
|
||||
MOVQ a0, AX \
|
||||
MULQ 8+rb \
|
||||
ADDQ AX, R9 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R10 \
|
||||
MOVQ a0, AX \
|
||||
MULQ 16+rb \
|
||||
ADDQ AX, R10 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R11 \
|
||||
MOVQ a0, AX \
|
||||
MULQ 24+rb \
|
||||
ADDQ AX, R11 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R12 \
|
||||
\
|
||||
storeBlock(R8,R9,R10,R11, 0+stack) \
|
||||
MOVQ R12, 32+stack \
|
||||
\
|
||||
MOVQ a1, AX \
|
||||
MULQ 0+rb \
|
||||
MOVQ AX, R8 \
|
||||
MOVQ DX, R9 \
|
||||
MOVQ a1, AX \
|
||||
MULQ 8+rb \
|
||||
ADDQ AX, R9 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R10 \
|
||||
MOVQ a1, AX \
|
||||
MULQ 16+rb \
|
||||
ADDQ AX, R10 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R11 \
|
||||
MOVQ a1, AX \
|
||||
MULQ 24+rb \
|
||||
ADDQ AX, R11 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R12 \
|
||||
\
|
||||
ADDQ 8+stack, R8 \
|
||||
ADCQ 16+stack, R9 \
|
||||
ADCQ 24+stack, R10 \
|
||||
ADCQ 32+stack, R11 \
|
||||
ADCQ $0, R12 \
|
||||
storeBlock(R8,R9,R10,R11, 8+stack) \
|
||||
MOVQ R12, 40+stack \
|
||||
\
|
||||
MOVQ a2, AX \
|
||||
MULQ 0+rb \
|
||||
MOVQ AX, R8 \
|
||||
MOVQ DX, R9 \
|
||||
MOVQ a2, AX \
|
||||
MULQ 8+rb \
|
||||
ADDQ AX, R9 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R10 \
|
||||
MOVQ a2, AX \
|
||||
MULQ 16+rb \
|
||||
ADDQ AX, R10 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R11 \
|
||||
MOVQ a2, AX \
|
||||
MULQ 24+rb \
|
||||
ADDQ AX, R11 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R12 \
|
||||
\
|
||||
ADDQ 16+stack, R8 \
|
||||
ADCQ 24+stack, R9 \
|
||||
ADCQ 32+stack, R10 \
|
||||
ADCQ 40+stack, R11 \
|
||||
ADCQ $0, R12 \
|
||||
storeBlock(R8,R9,R10,R11, 16+stack) \
|
||||
MOVQ R12, 48+stack \
|
||||
\
|
||||
MOVQ a3, AX \
|
||||
MULQ 0+rb \
|
||||
MOVQ AX, R8 \
|
||||
MOVQ DX, R9 \
|
||||
MOVQ a3, AX \
|
||||
MULQ 8+rb \
|
||||
ADDQ AX, R9 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R10 \
|
||||
MOVQ a3, AX \
|
||||
MULQ 16+rb \
|
||||
ADDQ AX, R10 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R11 \
|
||||
MOVQ a3, AX \
|
||||
MULQ 24+rb \
|
||||
ADDQ AX, R11 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R12 \
|
||||
\
|
||||
ADDQ 24+stack, R8 \
|
||||
ADCQ 32+stack, R9 \
|
||||
ADCQ 40+stack, R10 \
|
||||
ADCQ 48+stack, R11 \
|
||||
ADCQ $0, R12 \
|
||||
storeBlock(R8,R9,R10,R11, 24+stack) \
|
||||
MOVQ R12, 56+stack
|
||||
|
||||
#define gfpReduce(stack) \
|
||||
\ // m = (T * N') mod R, store m in R8:R9:R10:R11
|
||||
MOVQ ·np+0(SB), AX \
|
||||
MULQ 0+stack \
|
||||
MOVQ AX, R8 \
|
||||
MOVQ DX, R9 \
|
||||
MOVQ ·np+0(SB), AX \
|
||||
MULQ 8+stack \
|
||||
ADDQ AX, R9 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R10 \
|
||||
MOVQ ·np+0(SB), AX \
|
||||
MULQ 16+stack \
|
||||
ADDQ AX, R10 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R11 \
|
||||
MOVQ ·np+0(SB), AX \
|
||||
MULQ 24+stack \
|
||||
ADDQ AX, R11 \
|
||||
\
|
||||
MOVQ ·np+8(SB), AX \
|
||||
MULQ 0+stack \
|
||||
MOVQ AX, R12 \
|
||||
MOVQ DX, R13 \
|
||||
MOVQ ·np+8(SB), AX \
|
||||
MULQ 8+stack \
|
||||
ADDQ AX, R13 \
|
||||
ADCQ $0, DX \
|
||||
MOVQ DX, R14 \
|
||||
MOVQ ·np+8(SB), AX \
|
||||
MULQ 16+stack \
|
||||
ADDQ AX, R14 \
|
||||
\
|
||||
ADDQ R12, R9 \
|
||||
ADCQ R13, R10 \
|
||||
ADCQ R14, R11 \
|
||||
\
|
||||
MOVQ ·np+16(SB), AX \
|
||||
MULQ 0+stack \
|
||||
MOVQ AX, R12 \
|
||||
MOVQ DX, R13 \
|
||||
MOVQ ·np+16(SB), AX \
|
||||
MULQ 8+stack \
|
||||
ADDQ AX, R13 \
|
||||
\
|
||||
ADDQ R12, R10 \
|
||||
ADCQ R13, R11 \
|
||||
\
|
||||
MOVQ ·np+24(SB), AX \
|
||||
MULQ 0+stack \
|
||||
ADDQ AX, R11 \
|
||||
\
|
||||
storeBlock(R8,R9,R10,R11, 64+stack) \
|
||||
\
|
||||
\ // m * N
|
||||
mul(·p2+0(SB),·p2+8(SB),·p2+16(SB),·p2+24(SB), 64+stack, 96+stack) \
|
||||
\
|
||||
\ // Add the 512-bit intermediate to m*N
|
||||
loadBlock(96+stack, R8,R9,R10,R11) \
|
||||
loadBlock(128+stack, R12,R13,R14,CX) \
|
||||
\
|
||||
MOVQ $0, AX \
|
||||
ADDQ 0+stack, R8 \
|
||||
ADCQ 8+stack, R9 \
|
||||
ADCQ 16+stack, R10 \
|
||||
ADCQ 24+stack, R11 \
|
||||
ADCQ 32+stack, R12 \
|
||||
ADCQ 40+stack, R13 \
|
||||
ADCQ 48+stack, R14 \
|
||||
ADCQ 56+stack, CX \
|
||||
ADCQ $0, AX \
|
||||
\
|
||||
gfpCarry(R12,R13,R14,CX,AX, R8,R9,R10,R11,BX)
|
||||
133
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_arm64.h
generated
vendored
Normal file
133
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_arm64.h
generated
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
#define mul(c0,c1,c2,c3,c4,c5,c6,c7) \
|
||||
MUL R1, R5, c0 \
|
||||
UMULH R1, R5, c1 \
|
||||
MUL R1, R6, R0 \
|
||||
ADDS R0, c1 \
|
||||
UMULH R1, R6, c2 \
|
||||
MUL R1, R7, R0 \
|
||||
ADCS R0, c2 \
|
||||
UMULH R1, R7, c3 \
|
||||
MUL R1, R8, R0 \
|
||||
ADCS R0, c3 \
|
||||
UMULH R1, R8, c4 \
|
||||
ADCS ZR, c4 \
|
||||
\
|
||||
MUL R2, R5, R1 \
|
||||
UMULH R2, R5, R26 \
|
||||
MUL R2, R6, R0 \
|
||||
ADDS R0, R26 \
|
||||
UMULH R2, R6, R27 \
|
||||
MUL R2, R7, R0 \
|
||||
ADCS R0, R27 \
|
||||
UMULH R2, R7, R29 \
|
||||
MUL R2, R8, R0 \
|
||||
ADCS R0, R29 \
|
||||
UMULH R2, R8, c5 \
|
||||
ADCS ZR, c5 \
|
||||
ADDS R1, c1 \
|
||||
ADCS R26, c2 \
|
||||
ADCS R27, c3 \
|
||||
ADCS R29, c4 \
|
||||
ADCS ZR, c5 \
|
||||
\
|
||||
MUL R3, R5, R1 \
|
||||
UMULH R3, R5, R26 \
|
||||
MUL R3, R6, R0 \
|
||||
ADDS R0, R26 \
|
||||
UMULH R3, R6, R27 \
|
||||
MUL R3, R7, R0 \
|
||||
ADCS R0, R27 \
|
||||
UMULH R3, R7, R29 \
|
||||
MUL R3, R8, R0 \
|
||||
ADCS R0, R29 \
|
||||
UMULH R3, R8, c6 \
|
||||
ADCS ZR, c6 \
|
||||
ADDS R1, c2 \
|
||||
ADCS R26, c3 \
|
||||
ADCS R27, c4 \
|
||||
ADCS R29, c5 \
|
||||
ADCS ZR, c6 \
|
||||
\
|
||||
MUL R4, R5, R1 \
|
||||
UMULH R4, R5, R26 \
|
||||
MUL R4, R6, R0 \
|
||||
ADDS R0, R26 \
|
||||
UMULH R4, R6, R27 \
|
||||
MUL R4, R7, R0 \
|
||||
ADCS R0, R27 \
|
||||
UMULH R4, R7, R29 \
|
||||
MUL R4, R8, R0 \
|
||||
ADCS R0, R29 \
|
||||
UMULH R4, R8, c7 \
|
||||
ADCS ZR, c7 \
|
||||
ADDS R1, c3 \
|
||||
ADCS R26, c4 \
|
||||
ADCS R27, c5 \
|
||||
ADCS R29, c6 \
|
||||
ADCS ZR, c7
|
||||
|
||||
#define gfpReduce() \
|
||||
\ // m = (T * N') mod R, store m in R1:R2:R3:R4
|
||||
MOVD ·np+0(SB), R17 \
|
||||
MOVD ·np+8(SB), R25 \
|
||||
MOVD ·np+16(SB), R19 \
|
||||
MOVD ·np+24(SB), R20 \
|
||||
\
|
||||
MUL R9, R17, R1 \
|
||||
UMULH R9, R17, R2 \
|
||||
MUL R9, R25, R0 \
|
||||
ADDS R0, R2 \
|
||||
UMULH R9, R25, R3 \
|
||||
MUL R9, R19, R0 \
|
||||
ADCS R0, R3 \
|
||||
UMULH R9, R19, R4 \
|
||||
MUL R9, R20, R0 \
|
||||
ADCS R0, R4 \
|
||||
\
|
||||
MUL R10, R17, R21 \
|
||||
UMULH R10, R17, R22 \
|
||||
MUL R10, R25, R0 \
|
||||
ADDS R0, R22 \
|
||||
UMULH R10, R25, R23 \
|
||||
MUL R10, R19, R0 \
|
||||
ADCS R0, R23 \
|
||||
ADDS R21, R2 \
|
||||
ADCS R22, R3 \
|
||||
ADCS R23, R4 \
|
||||
\
|
||||
MUL R11, R17, R21 \
|
||||
UMULH R11, R17, R22 \
|
||||
MUL R11, R25, R0 \
|
||||
ADDS R0, R22 \
|
||||
ADDS R21, R3 \
|
||||
ADCS R22, R4 \
|
||||
\
|
||||
MUL R12, R17, R21 \
|
||||
ADDS R21, R4 \
|
||||
\
|
||||
\ // m * N
|
||||
loadModulus(R5,R6,R7,R8) \
|
||||
mul(R17,R25,R19,R20,R21,R22,R23,R24) \
|
||||
\
|
||||
\ // Add the 512-bit intermediate to m*N
|
||||
MOVD ZR, R0 \
|
||||
ADDS R9, R17 \
|
||||
ADCS R10, R25 \
|
||||
ADCS R11, R19 \
|
||||
ADCS R12, R20 \
|
||||
ADCS R13, R21 \
|
||||
ADCS R14, R22 \
|
||||
ADCS R15, R23 \
|
||||
ADCS R16, R24 \
|
||||
ADCS ZR, R0 \
|
||||
\
|
||||
\ // Our output is R21:R22:R23:R24. Reduce mod p if necessary.
|
||||
SUBS R5, R21, R10 \
|
||||
SBCS R6, R22, R11 \
|
||||
SBCS R7, R23, R12 \
|
||||
SBCS R8, R24, R13 \
|
||||
\
|
||||
CSEL CS, R10, R21, R1 \
|
||||
CSEL CS, R11, R22, R2 \
|
||||
CSEL CS, R12, R23, R3 \
|
||||
CSEL CS, R13, R24, R4
|
||||
112
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_bmi2_amd64.h
generated
vendored
Normal file
112
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/mul_bmi2_amd64.h
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
#define mulBMI2(a0,a1,a2,a3, rb) \
|
||||
MOVQ a0, DX \
|
||||
MOVQ $0, R13 \
|
||||
MULXQ 0+rb, R8, R9 \
|
||||
MULXQ 8+rb, AX, R10 \
|
||||
ADDQ AX, R9 \
|
||||
MULXQ 16+rb, AX, R11 \
|
||||
ADCQ AX, R10 \
|
||||
MULXQ 24+rb, AX, R12 \
|
||||
ADCQ AX, R11 \
|
||||
ADCQ $0, R12 \
|
||||
ADCQ $0, R13 \
|
||||
\
|
||||
MOVQ a1, DX \
|
||||
MOVQ $0, R14 \
|
||||
MULXQ 0+rb, AX, BX \
|
||||
ADDQ AX, R9 \
|
||||
ADCQ BX, R10 \
|
||||
MULXQ 16+rb, AX, BX \
|
||||
ADCQ AX, R11 \
|
||||
ADCQ BX, R12 \
|
||||
ADCQ $0, R13 \
|
||||
MULXQ 8+rb, AX, BX \
|
||||
ADDQ AX, R10 \
|
||||
ADCQ BX, R11 \
|
||||
MULXQ 24+rb, AX, BX \
|
||||
ADCQ AX, R12 \
|
||||
ADCQ BX, R13 \
|
||||
ADCQ $0, R14 \
|
||||
\
|
||||
MOVQ a2, DX \
|
||||
MOVQ $0, CX \
|
||||
MULXQ 0+rb, AX, BX \
|
||||
ADDQ AX, R10 \
|
||||
ADCQ BX, R11 \
|
||||
MULXQ 16+rb, AX, BX \
|
||||
ADCQ AX, R12 \
|
||||
ADCQ BX, R13 \
|
||||
ADCQ $0, R14 \
|
||||
MULXQ 8+rb, AX, BX \
|
||||
ADDQ AX, R11 \
|
||||
ADCQ BX, R12 \
|
||||
MULXQ 24+rb, AX, BX \
|
||||
ADCQ AX, R13 \
|
||||
ADCQ BX, R14 \
|
||||
ADCQ $0, CX \
|
||||
\
|
||||
MOVQ a3, DX \
|
||||
MULXQ 0+rb, AX, BX \
|
||||
ADDQ AX, R11 \
|
||||
ADCQ BX, R12 \
|
||||
MULXQ 16+rb, AX, BX \
|
||||
ADCQ AX, R13 \
|
||||
ADCQ BX, R14 \
|
||||
ADCQ $0, CX \
|
||||
MULXQ 8+rb, AX, BX \
|
||||
ADDQ AX, R12 \
|
||||
ADCQ BX, R13 \
|
||||
MULXQ 24+rb, AX, BX \
|
||||
ADCQ AX, R14 \
|
||||
ADCQ BX, CX
|
||||
|
||||
#define gfpReduceBMI2() \
|
||||
\ // m = (T * N') mod R, store m in R8:R9:R10:R11
|
||||
MOVQ ·np+0(SB), DX \
|
||||
MULXQ 0(SP), R8, R9 \
|
||||
MULXQ 8(SP), AX, R10 \
|
||||
ADDQ AX, R9 \
|
||||
MULXQ 16(SP), AX, R11 \
|
||||
ADCQ AX, R10 \
|
||||
MULXQ 24(SP), AX, BX \
|
||||
ADCQ AX, R11 \
|
||||
\
|
||||
MOVQ ·np+8(SB), DX \
|
||||
MULXQ 0(SP), AX, BX \
|
||||
ADDQ AX, R9 \
|
||||
ADCQ BX, R10 \
|
||||
MULXQ 16(SP), AX, BX \
|
||||
ADCQ AX, R11 \
|
||||
MULXQ 8(SP), AX, BX \
|
||||
ADDQ AX, R10 \
|
||||
ADCQ BX, R11 \
|
||||
\
|
||||
MOVQ ·np+16(SB), DX \
|
||||
MULXQ 0(SP), AX, BX \
|
||||
ADDQ AX, R10 \
|
||||
ADCQ BX, R11 \
|
||||
MULXQ 8(SP), AX, BX \
|
||||
ADDQ AX, R11 \
|
||||
\
|
||||
MOVQ ·np+24(SB), DX \
|
||||
MULXQ 0(SP), AX, BX \
|
||||
ADDQ AX, R11 \
|
||||
\
|
||||
storeBlock(R8,R9,R10,R11, 64(SP)) \
|
||||
\
|
||||
\ // m * N
|
||||
mulBMI2(·p2+0(SB),·p2+8(SB),·p2+16(SB),·p2+24(SB), 64(SP)) \
|
||||
\
|
||||
\ // Add the 512-bit intermediate to m*N
|
||||
MOVQ $0, AX \
|
||||
ADDQ 0(SP), R8 \
|
||||
ADCQ 8(SP), R9 \
|
||||
ADCQ 16(SP), R10 \
|
||||
ADCQ 24(SP), R11 \
|
||||
ADCQ 32(SP), R12 \
|
||||
ADCQ 40(SP), R13 \
|
||||
ADCQ 48(SP), R14 \
|
||||
ADCQ 56(SP), CX \
|
||||
ADCQ $0, AX \
|
||||
\
|
||||
gfpCarry(R12,R13,R14,CX,AX, R8,R9,R10,R11,BX)
|
||||
271
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/optate.go
generated
vendored
Normal file
271
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/optate.go
generated
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
package bn256
|
||||
|
||||
func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2) (a, b, c *gfP2, rOut *twistPoint) {
|
||||
// See the mixed addition algorithm from "Faster Computation of the
|
||||
// Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
|
||||
B := (&gfP2{}).Mul(&p.x, &r.t)
|
||||
|
||||
D := (&gfP2{}).Add(&p.y, &r.z)
|
||||
D.Square(D).Sub(D, r2).Sub(D, &r.t).Mul(D, &r.t)
|
||||
|
||||
H := (&gfP2{}).Sub(B, &r.x)
|
||||
I := (&gfP2{}).Square(H)
|
||||
|
||||
E := (&gfP2{}).Add(I, I)
|
||||
E.Add(E, E)
|
||||
|
||||
J := (&gfP2{}).Mul(H, E)
|
||||
|
||||
L1 := (&gfP2{}).Sub(D, &r.y)
|
||||
L1.Sub(L1, &r.y)
|
||||
|
||||
V := (&gfP2{}).Mul(&r.x, E)
|
||||
|
||||
rOut = &twistPoint{}
|
||||
rOut.x.Square(L1).Sub(&rOut.x, J).Sub(&rOut.x, V).Sub(&rOut.x, V)
|
||||
|
||||
rOut.z.Add(&r.z, H).Square(&rOut.z).Sub(&rOut.z, &r.t).Sub(&rOut.z, I)
|
||||
|
||||
t := (&gfP2{}).Sub(V, &rOut.x)
|
||||
t.Mul(t, L1)
|
||||
t2 := (&gfP2{}).Mul(&r.y, J)
|
||||
t2.Add(t2, t2)
|
||||
rOut.y.Sub(t, t2)
|
||||
|
||||
rOut.t.Square(&rOut.z)
|
||||
|
||||
t.Add(&p.y, &rOut.z).Square(t).Sub(t, r2).Sub(t, &rOut.t)
|
||||
|
||||
t2.Mul(L1, &p.x)
|
||||
t2.Add(t2, t2)
|
||||
a = (&gfP2{}).Sub(t2, t)
|
||||
|
||||
c = (&gfP2{}).MulScalar(&rOut.z, &q.y)
|
||||
c.Add(c, c)
|
||||
|
||||
b = (&gfP2{}).Neg(L1)
|
||||
b.MulScalar(b, &q.x).Add(b, b)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func lineFunctionDouble(r *twistPoint, q *curvePoint) (a, b, c *gfP2, rOut *twistPoint) {
|
||||
// See the doubling algorithm for a=0 from "Faster Computation of the
|
||||
// Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
|
||||
A := (&gfP2{}).Square(&r.x)
|
||||
B := (&gfP2{}).Square(&r.y)
|
||||
C := (&gfP2{}).Square(B)
|
||||
|
||||
D := (&gfP2{}).Add(&r.x, B)
|
||||
D.Square(D).Sub(D, A).Sub(D, C).Add(D, D)
|
||||
|
||||
E := (&gfP2{}).Add(A, A)
|
||||
E.Add(E, A)
|
||||
|
||||
G := (&gfP2{}).Square(E)
|
||||
|
||||
rOut = &twistPoint{}
|
||||
rOut.x.Sub(G, D).Sub(&rOut.x, D)
|
||||
|
||||
rOut.z.Add(&r.y, &r.z).Square(&rOut.z).Sub(&rOut.z, B).Sub(&rOut.z, &r.t)
|
||||
|
||||
rOut.y.Sub(D, &rOut.x).Mul(&rOut.y, E)
|
||||
t := (&gfP2{}).Add(C, C)
|
||||
t.Add(t, t).Add(t, t)
|
||||
rOut.y.Sub(&rOut.y, t)
|
||||
|
||||
rOut.t.Square(&rOut.z)
|
||||
|
||||
t.Mul(E, &r.t).Add(t, t)
|
||||
b = (&gfP2{}).Neg(t)
|
||||
b.MulScalar(b, &q.x)
|
||||
|
||||
a = (&gfP2{}).Add(&r.x, E)
|
||||
a.Square(a).Sub(a, A).Sub(a, G)
|
||||
t.Add(B, B).Add(t, t)
|
||||
a.Sub(a, t)
|
||||
|
||||
c = (&gfP2{}).Mul(&rOut.z, &r.t)
|
||||
c.Add(c, c).MulScalar(c, &q.y)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func mulLine(ret *gfP12, a, b, c *gfP2) {
|
||||
a2 := &gfP6{}
|
||||
a2.y.Set(a)
|
||||
a2.z.Set(b)
|
||||
a2.Mul(a2, &ret.x)
|
||||
t3 := (&gfP6{}).MulScalar(&ret.y, c)
|
||||
|
||||
t := (&gfP2{}).Add(b, c)
|
||||
t2 := &gfP6{}
|
||||
t2.y.Set(a)
|
||||
t2.z.Set(t)
|
||||
ret.x.Add(&ret.x, &ret.y)
|
||||
|
||||
ret.y.Set(t3)
|
||||
|
||||
ret.x.Mul(&ret.x, t2).Sub(&ret.x, a2).Sub(&ret.x, &ret.y)
|
||||
a2.MulTau(a2)
|
||||
ret.y.Add(&ret.y, a2)
|
||||
}
|
||||
|
||||
// sixuPlus2NAF is 6u+2 in non-adjacent form.
|
||||
var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0,
|
||||
0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0, 1, 1,
|
||||
1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1,
|
||||
1, 0, 0, -1, 0, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, 1, 1}
|
||||
|
||||
// miller implements the Miller loop for calculating the Optimal Ate pairing.
|
||||
// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf
|
||||
func miller(q *twistPoint, p *curvePoint) *gfP12 {
|
||||
ret := (&gfP12{}).SetOne()
|
||||
|
||||
aAffine := &twistPoint{}
|
||||
aAffine.Set(q)
|
||||
aAffine.MakeAffine()
|
||||
|
||||
bAffine := &curvePoint{}
|
||||
bAffine.Set(p)
|
||||
bAffine.MakeAffine()
|
||||
|
||||
minusA := &twistPoint{}
|
||||
minusA.Neg(aAffine)
|
||||
|
||||
r := &twistPoint{}
|
||||
r.Set(aAffine)
|
||||
|
||||
r2 := (&gfP2{}).Square(&aAffine.y)
|
||||
|
||||
for i := len(sixuPlus2NAF) - 1; i > 0; i-- {
|
||||
a, b, c, newR := lineFunctionDouble(r, bAffine)
|
||||
if i != len(sixuPlus2NAF)-1 {
|
||||
ret.Square(ret)
|
||||
}
|
||||
|
||||
mulLine(ret, a, b, c)
|
||||
r = newR
|
||||
|
||||
switch sixuPlus2NAF[i-1] {
|
||||
case 1:
|
||||
a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2)
|
||||
case -1:
|
||||
a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
mulLine(ret, a, b, c)
|
||||
r = newR
|
||||
}
|
||||
|
||||
// In order to calculate Q1 we have to convert q from the sextic twist
|
||||
// to the full GF(p^12) group, apply the Frobenius there, and convert
|
||||
// back.
|
||||
//
|
||||
// The twist isomorphism is (x', y') -> (xω², yω³). If we consider just
|
||||
// x for a moment, then after applying the Frobenius, we have x̄ω^(2p)
|
||||
// where x̄ is the conjugate of x. If we are going to apply the inverse
|
||||
// isomorphism we need a value with a single coefficient of ω² so we
|
||||
// rewrite this as x̄ω^(2p-2)ω². ξ⁶ = ω and, due to the construction of
|
||||
// p, 2p-2 is a multiple of six. Therefore we can rewrite as
|
||||
// x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the
|
||||
// ω².
|
||||
//
|
||||
// A similar argument can be made for the y value.
|
||||
|
||||
q1 := &twistPoint{}
|
||||
q1.x.Conjugate(&aAffine.x).Mul(&q1.x, xiToPMinus1Over3)
|
||||
q1.y.Conjugate(&aAffine.y).Mul(&q1.y, xiToPMinus1Over2)
|
||||
q1.z.SetOne()
|
||||
q1.t.SetOne()
|
||||
|
||||
// For Q2 we are applying the p² Frobenius. The two conjugations cancel
|
||||
// out and we are left only with the factors from the isomorphism. In
|
||||
// the case of x, we end up with a pure number which is why
|
||||
// xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We
|
||||
// ignore this to end up with -Q2.
|
||||
|
||||
minusQ2 := &twistPoint{}
|
||||
minusQ2.x.MulScalar(&aAffine.x, xiToPSquaredMinus1Over3)
|
||||
minusQ2.y.Set(&aAffine.y)
|
||||
minusQ2.z.SetOne()
|
||||
minusQ2.t.SetOne()
|
||||
|
||||
r2.Square(&q1.y)
|
||||
a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2)
|
||||
mulLine(ret, a, b, c)
|
||||
r = newR
|
||||
|
||||
r2.Square(&minusQ2.y)
|
||||
a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2)
|
||||
mulLine(ret, a, b, c)
|
||||
r = newR
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// finalExponentiation computes the (p¹²-1)/Order-th power of an element of
|
||||
// GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from
|
||||
// http://cryptojedi.org/papers/dclxvi-20100714.pdf)
|
||||
func finalExponentiation(in *gfP12) *gfP12 {
|
||||
t1 := &gfP12{}
|
||||
|
||||
// This is the p^6-Frobenius
|
||||
t1.x.Neg(&in.x)
|
||||
t1.y.Set(&in.y)
|
||||
|
||||
inv := &gfP12{}
|
||||
inv.Invert(in)
|
||||
t1.Mul(t1, inv)
|
||||
|
||||
t2 := (&gfP12{}).FrobeniusP2(t1)
|
||||
t1.Mul(t1, t2)
|
||||
|
||||
fp := (&gfP12{}).Frobenius(t1)
|
||||
fp2 := (&gfP12{}).FrobeniusP2(t1)
|
||||
fp3 := (&gfP12{}).Frobenius(fp2)
|
||||
|
||||
fu := (&gfP12{}).Exp(t1, u)
|
||||
fu2 := (&gfP12{}).Exp(fu, u)
|
||||
fu3 := (&gfP12{}).Exp(fu2, u)
|
||||
|
||||
y3 := (&gfP12{}).Frobenius(fu)
|
||||
fu2p := (&gfP12{}).Frobenius(fu2)
|
||||
fu3p := (&gfP12{}).Frobenius(fu3)
|
||||
y2 := (&gfP12{}).FrobeniusP2(fu2)
|
||||
|
||||
y0 := &gfP12{}
|
||||
y0.Mul(fp, fp2).Mul(y0, fp3)
|
||||
|
||||
y1 := (&gfP12{}).Conjugate(t1)
|
||||
y5 := (&gfP12{}).Conjugate(fu2)
|
||||
y3.Conjugate(y3)
|
||||
y4 := (&gfP12{}).Mul(fu, fu2p)
|
||||
y4.Conjugate(y4)
|
||||
|
||||
y6 := (&gfP12{}).Mul(fu3, fu3p)
|
||||
y6.Conjugate(y6)
|
||||
|
||||
t0 := (&gfP12{}).Square(y6)
|
||||
t0.Mul(t0, y4).Mul(t0, y5)
|
||||
t1.Mul(y3, y5).Mul(t1, t0)
|
||||
t0.Mul(t0, y2)
|
||||
t1.Square(t1).Mul(t1, t0).Square(t1)
|
||||
t0.Mul(t1, y1)
|
||||
t1.Mul(t1, y0)
|
||||
t0.Square(t0).Mul(t0, t1)
|
||||
|
||||
return t0
|
||||
}
|
||||
|
||||
func optimalAte(a *twistPoint, b *curvePoint) *gfP12 {
|
||||
e := miller(a, b)
|
||||
ret := finalExponentiation(e)
|
||||
|
||||
if a.IsInfinity() || b.IsInfinity() {
|
||||
ret.SetOne()
|
||||
}
|
||||
return ret
|
||||
}
|
||||
204
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/twist.go
generated
vendored
Normal file
204
vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/twist.go
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
package bn256
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are
|
||||
// kept in Jacobian form and t=z² when valid. The group G₂ is the set of
|
||||
// n-torsion points of this curve over GF(p²) (where n = Order)
|
||||
type twistPoint struct {
|
||||
x, y, z, t gfP2
|
||||
}
|
||||
|
||||
var twistB = &gfP2{
|
||||
gfP{0x38e7ecccd1dcff67, 0x65f0b37d93ce0d3e, 0xd749d0dd22ac00aa, 0x0141b9ce4a688d4d},
|
||||
gfP{0x3bf938e377b802a8, 0x020b1b273633535d, 0x26b7edf049755260, 0x2514c6324384a86d},
|
||||
}
|
||||
|
||||
// twistGen is the generator of group G₂.
|
||||
var twistGen = &twistPoint{
|
||||
gfP2{
|
||||
gfP{0xafb4737da84c6140, 0x6043dd5a5802d8c4, 0x09e950fc52a02f86, 0x14fef0833aea7b6b},
|
||||
gfP{0x8e83b5d102bc2026, 0xdceb1935497b0172, 0xfbb8264797811adf, 0x19573841af96503b},
|
||||
},
|
||||
gfP2{
|
||||
gfP{0x64095b56c71856ee, 0xdc57f922327d3cbb, 0x55f935be33351076, 0x0da4a0e693fd6482},
|
||||
gfP{0x619dfa9d886be9f6, 0xfe7fd297f59e9b78, 0xff9e1a62231b7dfe, 0x28fd7eebae9e4206},
|
||||
},
|
||||
gfP2{*newGFp(0), *newGFp(1)},
|
||||
gfP2{*newGFp(0), *newGFp(1)},
|
||||
}
|
||||
|
||||
func (c *twistPoint) String() string {
|
||||
c.MakeAffine()
|
||||
x, y := gfP2Decode(&c.x), gfP2Decode(&c.y)
|
||||
return "(" + x.String() + ", " + y.String() + ")"
|
||||
}
|
||||
|
||||
func (c *twistPoint) Set(a *twistPoint) {
|
||||
c.x.Set(&a.x)
|
||||
c.y.Set(&a.y)
|
||||
c.z.Set(&a.z)
|
||||
c.t.Set(&a.t)
|
||||
}
|
||||
|
||||
// IsOnCurve returns true iff c is on the curve.
|
||||
func (c *twistPoint) IsOnCurve() bool {
|
||||
c.MakeAffine()
|
||||
if c.IsInfinity() {
|
||||
return true
|
||||
}
|
||||
|
||||
y2, x3 := &gfP2{}, &gfP2{}
|
||||
y2.Square(&c.y)
|
||||
x3.Square(&c.x).Mul(x3, &c.x).Add(x3, twistB)
|
||||
|
||||
if *y2 != *x3 {
|
||||
return false
|
||||
}
|
||||
cneg := &twistPoint{}
|
||||
cneg.Mul(c, Order)
|
||||
return cneg.z.IsZero()
|
||||
}
|
||||
|
||||
func (c *twistPoint) SetInfinity() {
|
||||
c.x.SetZero()
|
||||
c.y.SetOne()
|
||||
c.z.SetZero()
|
||||
c.t.SetZero()
|
||||
}
|
||||
|
||||
func (c *twistPoint) IsInfinity() bool {
|
||||
return c.z.IsZero()
|
||||
}
|
||||
|
||||
func (c *twistPoint) Add(a, b *twistPoint) {
|
||||
// For additional comments, see the same function in curve.go.
|
||||
|
||||
if a.IsInfinity() {
|
||||
c.Set(b)
|
||||
return
|
||||
}
|
||||
if b.IsInfinity() {
|
||||
c.Set(a)
|
||||
return
|
||||
}
|
||||
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
|
||||
z12 := (&gfP2{}).Square(&a.z)
|
||||
z22 := (&gfP2{}).Square(&b.z)
|
||||
u1 := (&gfP2{}).Mul(&a.x, z22)
|
||||
u2 := (&gfP2{}).Mul(&b.x, z12)
|
||||
|
||||
t := (&gfP2{}).Mul(&b.z, z22)
|
||||
s1 := (&gfP2{}).Mul(&a.y, t)
|
||||
|
||||
t.Mul(&a.z, z12)
|
||||
s2 := (&gfP2{}).Mul(&b.y, t)
|
||||
|
||||
h := (&gfP2{}).Sub(u2, u1)
|
||||
xEqual := h.IsZero()
|
||||
|
||||
t.Add(h, h)
|
||||
i := (&gfP2{}).Square(t)
|
||||
j := (&gfP2{}).Mul(h, i)
|
||||
|
||||
t.Sub(s2, s1)
|
||||
yEqual := t.IsZero()
|
||||
if xEqual && yEqual {
|
||||
c.Double(a)
|
||||
return
|
||||
}
|
||||
r := (&gfP2{}).Add(t, t)
|
||||
|
||||
v := (&gfP2{}).Mul(u1, i)
|
||||
|
||||
t4 := (&gfP2{}).Square(r)
|
||||
t.Add(v, v)
|
||||
t6 := (&gfP2{}).Sub(t4, j)
|
||||
c.x.Sub(t6, t)
|
||||
|
||||
t.Sub(v, &c.x) // t7
|
||||
t4.Mul(s1, j) // t8
|
||||
t6.Add(t4, t4) // t9
|
||||
t4.Mul(r, t) // t10
|
||||
c.y.Sub(t4, t6)
|
||||
|
||||
t.Add(&a.z, &b.z) // t11
|
||||
t4.Square(t) // t12
|
||||
t.Sub(t4, z12) // t13
|
||||
t4.Sub(t, z22) // t14
|
||||
c.z.Mul(t4, h)
|
||||
}
|
||||
|
||||
func (c *twistPoint) Double(a *twistPoint) {
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
|
||||
A := (&gfP2{}).Square(&a.x)
|
||||
B := (&gfP2{}).Square(&a.y)
|
||||
C := (&gfP2{}).Square(B)
|
||||
|
||||
t := (&gfP2{}).Add(&a.x, B)
|
||||
t2 := (&gfP2{}).Square(t)
|
||||
t.Sub(t2, A)
|
||||
t2.Sub(t, C)
|
||||
d := (&gfP2{}).Add(t2, t2)
|
||||
t.Add(A, A)
|
||||
e := (&gfP2{}).Add(t, A)
|
||||
f := (&gfP2{}).Square(e)
|
||||
|
||||
t.Add(d, d)
|
||||
c.x.Sub(f, t)
|
||||
|
||||
c.z.Mul(&a.y, &a.z)
|
||||
c.z.Add(&c.z, &c.z)
|
||||
|
||||
t.Add(C, C)
|
||||
t2.Add(t, t)
|
||||
t.Add(t2, t2)
|
||||
c.y.Sub(d, &c.x)
|
||||
t2.Mul(e, &c.y)
|
||||
c.y.Sub(t2, t)
|
||||
}
|
||||
|
||||
func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int) {
|
||||
sum, t := &twistPoint{}, &twistPoint{}
|
||||
|
||||
for i := scalar.BitLen(); i >= 0; i-- {
|
||||
t.Double(sum)
|
||||
if scalar.Bit(i) != 0 {
|
||||
sum.Add(t, a)
|
||||
} else {
|
||||
sum.Set(t)
|
||||
}
|
||||
}
|
||||
|
||||
c.Set(sum)
|
||||
}
|
||||
|
||||
func (c *twistPoint) MakeAffine() {
|
||||
if c.z.IsOne() {
|
||||
return
|
||||
} else if c.z.IsZero() {
|
||||
c.x.SetZero()
|
||||
c.y.SetOne()
|
||||
c.t.SetZero()
|
||||
return
|
||||
}
|
||||
|
||||
zInv := (&gfP2{}).Invert(&c.z)
|
||||
t := (&gfP2{}).Mul(&c.y, zInv)
|
||||
zInv2 := (&gfP2{}).Square(zInv)
|
||||
c.y.Mul(t, zInv2)
|
||||
t.Mul(&c.x, zInv2)
|
||||
c.x.Set(t)
|
||||
c.z.SetOne()
|
||||
c.t.SetOne()
|
||||
}
|
||||
|
||||
func (c *twistPoint) Neg(a *twistPoint) {
|
||||
c.x.Set(&a.x)
|
||||
c.y.Neg(&a.y)
|
||||
c.z.Set(&a.z)
|
||||
c.t.SetZero()
|
||||
}
|
||||
460
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/bn256.go
generated
vendored
Normal file
460
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/bn256.go
generated
vendored
Normal file
@@ -0,0 +1,460 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package bn256 implements a particular bilinear group.
|
||||
//
|
||||
// Bilinear groups are the basis of many of the new cryptographic protocols
|
||||
// that have been proposed over the past decade. They consist of a triplet of
|
||||
// groups (G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ
|
||||
// (where gₓ is a generator of the respective group). That function is called
|
||||
// a pairing function.
|
||||
//
|
||||
// This package specifically implements the Optimal Ate pairing over a 256-bit
|
||||
// Barreto-Naehrig curve as described in
|
||||
// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is not
|
||||
// compatible with the implementation described in that paper, as different
|
||||
// parameters are chosen.
|
||||
//
|
||||
// (This package previously claimed to operate at a 128-bit security level.
|
||||
// However, recent improvements in attacks mean that is no longer true. See
|
||||
// https://moderncrypto.org/mail-archive/curves/2016/000740.html.)
|
||||
package bn256
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// BUG(agl): this implementation is not constant time.
|
||||
// TODO(agl): keep GF(p²) elements in Mongomery form.
|
||||
|
||||
// G1 is an abstract cyclic group. The zero value is suitable for use as the
|
||||
// output of an operation, but cannot be used as an input.
|
||||
type G1 struct {
|
||||
p *curvePoint
|
||||
}
|
||||
|
||||
// RandomG1 returns x and g₁ˣ where x is a random, non-zero number read from r.
|
||||
func RandomG1(r io.Reader) (*big.Int, *G1, error) {
|
||||
var k *big.Int
|
||||
var err error
|
||||
|
||||
for {
|
||||
k, err = rand.Int(r, Order)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if k.Sign() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return k, new(G1).ScalarBaseMult(k), nil
|
||||
}
|
||||
|
||||
func (e *G1) String() string {
|
||||
return "bn256.G1" + e.p.String()
|
||||
}
|
||||
|
||||
// CurvePoints returns p's curve points in big integer
|
||||
func (e *G1) CurvePoints() (*big.Int, *big.Int, *big.Int, *big.Int) {
|
||||
return e.p.x, e.p.y, e.p.z, e.p.t
|
||||
}
|
||||
|
||||
// ScalarBaseMult sets e to g*k where g is the generator of the group and
|
||||
// then returns e.
|
||||
func (e *G1) ScalarBaseMult(k *big.Int) *G1 {
|
||||
if e.p == nil {
|
||||
e.p = newCurvePoint(nil)
|
||||
}
|
||||
e.p.Mul(curveGen, k, new(bnPool))
|
||||
return e
|
||||
}
|
||||
|
||||
// ScalarMult sets e to a*k and then returns e.
|
||||
func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 {
|
||||
if e.p == nil {
|
||||
e.p = newCurvePoint(nil)
|
||||
}
|
||||
e.p.Mul(a.p, k, new(bnPool))
|
||||
return e
|
||||
}
|
||||
|
||||
// Add sets e to a+b and then returns e.
|
||||
// BUG(agl): this function is not complete: a==b fails.
|
||||
func (e *G1) Add(a, b *G1) *G1 {
|
||||
if e.p == nil {
|
||||
e.p = newCurvePoint(nil)
|
||||
}
|
||||
e.p.Add(a.p, b.p, new(bnPool))
|
||||
return e
|
||||
}
|
||||
|
||||
// Neg sets e to -a and then returns e.
|
||||
func (e *G1) Neg(a *G1) *G1 {
|
||||
if e.p == nil {
|
||||
e.p = newCurvePoint(nil)
|
||||
}
|
||||
e.p.Negative(a.p)
|
||||
return e
|
||||
}
|
||||
|
||||
// Marshal converts n to a byte slice.
|
||||
func (e *G1) Marshal() []byte {
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8
|
||||
|
||||
if e.p.IsInfinity() {
|
||||
return make([]byte, numBytes*2)
|
||||
}
|
||||
|
||||
e.p.MakeAffine(nil)
|
||||
|
||||
xBytes := new(big.Int).Mod(e.p.x, P).Bytes()
|
||||
yBytes := new(big.Int).Mod(e.p.y, P).Bytes()
|
||||
|
||||
ret := make([]byte, numBytes*2)
|
||||
copy(ret[1*numBytes-len(xBytes):], xBytes)
|
||||
copy(ret[2*numBytes-len(yBytes):], yBytes)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Unmarshal sets e to the result of converting the output of Marshal back into
|
||||
// a group element and then returns e.
|
||||
func (e *G1) Unmarshal(m []byte) ([]byte, error) {
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8
|
||||
if len(m) != 2*numBytes {
|
||||
return nil, errors.New("bn256: not enough data")
|
||||
}
|
||||
// Unmarshal the points and check their caps
|
||||
if e.p == nil {
|
||||
e.p = newCurvePoint(nil)
|
||||
}
|
||||
e.p.x.SetBytes(m[0*numBytes : 1*numBytes])
|
||||
if e.p.x.Cmp(P) >= 0 {
|
||||
return nil, errors.New("bn256: coordinate exceeds modulus")
|
||||
}
|
||||
e.p.y.SetBytes(m[1*numBytes : 2*numBytes])
|
||||
if e.p.y.Cmp(P) >= 0 {
|
||||
return nil, errors.New("bn256: coordinate exceeds modulus")
|
||||
}
|
||||
// Ensure the point is on the curve
|
||||
if e.p.x.Sign() == 0 && e.p.y.Sign() == 0 {
|
||||
// This is the point at infinity.
|
||||
e.p.y.SetInt64(1)
|
||||
e.p.z.SetInt64(0)
|
||||
e.p.t.SetInt64(0)
|
||||
} else {
|
||||
e.p.z.SetInt64(1)
|
||||
e.p.t.SetInt64(1)
|
||||
|
||||
if !e.p.IsOnCurve() {
|
||||
return nil, errors.New("bn256: malformed point")
|
||||
}
|
||||
}
|
||||
return m[2*numBytes:], nil
|
||||
}
|
||||
|
||||
// G2 is an abstract cyclic group. The zero value is suitable for use as the
|
||||
// output of an operation, but cannot be used as an input.
|
||||
type G2 struct {
|
||||
p *twistPoint
|
||||
}
|
||||
|
||||
// RandomG1 returns x and g₂ˣ where x is a random, non-zero number read from r.
|
||||
func RandomG2(r io.Reader) (*big.Int, *G2, error) {
|
||||
var k *big.Int
|
||||
var err error
|
||||
|
||||
for {
|
||||
k, err = rand.Int(r, Order)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if k.Sign() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return k, new(G2).ScalarBaseMult(k), nil
|
||||
}
|
||||
|
||||
func (e *G2) String() string {
|
||||
return "bn256.G2" + e.p.String()
|
||||
}
|
||||
|
||||
// CurvePoints returns the curve points of p which includes the real
|
||||
// and imaginary parts of the curve point.
|
||||
func (e *G2) CurvePoints() (*gfP2, *gfP2, *gfP2, *gfP2) {
|
||||
return e.p.x, e.p.y, e.p.z, e.p.t
|
||||
}
|
||||
|
||||
// ScalarBaseMult sets e to g*k where g is the generator of the group and
|
||||
// then returns out.
|
||||
func (e *G2) ScalarBaseMult(k *big.Int) *G2 {
|
||||
if e.p == nil {
|
||||
e.p = newTwistPoint(nil)
|
||||
}
|
||||
e.p.Mul(twistGen, k, new(bnPool))
|
||||
return e
|
||||
}
|
||||
|
||||
// ScalarMult sets e to a*k and then returns e.
|
||||
func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 {
|
||||
if e.p == nil {
|
||||
e.p = newTwistPoint(nil)
|
||||
}
|
||||
e.p.Mul(a.p, k, new(bnPool))
|
||||
return e
|
||||
}
|
||||
|
||||
// Add sets e to a+b and then returns e.
|
||||
// BUG(agl): this function is not complete: a==b fails.
|
||||
func (e *G2) Add(a, b *G2) *G2 {
|
||||
if e.p == nil {
|
||||
e.p = newTwistPoint(nil)
|
||||
}
|
||||
e.p.Add(a.p, b.p, new(bnPool))
|
||||
return e
|
||||
}
|
||||
|
||||
// Marshal converts n into a byte slice.
|
||||
func (n *G2) Marshal() []byte {
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8
|
||||
|
||||
if n.p.IsInfinity() {
|
||||
return make([]byte, numBytes*4)
|
||||
}
|
||||
|
||||
n.p.MakeAffine(nil)
|
||||
|
||||
xxBytes := new(big.Int).Mod(n.p.x.x, P).Bytes()
|
||||
xyBytes := new(big.Int).Mod(n.p.x.y, P).Bytes()
|
||||
yxBytes := new(big.Int).Mod(n.p.y.x, P).Bytes()
|
||||
yyBytes := new(big.Int).Mod(n.p.y.y, P).Bytes()
|
||||
|
||||
ret := make([]byte, numBytes*4)
|
||||
copy(ret[1*numBytes-len(xxBytes):], xxBytes)
|
||||
copy(ret[2*numBytes-len(xyBytes):], xyBytes)
|
||||
copy(ret[3*numBytes-len(yxBytes):], yxBytes)
|
||||
copy(ret[4*numBytes-len(yyBytes):], yyBytes)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Unmarshal sets e to the result of converting the output of Marshal back into
|
||||
// a group element and then returns e.
|
||||
func (e *G2) Unmarshal(m []byte) ([]byte, error) {
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8
|
||||
if len(m) != 4*numBytes {
|
||||
return nil, errors.New("bn256: not enough data")
|
||||
}
|
||||
// Unmarshal the points and check their caps
|
||||
if e.p == nil {
|
||||
e.p = newTwistPoint(nil)
|
||||
}
|
||||
e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes])
|
||||
if e.p.x.x.Cmp(P) >= 0 {
|
||||
return nil, errors.New("bn256: coordinate exceeds modulus")
|
||||
}
|
||||
e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes])
|
||||
if e.p.x.y.Cmp(P) >= 0 {
|
||||
return nil, errors.New("bn256: coordinate exceeds modulus")
|
||||
}
|
||||
e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes])
|
||||
if e.p.y.x.Cmp(P) >= 0 {
|
||||
return nil, errors.New("bn256: coordinate exceeds modulus")
|
||||
}
|
||||
e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes])
|
||||
if e.p.y.y.Cmp(P) >= 0 {
|
||||
return nil, errors.New("bn256: coordinate exceeds modulus")
|
||||
}
|
||||
// Ensure the point is on the curve
|
||||
if e.p.x.x.Sign() == 0 &&
|
||||
e.p.x.y.Sign() == 0 &&
|
||||
e.p.y.x.Sign() == 0 &&
|
||||
e.p.y.y.Sign() == 0 {
|
||||
// This is the point at infinity.
|
||||
e.p.y.SetOne()
|
||||
e.p.z.SetZero()
|
||||
e.p.t.SetZero()
|
||||
} else {
|
||||
e.p.z.SetOne()
|
||||
e.p.t.SetOne()
|
||||
|
||||
if !e.p.IsOnCurve() {
|
||||
return nil, errors.New("bn256: malformed point")
|
||||
}
|
||||
}
|
||||
return m[4*numBytes:], nil
|
||||
}
|
||||
|
||||
// GT is an abstract cyclic group. The zero value is suitable for use as the
|
||||
// output of an operation, but cannot be used as an input.
|
||||
type GT struct {
|
||||
p *gfP12
|
||||
}
|
||||
|
||||
func (g *GT) String() string {
|
||||
return "bn256.GT" + g.p.String()
|
||||
}
|
||||
|
||||
// ScalarMult sets e to a*k and then returns e.
|
||||
func (e *GT) ScalarMult(a *GT, k *big.Int) *GT {
|
||||
if e.p == nil {
|
||||
e.p = newGFp12(nil)
|
||||
}
|
||||
e.p.Exp(a.p, k, new(bnPool))
|
||||
return e
|
||||
}
|
||||
|
||||
// Add sets e to a+b and then returns e.
|
||||
func (e *GT) Add(a, b *GT) *GT {
|
||||
if e.p == nil {
|
||||
e.p = newGFp12(nil)
|
||||
}
|
||||
e.p.Mul(a.p, b.p, new(bnPool))
|
||||
return e
|
||||
}
|
||||
|
||||
// Neg sets e to -a and then returns e.
|
||||
func (e *GT) Neg(a *GT) *GT {
|
||||
if e.p == nil {
|
||||
e.p = newGFp12(nil)
|
||||
}
|
||||
e.p.Invert(a.p, new(bnPool))
|
||||
return e
|
||||
}
|
||||
|
||||
// Marshal converts n into a byte slice.
|
||||
func (n *GT) Marshal() []byte {
|
||||
n.p.Minimal()
|
||||
|
||||
xxxBytes := n.p.x.x.x.Bytes()
|
||||
xxyBytes := n.p.x.x.y.Bytes()
|
||||
xyxBytes := n.p.x.y.x.Bytes()
|
||||
xyyBytes := n.p.x.y.y.Bytes()
|
||||
xzxBytes := n.p.x.z.x.Bytes()
|
||||
xzyBytes := n.p.x.z.y.Bytes()
|
||||
yxxBytes := n.p.y.x.x.Bytes()
|
||||
yxyBytes := n.p.y.x.y.Bytes()
|
||||
yyxBytes := n.p.y.y.x.Bytes()
|
||||
yyyBytes := n.p.y.y.y.Bytes()
|
||||
yzxBytes := n.p.y.z.x.Bytes()
|
||||
yzyBytes := n.p.y.z.y.Bytes()
|
||||
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8
|
||||
|
||||
ret := make([]byte, numBytes*12)
|
||||
copy(ret[1*numBytes-len(xxxBytes):], xxxBytes)
|
||||
copy(ret[2*numBytes-len(xxyBytes):], xxyBytes)
|
||||
copy(ret[3*numBytes-len(xyxBytes):], xyxBytes)
|
||||
copy(ret[4*numBytes-len(xyyBytes):], xyyBytes)
|
||||
copy(ret[5*numBytes-len(xzxBytes):], xzxBytes)
|
||||
copy(ret[6*numBytes-len(xzyBytes):], xzyBytes)
|
||||
copy(ret[7*numBytes-len(yxxBytes):], yxxBytes)
|
||||
copy(ret[8*numBytes-len(yxyBytes):], yxyBytes)
|
||||
copy(ret[9*numBytes-len(yyxBytes):], yyxBytes)
|
||||
copy(ret[10*numBytes-len(yyyBytes):], yyyBytes)
|
||||
copy(ret[11*numBytes-len(yzxBytes):], yzxBytes)
|
||||
copy(ret[12*numBytes-len(yzyBytes):], yzyBytes)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Unmarshal sets e to the result of converting the output of Marshal back into
|
||||
// a group element and then returns e.
|
||||
func (e *GT) Unmarshal(m []byte) (*GT, bool) {
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8
|
||||
|
||||
if len(m) != 12*numBytes {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if e.p == nil {
|
||||
e.p = newGFp12(nil)
|
||||
}
|
||||
|
||||
e.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes])
|
||||
e.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes])
|
||||
e.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes])
|
||||
e.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes])
|
||||
e.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes])
|
||||
e.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes])
|
||||
e.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes])
|
||||
e.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes])
|
||||
e.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes])
|
||||
e.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes])
|
||||
e.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes])
|
||||
e.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes])
|
||||
|
||||
return e, true
|
||||
}
|
||||
|
||||
// Pair calculates an Optimal Ate pairing.
|
||||
func Pair(g1 *G1, g2 *G2) *GT {
|
||||
return >{optimalAte(g2.p, g1.p, new(bnPool))}
|
||||
}
|
||||
|
||||
// PairingCheck calculates the Optimal Ate pairing for a set of points.
|
||||
func PairingCheck(a []*G1, b []*G2) bool {
|
||||
pool := new(bnPool)
|
||||
|
||||
acc := newGFp12(pool)
|
||||
acc.SetOne()
|
||||
|
||||
for i := 0; i < len(a); i++ {
|
||||
if a[i].p.IsInfinity() || b[i].p.IsInfinity() {
|
||||
continue
|
||||
}
|
||||
acc.Mul(acc, miller(b[i].p, a[i].p, pool), pool)
|
||||
}
|
||||
ret := finalExponentiation(acc, pool)
|
||||
acc.Put(pool)
|
||||
|
||||
return ret.IsOne()
|
||||
}
|
||||
|
||||
// bnPool implements a tiny cache of *big.Int objects that's used to reduce the
|
||||
// number of allocations made during processing.
|
||||
type bnPool struct {
|
||||
bns []*big.Int
|
||||
count int
|
||||
}
|
||||
|
||||
func (pool *bnPool) Get() *big.Int {
|
||||
if pool == nil {
|
||||
return new(big.Int)
|
||||
}
|
||||
|
||||
pool.count++
|
||||
l := len(pool.bns)
|
||||
if l == 0 {
|
||||
return new(big.Int)
|
||||
}
|
||||
|
||||
bn := pool.bns[l-1]
|
||||
pool.bns = pool.bns[:l-1]
|
||||
return bn
|
||||
}
|
||||
|
||||
func (pool *bnPool) Put(bn *big.Int) {
|
||||
if pool == nil {
|
||||
return
|
||||
}
|
||||
pool.bns = append(pool.bns, bn)
|
||||
pool.count--
|
||||
}
|
||||
|
||||
func (pool *bnPool) Count() int {
|
||||
return pool.count
|
||||
}
|
||||
47
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/constants.go
generated
vendored
Normal file
47
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/constants.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func bigFromBase10(s string) *big.Int {
|
||||
n, _ := new(big.Int).SetString(s, 10)
|
||||
return n
|
||||
}
|
||||
|
||||
// u is the BN parameter that determines the prime.
|
||||
var u = bigFromBase10("4965661367192848881")
|
||||
|
||||
// P is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1.
|
||||
var P = bigFromBase10("21888242871839275222246405745257275088696311157297823662689037894645226208583")
|
||||
|
||||
// Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1.
|
||||
// Needs to be highly 2-adic for efficient SNARK key and proof generation.
|
||||
// Order - 1 = 2^28 * 3^2 * 13 * 29 * 983 * 11003 * 237073 * 405928799 * 1670836401704629 * 13818364434197438864469338081.
|
||||
// Refer to https://eprint.iacr.org/2013/879.pdf and https://eprint.iacr.org/2013/507.pdf for more information on these parameters.
|
||||
var Order = bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617")
|
||||
|
||||
// xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+9.
|
||||
var xiToPMinus1Over6 = &gfP2{bigFromBase10("16469823323077808223889137241176536799009286646108169935659301613961712198316"), bigFromBase10("8376118865763821496583973867626364092589906065868298776909617916018768340080")}
|
||||
|
||||
// xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+9.
|
||||
var xiToPMinus1Over3 = &gfP2{bigFromBase10("10307601595873709700152284273816112264069230130616436755625194854815875713954"), bigFromBase10("21575463638280843010398324269430826099269044274347216827212613867836435027261")}
|
||||
|
||||
// xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+9.
|
||||
var xiToPMinus1Over2 = &gfP2{bigFromBase10("3505843767911556378687030309984248845540243509899259641013678093033130930403"), bigFromBase10("2821565182194536844548159561693502659359617185244120367078079554186484126554")}
|
||||
|
||||
// xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+9.
|
||||
var xiToPSquaredMinus1Over3 = bigFromBase10("21888242871839275220042445260109153167277707414472061641714758635765020556616")
|
||||
|
||||
// xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+9 (a cubic root of unity, mod p).
|
||||
var xiTo2PSquaredMinus2Over3 = bigFromBase10("2203960485148121921418603742825762020974279258880205651966")
|
||||
|
||||
// xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+9 (a cubic root of -1, mod p).
|
||||
var xiToPSquaredMinus1Over6 = bigFromBase10("21888242871839275220042445260109153167277707414472061641714758635765020556617")
|
||||
|
||||
// xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+9.
|
||||
var xiTo2PMinus2Over3 = &gfP2{bigFromBase10("19937756971775647987995932169929341994314640652964949448313374472400716661030"), bigFromBase10("2581911344467009335267311115468803099551665605076196740867805258568234346338")}
|
||||
286
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/curve.go
generated
vendored
Normal file
286
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/curve.go
generated
vendored
Normal file
@@ -0,0 +1,286 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// curvePoint implements the elliptic curve y²=x³+3. Points are kept in
|
||||
// Jacobian form and t=z² when valid. G₁ is the set of points of this curve on
|
||||
// GF(p).
|
||||
type curvePoint struct {
|
||||
x, y, z, t *big.Int
|
||||
}
|
||||
|
||||
var curveB = new(big.Int).SetInt64(3)
|
||||
|
||||
// curveGen is the generator of G₁.
|
||||
var curveGen = &curvePoint{
|
||||
new(big.Int).SetInt64(1),
|
||||
new(big.Int).SetInt64(2),
|
||||
new(big.Int).SetInt64(1),
|
||||
new(big.Int).SetInt64(1),
|
||||
}
|
||||
|
||||
func newCurvePoint(pool *bnPool) *curvePoint {
|
||||
return &curvePoint{
|
||||
pool.Get(),
|
||||
pool.Get(),
|
||||
pool.Get(),
|
||||
pool.Get(),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *curvePoint) String() string {
|
||||
c.MakeAffine(new(bnPool))
|
||||
return "(" + c.x.String() + ", " + c.y.String() + ")"
|
||||
}
|
||||
|
||||
func (c *curvePoint) Put(pool *bnPool) {
|
||||
pool.Put(c.x)
|
||||
pool.Put(c.y)
|
||||
pool.Put(c.z)
|
||||
pool.Put(c.t)
|
||||
}
|
||||
|
||||
func (c *curvePoint) Set(a *curvePoint) {
|
||||
c.x.Set(a.x)
|
||||
c.y.Set(a.y)
|
||||
c.z.Set(a.z)
|
||||
c.t.Set(a.t)
|
||||
}
|
||||
|
||||
// IsOnCurve returns true iff c is on the curve where c must be in affine form.
|
||||
func (c *curvePoint) IsOnCurve() bool {
|
||||
yy := new(big.Int).Mul(c.y, c.y)
|
||||
xxx := new(big.Int).Mul(c.x, c.x)
|
||||
xxx.Mul(xxx, c.x)
|
||||
yy.Sub(yy, xxx)
|
||||
yy.Sub(yy, curveB)
|
||||
if yy.Sign() < 0 || yy.Cmp(P) >= 0 {
|
||||
yy.Mod(yy, P)
|
||||
}
|
||||
return yy.Sign() == 0
|
||||
}
|
||||
|
||||
func (c *curvePoint) SetInfinity() {
|
||||
c.z.SetInt64(0)
|
||||
}
|
||||
|
||||
func (c *curvePoint) IsInfinity() bool {
|
||||
return c.z.Sign() == 0
|
||||
}
|
||||
|
||||
func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) {
|
||||
if a.IsInfinity() {
|
||||
c.Set(b)
|
||||
return
|
||||
}
|
||||
if b.IsInfinity() {
|
||||
c.Set(a)
|
||||
return
|
||||
}
|
||||
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
|
||||
|
||||
// Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2]
|
||||
// by [u1:s1:z1·z2] and [u2:s2:z1·z2]
|
||||
// where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³
|
||||
z1z1 := pool.Get().Mul(a.z, a.z)
|
||||
z1z1.Mod(z1z1, P)
|
||||
z2z2 := pool.Get().Mul(b.z, b.z)
|
||||
z2z2.Mod(z2z2, P)
|
||||
u1 := pool.Get().Mul(a.x, z2z2)
|
||||
u1.Mod(u1, P)
|
||||
u2 := pool.Get().Mul(b.x, z1z1)
|
||||
u2.Mod(u2, P)
|
||||
|
||||
t := pool.Get().Mul(b.z, z2z2)
|
||||
t.Mod(t, P)
|
||||
s1 := pool.Get().Mul(a.y, t)
|
||||
s1.Mod(s1, P)
|
||||
|
||||
t.Mul(a.z, z1z1)
|
||||
t.Mod(t, P)
|
||||
s2 := pool.Get().Mul(b.y, t)
|
||||
s2.Mod(s2, P)
|
||||
|
||||
// Compute x = (2h)²(s²-u1-u2)
|
||||
// where s = (s2-s1)/(u2-u1) is the slope of the line through
|
||||
// (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below.
|
||||
// This is also:
|
||||
// 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1)
|
||||
// = r² - j - 2v
|
||||
// with the notations below.
|
||||
h := pool.Get().Sub(u2, u1)
|
||||
xEqual := h.Sign() == 0
|
||||
|
||||
t.Add(h, h)
|
||||
// i = 4h²
|
||||
i := pool.Get().Mul(t, t)
|
||||
i.Mod(i, P)
|
||||
// j = 4h³
|
||||
j := pool.Get().Mul(h, i)
|
||||
j.Mod(j, P)
|
||||
|
||||
t.Sub(s2, s1)
|
||||
yEqual := t.Sign() == 0
|
||||
if xEqual && yEqual {
|
||||
c.Double(a, pool)
|
||||
return
|
||||
}
|
||||
r := pool.Get().Add(t, t)
|
||||
|
||||
v := pool.Get().Mul(u1, i)
|
||||
v.Mod(v, P)
|
||||
|
||||
// t4 = 4(s2-s1)²
|
||||
t4 := pool.Get().Mul(r, r)
|
||||
t4.Mod(t4, P)
|
||||
t.Add(v, v)
|
||||
t6 := pool.Get().Sub(t4, j)
|
||||
c.x.Sub(t6, t)
|
||||
|
||||
// Set y = -(2h)³(s1 + s*(x/4h²-u1))
|
||||
// This is also
|
||||
// y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j
|
||||
t.Sub(v, c.x) // t7
|
||||
t4.Mul(s1, j) // t8
|
||||
t4.Mod(t4, P)
|
||||
t6.Add(t4, t4) // t9
|
||||
t4.Mul(r, t) // t10
|
||||
t4.Mod(t4, P)
|
||||
c.y.Sub(t4, t6)
|
||||
|
||||
// Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2
|
||||
t.Add(a.z, b.z) // t11
|
||||
t4.Mul(t, t) // t12
|
||||
t4.Mod(t4, P)
|
||||
t.Sub(t4, z1z1) // t13
|
||||
t4.Sub(t, z2z2) // t14
|
||||
c.z.Mul(t4, h)
|
||||
c.z.Mod(c.z, P)
|
||||
|
||||
pool.Put(z1z1)
|
||||
pool.Put(z2z2)
|
||||
pool.Put(u1)
|
||||
pool.Put(u2)
|
||||
pool.Put(t)
|
||||
pool.Put(s1)
|
||||
pool.Put(s2)
|
||||
pool.Put(h)
|
||||
pool.Put(i)
|
||||
pool.Put(j)
|
||||
pool.Put(r)
|
||||
pool.Put(v)
|
||||
pool.Put(t4)
|
||||
pool.Put(t6)
|
||||
}
|
||||
|
||||
func (c *curvePoint) Double(a *curvePoint, pool *bnPool) {
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
|
||||
A := pool.Get().Mul(a.x, a.x)
|
||||
A.Mod(A, P)
|
||||
B := pool.Get().Mul(a.y, a.y)
|
||||
B.Mod(B, P)
|
||||
C_ := pool.Get().Mul(B, B)
|
||||
C_.Mod(C_, P)
|
||||
|
||||
t := pool.Get().Add(a.x, B)
|
||||
t2 := pool.Get().Mul(t, t)
|
||||
t2.Mod(t2, P)
|
||||
t.Sub(t2, A)
|
||||
t2.Sub(t, C_)
|
||||
d := pool.Get().Add(t2, t2)
|
||||
t.Add(A, A)
|
||||
e := pool.Get().Add(t, A)
|
||||
f := pool.Get().Mul(e, e)
|
||||
f.Mod(f, P)
|
||||
|
||||
t.Add(d, d)
|
||||
c.x.Sub(f, t)
|
||||
|
||||
t.Add(C_, C_)
|
||||
t2.Add(t, t)
|
||||
t.Add(t2, t2)
|
||||
c.y.Sub(d, c.x)
|
||||
t2.Mul(e, c.y)
|
||||
t2.Mod(t2, P)
|
||||
c.y.Sub(t2, t)
|
||||
|
||||
t.Mul(a.y, a.z)
|
||||
t.Mod(t, P)
|
||||
c.z.Add(t, t)
|
||||
|
||||
pool.Put(A)
|
||||
pool.Put(B)
|
||||
pool.Put(C_)
|
||||
pool.Put(t)
|
||||
pool.Put(t2)
|
||||
pool.Put(d)
|
||||
pool.Put(e)
|
||||
pool.Put(f)
|
||||
}
|
||||
|
||||
func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint {
|
||||
sum := newCurvePoint(pool)
|
||||
sum.SetInfinity()
|
||||
t := newCurvePoint(pool)
|
||||
|
||||
for i := scalar.BitLen(); i >= 0; i-- {
|
||||
t.Double(sum, pool)
|
||||
if scalar.Bit(i) != 0 {
|
||||
sum.Add(t, a, pool)
|
||||
} else {
|
||||
sum.Set(t)
|
||||
}
|
||||
}
|
||||
|
||||
c.Set(sum)
|
||||
sum.Put(pool)
|
||||
t.Put(pool)
|
||||
return c
|
||||
}
|
||||
|
||||
// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets
|
||||
// c to 0 : 1 : 0.
|
||||
func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint {
|
||||
if words := c.z.Bits(); len(words) == 1 && words[0] == 1 {
|
||||
return c
|
||||
}
|
||||
if c.IsInfinity() {
|
||||
c.x.SetInt64(0)
|
||||
c.y.SetInt64(1)
|
||||
c.z.SetInt64(0)
|
||||
c.t.SetInt64(0)
|
||||
return c
|
||||
}
|
||||
zInv := pool.Get().ModInverse(c.z, P)
|
||||
t := pool.Get().Mul(c.y, zInv)
|
||||
t.Mod(t, P)
|
||||
zInv2 := pool.Get().Mul(zInv, zInv)
|
||||
zInv2.Mod(zInv2, P)
|
||||
c.y.Mul(t, zInv2)
|
||||
c.y.Mod(c.y, P)
|
||||
t.Mul(c.x, zInv2)
|
||||
t.Mod(t, P)
|
||||
c.x.Set(t)
|
||||
c.z.SetInt64(1)
|
||||
c.t.SetInt64(1)
|
||||
|
||||
pool.Put(zInv)
|
||||
pool.Put(t)
|
||||
pool.Put(zInv2)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *curvePoint) Negative(a *curvePoint) {
|
||||
c.x.Set(a.x)
|
||||
c.y.Neg(a.y)
|
||||
c.z.Set(a.z)
|
||||
c.t.SetInt64(0)
|
||||
}
|
||||
200
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp12.go
generated
vendored
Normal file
200
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp12.go
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256
|
||||
|
||||
// For details of the algorithms used, see "Multiplication and Squaring on
|
||||
// Pairing-Friendly Fields, Devegili et al.
|
||||
// http://eprint.iacr.org/2006/471.pdf.
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// gfP12 implements the field of size p¹² as a quadratic extension of gfP6
|
||||
// where ω²=τ.
|
||||
type gfP12 struct {
|
||||
x, y *gfP6 // value is xω + y
|
||||
}
|
||||
|
||||
func newGFp12(pool *bnPool) *gfP12 {
|
||||
return &gfP12{newGFp6(pool), newGFp6(pool)}
|
||||
}
|
||||
|
||||
func (e *gfP12) String() string {
|
||||
return "(" + e.x.String() + "," + e.y.String() + ")"
|
||||
}
|
||||
|
||||
func (e *gfP12) Put(pool *bnPool) {
|
||||
e.x.Put(pool)
|
||||
e.y.Put(pool)
|
||||
}
|
||||
|
||||
func (e *gfP12) Set(a *gfP12) *gfP12 {
|
||||
e.x.Set(a.x)
|
||||
e.y.Set(a.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) SetZero() *gfP12 {
|
||||
e.x.SetZero()
|
||||
e.y.SetZero()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) SetOne() *gfP12 {
|
||||
e.x.SetZero()
|
||||
e.y.SetOne()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) Minimal() {
|
||||
e.x.Minimal()
|
||||
e.y.Minimal()
|
||||
}
|
||||
|
||||
func (e *gfP12) IsZero() bool {
|
||||
e.Minimal()
|
||||
return e.x.IsZero() && e.y.IsZero()
|
||||
}
|
||||
|
||||
func (e *gfP12) IsOne() bool {
|
||||
e.Minimal()
|
||||
return e.x.IsZero() && e.y.IsOne()
|
||||
}
|
||||
|
||||
func (e *gfP12) Conjugate(a *gfP12) *gfP12 {
|
||||
e.x.Negative(a.x)
|
||||
e.y.Set(a.y)
|
||||
return a
|
||||
}
|
||||
|
||||
func (e *gfP12) Negative(a *gfP12) *gfP12 {
|
||||
e.x.Negative(a.x)
|
||||
e.y.Negative(a.y)
|
||||
return e
|
||||
}
|
||||
|
||||
// Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p
|
||||
func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 {
|
||||
e.x.Frobenius(a.x, pool)
|
||||
e.y.Frobenius(a.y, pool)
|
||||
e.x.MulScalar(e.x, xiToPMinus1Over6, pool)
|
||||
return e
|
||||
}
|
||||
|
||||
// FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p²
|
||||
func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 {
|
||||
e.x.FrobeniusP2(a.x)
|
||||
e.x.MulGFP(e.x, xiToPSquaredMinus1Over6)
|
||||
e.y.FrobeniusP2(a.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) Add(a, b *gfP12) *gfP12 {
|
||||
e.x.Add(a.x, b.x)
|
||||
e.y.Add(a.y, b.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) Sub(a, b *gfP12) *gfP12 {
|
||||
e.x.Sub(a.x, b.x)
|
||||
e.y.Sub(a.y, b.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 {
|
||||
tx := newGFp6(pool)
|
||||
tx.Mul(a.x, b.y, pool)
|
||||
t := newGFp6(pool)
|
||||
t.Mul(b.x, a.y, pool)
|
||||
tx.Add(tx, t)
|
||||
|
||||
ty := newGFp6(pool)
|
||||
ty.Mul(a.y, b.y, pool)
|
||||
t.Mul(a.x, b.x, pool)
|
||||
t.MulTau(t, pool)
|
||||
e.y.Add(ty, t)
|
||||
e.x.Set(tx)
|
||||
|
||||
tx.Put(pool)
|
||||
ty.Put(pool)
|
||||
t.Put(pool)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 {
|
||||
e.x.Mul(e.x, b, pool)
|
||||
e.y.Mul(e.y, b, pool)
|
||||
return e
|
||||
}
|
||||
|
||||
func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 {
|
||||
sum := newGFp12(pool)
|
||||
sum.SetOne()
|
||||
t := newGFp12(pool)
|
||||
|
||||
for i := power.BitLen() - 1; i >= 0; i-- {
|
||||
t.Square(sum, pool)
|
||||
if power.Bit(i) != 0 {
|
||||
sum.Mul(t, a, pool)
|
||||
} else {
|
||||
sum.Set(t)
|
||||
}
|
||||
}
|
||||
|
||||
c.Set(sum)
|
||||
|
||||
sum.Put(pool)
|
||||
t.Put(pool)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 {
|
||||
// Complex squaring algorithm
|
||||
v0 := newGFp6(pool)
|
||||
v0.Mul(a.x, a.y, pool)
|
||||
|
||||
t := newGFp6(pool)
|
||||
t.MulTau(a.x, pool)
|
||||
t.Add(a.y, t)
|
||||
ty := newGFp6(pool)
|
||||
ty.Add(a.x, a.y)
|
||||
ty.Mul(ty, t, pool)
|
||||
ty.Sub(ty, v0)
|
||||
t.MulTau(v0, pool)
|
||||
ty.Sub(ty, t)
|
||||
|
||||
e.y.Set(ty)
|
||||
e.x.Double(v0)
|
||||
|
||||
v0.Put(pool)
|
||||
t.Put(pool)
|
||||
ty.Put(pool)
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 {
|
||||
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
||||
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
||||
t1 := newGFp6(pool)
|
||||
t2 := newGFp6(pool)
|
||||
|
||||
t1.Square(a.x, pool)
|
||||
t2.Square(a.y, pool)
|
||||
t1.MulTau(t1, pool)
|
||||
t1.Sub(t2, t1)
|
||||
t2.Invert(t1, pool)
|
||||
|
||||
e.x.Negative(a.x)
|
||||
e.y.Set(a.y)
|
||||
e.MulScalar(e, t2, pool)
|
||||
|
||||
t1.Put(pool)
|
||||
t2.Put(pool)
|
||||
|
||||
return e
|
||||
}
|
||||
227
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp2.go
generated
vendored
Normal file
227
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp2.go
generated
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256
|
||||
|
||||
// For details of the algorithms used, see "Multiplication and Squaring on
|
||||
// Pairing-Friendly Fields, Devegili et al.
|
||||
// http://eprint.iacr.org/2006/471.pdf.
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// gfP2 implements a field of size p² as a quadratic extension of the base
|
||||
// field where i²=-1.
|
||||
type gfP2 struct {
|
||||
x, y *big.Int // value is xi+y.
|
||||
}
|
||||
|
||||
func newGFp2(pool *bnPool) *gfP2 {
|
||||
return &gfP2{pool.Get(), pool.Get()}
|
||||
}
|
||||
|
||||
func (e *gfP2) String() string {
|
||||
x := new(big.Int).Mod(e.x, P)
|
||||
y := new(big.Int).Mod(e.y, P)
|
||||
return "(" + x.String() + "," + y.String() + ")"
|
||||
}
|
||||
|
||||
func (e *gfP2) Put(pool *bnPool) {
|
||||
pool.Put(e.x)
|
||||
pool.Put(e.y)
|
||||
}
|
||||
|
||||
func (e *gfP2) Set(a *gfP2) *gfP2 {
|
||||
e.x.Set(a.x)
|
||||
e.y.Set(a.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) SetZero() *gfP2 {
|
||||
e.x.SetInt64(0)
|
||||
e.y.SetInt64(0)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) SetOne() *gfP2 {
|
||||
e.x.SetInt64(0)
|
||||
e.y.SetInt64(1)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Minimal() {
|
||||
if e.x.Sign() < 0 || e.x.Cmp(P) >= 0 {
|
||||
e.x.Mod(e.x, P)
|
||||
}
|
||||
if e.y.Sign() < 0 || e.y.Cmp(P) >= 0 {
|
||||
e.y.Mod(e.y, P)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *gfP2) IsZero() bool {
|
||||
return e.x.Sign() == 0 && e.y.Sign() == 0
|
||||
}
|
||||
|
||||
func (e *gfP2) IsOne() bool {
|
||||
if e.x.Sign() != 0 {
|
||||
return false
|
||||
}
|
||||
words := e.y.Bits()
|
||||
return len(words) == 1 && words[0] == 1
|
||||
}
|
||||
|
||||
func (e *gfP2) Conjugate(a *gfP2) *gfP2 {
|
||||
e.y.Set(a.y)
|
||||
e.x.Neg(a.x)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Negative(a *gfP2) *gfP2 {
|
||||
e.x.Neg(a.x)
|
||||
e.y.Neg(a.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Add(a, b *gfP2) *gfP2 {
|
||||
e.x.Add(a.x, b.x)
|
||||
e.y.Add(a.y, b.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Sub(a, b *gfP2) *gfP2 {
|
||||
e.x.Sub(a.x, b.x)
|
||||
e.y.Sub(a.y, b.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Double(a *gfP2) *gfP2 {
|
||||
e.x.Lsh(a.x, 1)
|
||||
e.y.Lsh(a.y, 1)
|
||||
return e
|
||||
}
|
||||
|
||||
func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 {
|
||||
sum := newGFp2(pool)
|
||||
sum.SetOne()
|
||||
t := newGFp2(pool)
|
||||
|
||||
for i := power.BitLen() - 1; i >= 0; i-- {
|
||||
t.Square(sum, pool)
|
||||
if power.Bit(i) != 0 {
|
||||
sum.Mul(t, a, pool)
|
||||
} else {
|
||||
sum.Set(t)
|
||||
}
|
||||
}
|
||||
|
||||
c.Set(sum)
|
||||
|
||||
sum.Put(pool)
|
||||
t.Put(pool)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// See "Multiplication and Squaring in Pairing-Friendly Fields",
|
||||
// http://eprint.iacr.org/2006/471.pdf
|
||||
func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 {
|
||||
tx := pool.Get().Mul(a.x, b.y)
|
||||
t := pool.Get().Mul(b.x, a.y)
|
||||
tx.Add(tx, t)
|
||||
tx.Mod(tx, P)
|
||||
|
||||
ty := pool.Get().Mul(a.y, b.y)
|
||||
t.Mul(a.x, b.x)
|
||||
ty.Sub(ty, t)
|
||||
e.y.Mod(ty, P)
|
||||
e.x.Set(tx)
|
||||
|
||||
pool.Put(tx)
|
||||
pool.Put(ty)
|
||||
pool.Put(t)
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 {
|
||||
e.x.Mul(a.x, b)
|
||||
e.y.Mul(a.y, b)
|
||||
return e
|
||||
}
|
||||
|
||||
// MulXi sets e=ξa where ξ=i+9 and then returns e.
|
||||
func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 {
|
||||
// (xi+y)(i+3) = (9x+y)i+(9y-x)
|
||||
tx := pool.Get().Lsh(a.x, 3)
|
||||
tx.Add(tx, a.x)
|
||||
tx.Add(tx, a.y)
|
||||
|
||||
ty := pool.Get().Lsh(a.y, 3)
|
||||
ty.Add(ty, a.y)
|
||||
ty.Sub(ty, a.x)
|
||||
|
||||
e.x.Set(tx)
|
||||
e.y.Set(ty)
|
||||
|
||||
pool.Put(tx)
|
||||
pool.Put(ty)
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 {
|
||||
// Complex squaring algorithm:
|
||||
// (xi+b)² = (x+y)(y-x) + 2*i*x*y
|
||||
t1 := pool.Get().Sub(a.y, a.x)
|
||||
t2 := pool.Get().Add(a.x, a.y)
|
||||
ty := pool.Get().Mul(t1, t2)
|
||||
ty.Mod(ty, P)
|
||||
|
||||
t1.Mul(a.x, a.y)
|
||||
t1.Lsh(t1, 1)
|
||||
|
||||
e.x.Mod(t1, P)
|
||||
e.y.Set(ty)
|
||||
|
||||
pool.Put(t1)
|
||||
pool.Put(t2)
|
||||
pool.Put(ty)
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 {
|
||||
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
||||
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
||||
t := pool.Get()
|
||||
t.Mul(a.y, a.y)
|
||||
t2 := pool.Get()
|
||||
t2.Mul(a.x, a.x)
|
||||
t.Add(t, t2)
|
||||
|
||||
inv := pool.Get()
|
||||
inv.ModInverse(t, P)
|
||||
|
||||
e.x.Neg(a.x)
|
||||
e.x.Mul(e.x, inv)
|
||||
e.x.Mod(e.x, P)
|
||||
|
||||
e.y.Mul(a.y, inv)
|
||||
e.y.Mod(e.y, P)
|
||||
|
||||
pool.Put(t)
|
||||
pool.Put(t2)
|
||||
pool.Put(inv)
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Real() *big.Int {
|
||||
return e.x
|
||||
}
|
||||
|
||||
func (e *gfP2) Imag() *big.Int {
|
||||
return e.y
|
||||
}
|
||||
296
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp6.go
generated
vendored
Normal file
296
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/gfp6.go
generated
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256
|
||||
|
||||
// For details of the algorithms used, see "Multiplication and Squaring on
|
||||
// Pairing-Friendly Fields, Devegili et al.
|
||||
// http://eprint.iacr.org/2006/471.pdf.
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ
|
||||
// and ξ=i+9.
|
||||
type gfP6 struct {
|
||||
x, y, z *gfP2 // value is xτ² + yτ + z
|
||||
}
|
||||
|
||||
func newGFp6(pool *bnPool) *gfP6 {
|
||||
return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)}
|
||||
}
|
||||
|
||||
func (e *gfP6) String() string {
|
||||
return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")"
|
||||
}
|
||||
|
||||
func (e *gfP6) Put(pool *bnPool) {
|
||||
e.x.Put(pool)
|
||||
e.y.Put(pool)
|
||||
e.z.Put(pool)
|
||||
}
|
||||
|
||||
func (e *gfP6) Set(a *gfP6) *gfP6 {
|
||||
e.x.Set(a.x)
|
||||
e.y.Set(a.y)
|
||||
e.z.Set(a.z)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) SetZero() *gfP6 {
|
||||
e.x.SetZero()
|
||||
e.y.SetZero()
|
||||
e.z.SetZero()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) SetOne() *gfP6 {
|
||||
e.x.SetZero()
|
||||
e.y.SetZero()
|
||||
e.z.SetOne()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) Minimal() {
|
||||
e.x.Minimal()
|
||||
e.y.Minimal()
|
||||
e.z.Minimal()
|
||||
}
|
||||
|
||||
func (e *gfP6) IsZero() bool {
|
||||
return e.x.IsZero() && e.y.IsZero() && e.z.IsZero()
|
||||
}
|
||||
|
||||
func (e *gfP6) IsOne() bool {
|
||||
return e.x.IsZero() && e.y.IsZero() && e.z.IsOne()
|
||||
}
|
||||
|
||||
func (e *gfP6) Negative(a *gfP6) *gfP6 {
|
||||
e.x.Negative(a.x)
|
||||
e.y.Negative(a.y)
|
||||
e.z.Negative(a.z)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 {
|
||||
e.x.Conjugate(a.x)
|
||||
e.y.Conjugate(a.y)
|
||||
e.z.Conjugate(a.z)
|
||||
|
||||
e.x.Mul(e.x, xiTo2PMinus2Over3, pool)
|
||||
e.y.Mul(e.y, xiToPMinus1Over3, pool)
|
||||
return e
|
||||
}
|
||||
|
||||
// FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z
|
||||
func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 {
|
||||
// τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3)
|
||||
e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3)
|
||||
// τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3)
|
||||
e.y.MulScalar(a.y, xiToPSquaredMinus1Over3)
|
||||
e.z.Set(a.z)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) Add(a, b *gfP6) *gfP6 {
|
||||
e.x.Add(a.x, b.x)
|
||||
e.y.Add(a.y, b.y)
|
||||
e.z.Add(a.z, b.z)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) Sub(a, b *gfP6) *gfP6 {
|
||||
e.x.Sub(a.x, b.x)
|
||||
e.y.Sub(a.y, b.y)
|
||||
e.z.Sub(a.z, b.z)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) Double(a *gfP6) *gfP6 {
|
||||
e.x.Double(a.x)
|
||||
e.y.Double(a.y)
|
||||
e.z.Double(a.z)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 {
|
||||
// "Multiplication and Squaring on Pairing-Friendly Fields"
|
||||
// Section 4, Karatsuba method.
|
||||
// http://eprint.iacr.org/2006/471.pdf
|
||||
|
||||
v0 := newGFp2(pool)
|
||||
v0.Mul(a.z, b.z, pool)
|
||||
v1 := newGFp2(pool)
|
||||
v1.Mul(a.y, b.y, pool)
|
||||
v2 := newGFp2(pool)
|
||||
v2.Mul(a.x, b.x, pool)
|
||||
|
||||
t0 := newGFp2(pool)
|
||||
t0.Add(a.x, a.y)
|
||||
t1 := newGFp2(pool)
|
||||
t1.Add(b.x, b.y)
|
||||
tz := newGFp2(pool)
|
||||
tz.Mul(t0, t1, pool)
|
||||
|
||||
tz.Sub(tz, v1)
|
||||
tz.Sub(tz, v2)
|
||||
tz.MulXi(tz, pool)
|
||||
tz.Add(tz, v0)
|
||||
|
||||
t0.Add(a.y, a.z)
|
||||
t1.Add(b.y, b.z)
|
||||
ty := newGFp2(pool)
|
||||
ty.Mul(t0, t1, pool)
|
||||
ty.Sub(ty, v0)
|
||||
ty.Sub(ty, v1)
|
||||
t0.MulXi(v2, pool)
|
||||
ty.Add(ty, t0)
|
||||
|
||||
t0.Add(a.x, a.z)
|
||||
t1.Add(b.x, b.z)
|
||||
tx := newGFp2(pool)
|
||||
tx.Mul(t0, t1, pool)
|
||||
tx.Sub(tx, v0)
|
||||
tx.Add(tx, v1)
|
||||
tx.Sub(tx, v2)
|
||||
|
||||
e.x.Set(tx)
|
||||
e.y.Set(ty)
|
||||
e.z.Set(tz)
|
||||
|
||||
t0.Put(pool)
|
||||
t1.Put(pool)
|
||||
tx.Put(pool)
|
||||
ty.Put(pool)
|
||||
tz.Put(pool)
|
||||
v0.Put(pool)
|
||||
v1.Put(pool)
|
||||
v2.Put(pool)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 {
|
||||
e.x.Mul(a.x, b, pool)
|
||||
e.y.Mul(a.y, b, pool)
|
||||
e.z.Mul(a.z, b, pool)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 {
|
||||
e.x.MulScalar(a.x, b)
|
||||
e.y.MulScalar(a.y, b)
|
||||
e.z.MulScalar(a.z, b)
|
||||
return e
|
||||
}
|
||||
|
||||
// MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ
|
||||
func (e *gfP6) MulTau(a *gfP6, pool *bnPool) {
|
||||
tz := newGFp2(pool)
|
||||
tz.MulXi(a.x, pool)
|
||||
ty := newGFp2(pool)
|
||||
ty.Set(a.y)
|
||||
e.y.Set(a.z)
|
||||
e.x.Set(ty)
|
||||
e.z.Set(tz)
|
||||
tz.Put(pool)
|
||||
ty.Put(pool)
|
||||
}
|
||||
|
||||
func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 {
|
||||
v0 := newGFp2(pool).Square(a.z, pool)
|
||||
v1 := newGFp2(pool).Square(a.y, pool)
|
||||
v2 := newGFp2(pool).Square(a.x, pool)
|
||||
|
||||
c0 := newGFp2(pool).Add(a.x, a.y)
|
||||
c0.Square(c0, pool)
|
||||
c0.Sub(c0, v1)
|
||||
c0.Sub(c0, v2)
|
||||
c0.MulXi(c0, pool)
|
||||
c0.Add(c0, v0)
|
||||
|
||||
c1 := newGFp2(pool).Add(a.y, a.z)
|
||||
c1.Square(c1, pool)
|
||||
c1.Sub(c1, v0)
|
||||
c1.Sub(c1, v1)
|
||||
xiV2 := newGFp2(pool).MulXi(v2, pool)
|
||||
c1.Add(c1, xiV2)
|
||||
|
||||
c2 := newGFp2(pool).Add(a.x, a.z)
|
||||
c2.Square(c2, pool)
|
||||
c2.Sub(c2, v0)
|
||||
c2.Add(c2, v1)
|
||||
c2.Sub(c2, v2)
|
||||
|
||||
e.x.Set(c2)
|
||||
e.y.Set(c1)
|
||||
e.z.Set(c0)
|
||||
|
||||
v0.Put(pool)
|
||||
v1.Put(pool)
|
||||
v2.Put(pool)
|
||||
c0.Put(pool)
|
||||
c1.Put(pool)
|
||||
c2.Put(pool)
|
||||
xiV2.Put(pool)
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 {
|
||||
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
||||
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
||||
|
||||
// Here we can give a short explanation of how it works: let j be a cubic root of
|
||||
// unity in GF(p²) so that 1+j+j²=0.
|
||||
// Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
|
||||
// = (xτ² + yτ + z)(Cτ²+Bτ+A)
|
||||
// = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm).
|
||||
//
|
||||
// On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
|
||||
// = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy)
|
||||
//
|
||||
// So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz)
|
||||
t1 := newGFp2(pool)
|
||||
|
||||
A := newGFp2(pool)
|
||||
A.Square(a.z, pool)
|
||||
t1.Mul(a.x, a.y, pool)
|
||||
t1.MulXi(t1, pool)
|
||||
A.Sub(A, t1)
|
||||
|
||||
B := newGFp2(pool)
|
||||
B.Square(a.x, pool)
|
||||
B.MulXi(B, pool)
|
||||
t1.Mul(a.y, a.z, pool)
|
||||
B.Sub(B, t1)
|
||||
|
||||
C_ := newGFp2(pool)
|
||||
C_.Square(a.y, pool)
|
||||
t1.Mul(a.x, a.z, pool)
|
||||
C_.Sub(C_, t1)
|
||||
|
||||
F := newGFp2(pool)
|
||||
F.Mul(C_, a.y, pool)
|
||||
F.MulXi(F, pool)
|
||||
t1.Mul(A, a.z, pool)
|
||||
F.Add(F, t1)
|
||||
t1.Mul(B, a.x, pool)
|
||||
t1.MulXi(t1, pool)
|
||||
F.Add(F, t1)
|
||||
|
||||
F.Invert(F, pool)
|
||||
|
||||
e.x.Mul(C_, F, pool)
|
||||
e.y.Mul(B, F, pool)
|
||||
e.z.Mul(A, F, pool)
|
||||
|
||||
t1.Put(pool)
|
||||
A.Put(pool)
|
||||
B.Put(pool)
|
||||
C_.Put(pool)
|
||||
F.Put(pool)
|
||||
|
||||
return e
|
||||
}
|
||||
397
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/optate.go
generated
vendored
Normal file
397
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/optate.go
generated
vendored
Normal file
@@ -0,0 +1,397 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256
|
||||
|
||||
func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
|
||||
// See the mixed addition algorithm from "Faster Computation of the
|
||||
// Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
|
||||
|
||||
B := newGFp2(pool).Mul(p.x, r.t, pool)
|
||||
|
||||
D := newGFp2(pool).Add(p.y, r.z)
|
||||
D.Square(D, pool)
|
||||
D.Sub(D, r2)
|
||||
D.Sub(D, r.t)
|
||||
D.Mul(D, r.t, pool)
|
||||
|
||||
H := newGFp2(pool).Sub(B, r.x)
|
||||
I := newGFp2(pool).Square(H, pool)
|
||||
|
||||
E := newGFp2(pool).Add(I, I)
|
||||
E.Add(E, E)
|
||||
|
||||
J := newGFp2(pool).Mul(H, E, pool)
|
||||
|
||||
L1 := newGFp2(pool).Sub(D, r.y)
|
||||
L1.Sub(L1, r.y)
|
||||
|
||||
V := newGFp2(pool).Mul(r.x, E, pool)
|
||||
|
||||
rOut = newTwistPoint(pool)
|
||||
rOut.x.Square(L1, pool)
|
||||
rOut.x.Sub(rOut.x, J)
|
||||
rOut.x.Sub(rOut.x, V)
|
||||
rOut.x.Sub(rOut.x, V)
|
||||
|
||||
rOut.z.Add(r.z, H)
|
||||
rOut.z.Square(rOut.z, pool)
|
||||
rOut.z.Sub(rOut.z, r.t)
|
||||
rOut.z.Sub(rOut.z, I)
|
||||
|
||||
t := newGFp2(pool).Sub(V, rOut.x)
|
||||
t.Mul(t, L1, pool)
|
||||
t2 := newGFp2(pool).Mul(r.y, J, pool)
|
||||
t2.Add(t2, t2)
|
||||
rOut.y.Sub(t, t2)
|
||||
|
||||
rOut.t.Square(rOut.z, pool)
|
||||
|
||||
t.Add(p.y, rOut.z)
|
||||
t.Square(t, pool)
|
||||
t.Sub(t, r2)
|
||||
t.Sub(t, rOut.t)
|
||||
|
||||
t2.Mul(L1, p.x, pool)
|
||||
t2.Add(t2, t2)
|
||||
a = newGFp2(pool)
|
||||
a.Sub(t2, t)
|
||||
|
||||
c = newGFp2(pool)
|
||||
c.MulScalar(rOut.z, q.y)
|
||||
c.Add(c, c)
|
||||
|
||||
b = newGFp2(pool)
|
||||
b.SetZero()
|
||||
b.Sub(b, L1)
|
||||
b.MulScalar(b, q.x)
|
||||
b.Add(b, b)
|
||||
|
||||
B.Put(pool)
|
||||
D.Put(pool)
|
||||
H.Put(pool)
|
||||
I.Put(pool)
|
||||
E.Put(pool)
|
||||
J.Put(pool)
|
||||
L1.Put(pool)
|
||||
V.Put(pool)
|
||||
t.Put(pool)
|
||||
t2.Put(pool)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
|
||||
// See the doubling algorithm for a=0 from "Faster Computation of the
|
||||
// Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
|
||||
|
||||
A := newGFp2(pool).Square(r.x, pool)
|
||||
B := newGFp2(pool).Square(r.y, pool)
|
||||
C_ := newGFp2(pool).Square(B, pool)
|
||||
|
||||
D := newGFp2(pool).Add(r.x, B)
|
||||
D.Square(D, pool)
|
||||
D.Sub(D, A)
|
||||
D.Sub(D, C_)
|
||||
D.Add(D, D)
|
||||
|
||||
E := newGFp2(pool).Add(A, A)
|
||||
E.Add(E, A)
|
||||
|
||||
G := newGFp2(pool).Square(E, pool)
|
||||
|
||||
rOut = newTwistPoint(pool)
|
||||
rOut.x.Sub(G, D)
|
||||
rOut.x.Sub(rOut.x, D)
|
||||
|
||||
rOut.z.Add(r.y, r.z)
|
||||
rOut.z.Square(rOut.z, pool)
|
||||
rOut.z.Sub(rOut.z, B)
|
||||
rOut.z.Sub(rOut.z, r.t)
|
||||
|
||||
rOut.y.Sub(D, rOut.x)
|
||||
rOut.y.Mul(rOut.y, E, pool)
|
||||
t := newGFp2(pool).Add(C_, C_)
|
||||
t.Add(t, t)
|
||||
t.Add(t, t)
|
||||
rOut.y.Sub(rOut.y, t)
|
||||
|
||||
rOut.t.Square(rOut.z, pool)
|
||||
|
||||
t.Mul(E, r.t, pool)
|
||||
t.Add(t, t)
|
||||
b = newGFp2(pool)
|
||||
b.SetZero()
|
||||
b.Sub(b, t)
|
||||
b.MulScalar(b, q.x)
|
||||
|
||||
a = newGFp2(pool)
|
||||
a.Add(r.x, E)
|
||||
a.Square(a, pool)
|
||||
a.Sub(a, A)
|
||||
a.Sub(a, G)
|
||||
t.Add(B, B)
|
||||
t.Add(t, t)
|
||||
a.Sub(a, t)
|
||||
|
||||
c = newGFp2(pool)
|
||||
c.Mul(rOut.z, r.t, pool)
|
||||
c.Add(c, c)
|
||||
c.MulScalar(c, q.y)
|
||||
|
||||
A.Put(pool)
|
||||
B.Put(pool)
|
||||
C_.Put(pool)
|
||||
D.Put(pool)
|
||||
E.Put(pool)
|
||||
G.Put(pool)
|
||||
t.Put(pool)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) {
|
||||
a2 := newGFp6(pool)
|
||||
a2.x.SetZero()
|
||||
a2.y.Set(a)
|
||||
a2.z.Set(b)
|
||||
a2.Mul(a2, ret.x, pool)
|
||||
t3 := newGFp6(pool).MulScalar(ret.y, c, pool)
|
||||
|
||||
t := newGFp2(pool)
|
||||
t.Add(b, c)
|
||||
t2 := newGFp6(pool)
|
||||
t2.x.SetZero()
|
||||
t2.y.Set(a)
|
||||
t2.z.Set(t)
|
||||
ret.x.Add(ret.x, ret.y)
|
||||
|
||||
ret.y.Set(t3)
|
||||
|
||||
ret.x.Mul(ret.x, t2, pool)
|
||||
ret.x.Sub(ret.x, a2)
|
||||
ret.x.Sub(ret.x, ret.y)
|
||||
a2.MulTau(a2, pool)
|
||||
ret.y.Add(ret.y, a2)
|
||||
|
||||
a2.Put(pool)
|
||||
t3.Put(pool)
|
||||
t2.Put(pool)
|
||||
t.Put(pool)
|
||||
}
|
||||
|
||||
// sixuPlus2NAF is 6u+2 in non-adjacent form.
|
||||
var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0,
|
||||
0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0, 1, 1,
|
||||
1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1,
|
||||
1, 0, 0, -1, 0, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, 1, 1}
|
||||
|
||||
// miller implements the Miller loop for calculating the Optimal Ate pairing.
|
||||
// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf
|
||||
func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 {
|
||||
ret := newGFp12(pool)
|
||||
ret.SetOne()
|
||||
|
||||
aAffine := newTwistPoint(pool)
|
||||
aAffine.Set(q)
|
||||
aAffine.MakeAffine(pool)
|
||||
|
||||
bAffine := newCurvePoint(pool)
|
||||
bAffine.Set(p)
|
||||
bAffine.MakeAffine(pool)
|
||||
|
||||
minusA := newTwistPoint(pool)
|
||||
minusA.Negative(aAffine, pool)
|
||||
|
||||
r := newTwistPoint(pool)
|
||||
r.Set(aAffine)
|
||||
|
||||
r2 := newGFp2(pool)
|
||||
r2.Square(aAffine.y, pool)
|
||||
|
||||
for i := len(sixuPlus2NAF) - 1; i > 0; i-- {
|
||||
a, b, c, newR := lineFunctionDouble(r, bAffine, pool)
|
||||
if i != len(sixuPlus2NAF)-1 {
|
||||
ret.Square(ret, pool)
|
||||
}
|
||||
|
||||
mulLine(ret, a, b, c, pool)
|
||||
a.Put(pool)
|
||||
b.Put(pool)
|
||||
c.Put(pool)
|
||||
r.Put(pool)
|
||||
r = newR
|
||||
|
||||
switch sixuPlus2NAF[i-1] {
|
||||
case 1:
|
||||
a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool)
|
||||
case -1:
|
||||
a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
mulLine(ret, a, b, c, pool)
|
||||
a.Put(pool)
|
||||
b.Put(pool)
|
||||
c.Put(pool)
|
||||
r.Put(pool)
|
||||
r = newR
|
||||
}
|
||||
|
||||
// In order to calculate Q1 we have to convert q from the sextic twist
|
||||
// to the full GF(p^12) group, apply the Frobenius there, and convert
|
||||
// back.
|
||||
//
|
||||
// The twist isomorphism is (x', y') -> (xω², yω³). If we consider just
|
||||
// x for a moment, then after applying the Frobenius, we have x̄ω^(2p)
|
||||
// where x̄ is the conjugate of x. If we are going to apply the inverse
|
||||
// isomorphism we need a value with a single coefficient of ω² so we
|
||||
// rewrite this as x̄ω^(2p-2)ω². ξ⁶ = ω and, due to the construction of
|
||||
// p, 2p-2 is a multiple of six. Therefore we can rewrite as
|
||||
// x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the
|
||||
// ω².
|
||||
//
|
||||
// A similar argument can be made for the y value.
|
||||
|
||||
q1 := newTwistPoint(pool)
|
||||
q1.x.Conjugate(aAffine.x)
|
||||
q1.x.Mul(q1.x, xiToPMinus1Over3, pool)
|
||||
q1.y.Conjugate(aAffine.y)
|
||||
q1.y.Mul(q1.y, xiToPMinus1Over2, pool)
|
||||
q1.z.SetOne()
|
||||
q1.t.SetOne()
|
||||
|
||||
// For Q2 we are applying the p² Frobenius. The two conjugations cancel
|
||||
// out and we are left only with the factors from the isomorphism. In
|
||||
// the case of x, we end up with a pure number which is why
|
||||
// xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We
|
||||
// ignore this to end up with -Q2.
|
||||
|
||||
minusQ2 := newTwistPoint(pool)
|
||||
minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3)
|
||||
minusQ2.y.Set(aAffine.y)
|
||||
minusQ2.z.SetOne()
|
||||
minusQ2.t.SetOne()
|
||||
|
||||
r2.Square(q1.y, pool)
|
||||
a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool)
|
||||
mulLine(ret, a, b, c, pool)
|
||||
a.Put(pool)
|
||||
b.Put(pool)
|
||||
c.Put(pool)
|
||||
r.Put(pool)
|
||||
r = newR
|
||||
|
||||
r2.Square(minusQ2.y, pool)
|
||||
a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool)
|
||||
mulLine(ret, a, b, c, pool)
|
||||
a.Put(pool)
|
||||
b.Put(pool)
|
||||
c.Put(pool)
|
||||
r.Put(pool)
|
||||
r = newR
|
||||
|
||||
aAffine.Put(pool)
|
||||
bAffine.Put(pool)
|
||||
minusA.Put(pool)
|
||||
r.Put(pool)
|
||||
r2.Put(pool)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// finalExponentiation computes the (p¹²-1)/Order-th power of an element of
|
||||
// GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from
|
||||
// http://cryptojedi.org/papers/dclxvi-20100714.pdf)
|
||||
func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 {
|
||||
t1 := newGFp12(pool)
|
||||
|
||||
// This is the p^6-Frobenius
|
||||
t1.x.Negative(in.x)
|
||||
t1.y.Set(in.y)
|
||||
|
||||
inv := newGFp12(pool)
|
||||
inv.Invert(in, pool)
|
||||
t1.Mul(t1, inv, pool)
|
||||
|
||||
t2 := newGFp12(pool).FrobeniusP2(t1, pool)
|
||||
t1.Mul(t1, t2, pool)
|
||||
|
||||
fp := newGFp12(pool).Frobenius(t1, pool)
|
||||
fp2 := newGFp12(pool).FrobeniusP2(t1, pool)
|
||||
fp3 := newGFp12(pool).Frobenius(fp2, pool)
|
||||
|
||||
fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
|
||||
fu.Exp(t1, u, pool)
|
||||
fu2.Exp(fu, u, pool)
|
||||
fu3.Exp(fu2, u, pool)
|
||||
|
||||
y3 := newGFp12(pool).Frobenius(fu, pool)
|
||||
fu2p := newGFp12(pool).Frobenius(fu2, pool)
|
||||
fu3p := newGFp12(pool).Frobenius(fu3, pool)
|
||||
y2 := newGFp12(pool).FrobeniusP2(fu2, pool)
|
||||
|
||||
y0 := newGFp12(pool)
|
||||
y0.Mul(fp, fp2, pool)
|
||||
y0.Mul(y0, fp3, pool)
|
||||
|
||||
y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
|
||||
y1.Conjugate(t1)
|
||||
y5.Conjugate(fu2)
|
||||
y3.Conjugate(y3)
|
||||
y4.Mul(fu, fu2p, pool)
|
||||
y4.Conjugate(y4)
|
||||
|
||||
y6 := newGFp12(pool)
|
||||
y6.Mul(fu3, fu3p, pool)
|
||||
y6.Conjugate(y6)
|
||||
|
||||
t0 := newGFp12(pool)
|
||||
t0.Square(y6, pool)
|
||||
t0.Mul(t0, y4, pool)
|
||||
t0.Mul(t0, y5, pool)
|
||||
t1.Mul(y3, y5, pool)
|
||||
t1.Mul(t1, t0, pool)
|
||||
t0.Mul(t0, y2, pool)
|
||||
t1.Square(t1, pool)
|
||||
t1.Mul(t1, t0, pool)
|
||||
t1.Square(t1, pool)
|
||||
t0.Mul(t1, y1, pool)
|
||||
t1.Mul(t1, y0, pool)
|
||||
t0.Square(t0, pool)
|
||||
t0.Mul(t0, t1, pool)
|
||||
|
||||
inv.Put(pool)
|
||||
t1.Put(pool)
|
||||
t2.Put(pool)
|
||||
fp.Put(pool)
|
||||
fp2.Put(pool)
|
||||
fp3.Put(pool)
|
||||
fu.Put(pool)
|
||||
fu2.Put(pool)
|
||||
fu3.Put(pool)
|
||||
fu2p.Put(pool)
|
||||
fu3p.Put(pool)
|
||||
y0.Put(pool)
|
||||
y1.Put(pool)
|
||||
y2.Put(pool)
|
||||
y3.Put(pool)
|
||||
y4.Put(pool)
|
||||
y5.Put(pool)
|
||||
y6.Put(pool)
|
||||
|
||||
return t0
|
||||
}
|
||||
|
||||
func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 {
|
||||
e := miller(a, b, pool)
|
||||
ret := finalExponentiation(e, pool)
|
||||
e.Put(pool)
|
||||
|
||||
if a.IsInfinity() || b.IsInfinity() {
|
||||
ret.SetOne()
|
||||
}
|
||||
return ret
|
||||
}
|
||||
263
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/twist.go
generated
vendored
Normal file
263
vendor/github.com/ethereum/go-ethereum/crypto/bn256/google/twist.go
generated
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are
|
||||
// kept in Jacobian form and t=z² when valid. The group G₂ is the set of
|
||||
// n-torsion points of this curve over GF(p²) (where n = Order)
|
||||
type twistPoint struct {
|
||||
x, y, z, t *gfP2
|
||||
}
|
||||
|
||||
var twistB = &gfP2{
|
||||
bigFromBase10("266929791119991161246907387137283842545076965332900288569378510910307636690"),
|
||||
bigFromBase10("19485874751759354771024239261021720505790618469301721065564631296452457478373"),
|
||||
}
|
||||
|
||||
// twistGen is the generator of group G₂.
|
||||
var twistGen = &twistPoint{
|
||||
&gfP2{
|
||||
bigFromBase10("11559732032986387107991004021392285783925812861821192530917403151452391805634"),
|
||||
bigFromBase10("10857046999023057135944570762232829481370756359578518086990519993285655852781"),
|
||||
},
|
||||
&gfP2{
|
||||
bigFromBase10("4082367875863433681332203403145435568316851327593401208105741076214120093531"),
|
||||
bigFromBase10("8495653923123431417604973247489272438418190587263600148770280649306958101930"),
|
||||
},
|
||||
&gfP2{
|
||||
bigFromBase10("0"),
|
||||
bigFromBase10("1"),
|
||||
},
|
||||
&gfP2{
|
||||
bigFromBase10("0"),
|
||||
bigFromBase10("1"),
|
||||
},
|
||||
}
|
||||
|
||||
func newTwistPoint(pool *bnPool) *twistPoint {
|
||||
return &twistPoint{
|
||||
newGFp2(pool),
|
||||
newGFp2(pool),
|
||||
newGFp2(pool),
|
||||
newGFp2(pool),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *twistPoint) String() string {
|
||||
return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")"
|
||||
}
|
||||
|
||||
func (c *twistPoint) Put(pool *bnPool) {
|
||||
c.x.Put(pool)
|
||||
c.y.Put(pool)
|
||||
c.z.Put(pool)
|
||||
c.t.Put(pool)
|
||||
}
|
||||
|
||||
func (c *twistPoint) Set(a *twistPoint) {
|
||||
c.x.Set(a.x)
|
||||
c.y.Set(a.y)
|
||||
c.z.Set(a.z)
|
||||
c.t.Set(a.t)
|
||||
}
|
||||
|
||||
// IsOnCurve returns true iff c is on the curve where c must be in affine form.
|
||||
func (c *twistPoint) IsOnCurve() bool {
|
||||
pool := new(bnPool)
|
||||
yy := newGFp2(pool).Square(c.y, pool)
|
||||
xxx := newGFp2(pool).Square(c.x, pool)
|
||||
xxx.Mul(xxx, c.x, pool)
|
||||
yy.Sub(yy, xxx)
|
||||
yy.Sub(yy, twistB)
|
||||
yy.Minimal()
|
||||
|
||||
if yy.x.Sign() != 0 || yy.y.Sign() != 0 {
|
||||
return false
|
||||
}
|
||||
cneg := newTwistPoint(pool)
|
||||
cneg.Mul(c, Order, pool)
|
||||
return cneg.z.IsZero()
|
||||
}
|
||||
|
||||
func (c *twistPoint) SetInfinity() {
|
||||
c.z.SetZero()
|
||||
}
|
||||
|
||||
func (c *twistPoint) IsInfinity() bool {
|
||||
return c.z.IsZero()
|
||||
}
|
||||
|
||||
func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) {
|
||||
// For additional comments, see the same function in curve.go.
|
||||
|
||||
if a.IsInfinity() {
|
||||
c.Set(b)
|
||||
return
|
||||
}
|
||||
if b.IsInfinity() {
|
||||
c.Set(a)
|
||||
return
|
||||
}
|
||||
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
|
||||
z1z1 := newGFp2(pool).Square(a.z, pool)
|
||||
z2z2 := newGFp2(pool).Square(b.z, pool)
|
||||
u1 := newGFp2(pool).Mul(a.x, z2z2, pool)
|
||||
u2 := newGFp2(pool).Mul(b.x, z1z1, pool)
|
||||
|
||||
t := newGFp2(pool).Mul(b.z, z2z2, pool)
|
||||
s1 := newGFp2(pool).Mul(a.y, t, pool)
|
||||
|
||||
t.Mul(a.z, z1z1, pool)
|
||||
s2 := newGFp2(pool).Mul(b.y, t, pool)
|
||||
|
||||
h := newGFp2(pool).Sub(u2, u1)
|
||||
xEqual := h.IsZero()
|
||||
|
||||
t.Add(h, h)
|
||||
i := newGFp2(pool).Square(t, pool)
|
||||
j := newGFp2(pool).Mul(h, i, pool)
|
||||
|
||||
t.Sub(s2, s1)
|
||||
yEqual := t.IsZero()
|
||||
if xEqual && yEqual {
|
||||
c.Double(a, pool)
|
||||
return
|
||||
}
|
||||
r := newGFp2(pool).Add(t, t)
|
||||
|
||||
v := newGFp2(pool).Mul(u1, i, pool)
|
||||
|
||||
t4 := newGFp2(pool).Square(r, pool)
|
||||
t.Add(v, v)
|
||||
t6 := newGFp2(pool).Sub(t4, j)
|
||||
c.x.Sub(t6, t)
|
||||
|
||||
t.Sub(v, c.x) // t7
|
||||
t4.Mul(s1, j, pool) // t8
|
||||
t6.Add(t4, t4) // t9
|
||||
t4.Mul(r, t, pool) // t10
|
||||
c.y.Sub(t4, t6)
|
||||
|
||||
t.Add(a.z, b.z) // t11
|
||||
t4.Square(t, pool) // t12
|
||||
t.Sub(t4, z1z1) // t13
|
||||
t4.Sub(t, z2z2) // t14
|
||||
c.z.Mul(t4, h, pool)
|
||||
|
||||
z1z1.Put(pool)
|
||||
z2z2.Put(pool)
|
||||
u1.Put(pool)
|
||||
u2.Put(pool)
|
||||
t.Put(pool)
|
||||
s1.Put(pool)
|
||||
s2.Put(pool)
|
||||
h.Put(pool)
|
||||
i.Put(pool)
|
||||
j.Put(pool)
|
||||
r.Put(pool)
|
||||
v.Put(pool)
|
||||
t4.Put(pool)
|
||||
t6.Put(pool)
|
||||
}
|
||||
|
||||
func (c *twistPoint) Double(a *twistPoint, pool *bnPool) {
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
|
||||
A := newGFp2(pool).Square(a.x, pool)
|
||||
B := newGFp2(pool).Square(a.y, pool)
|
||||
C_ := newGFp2(pool).Square(B, pool)
|
||||
|
||||
t := newGFp2(pool).Add(a.x, B)
|
||||
t2 := newGFp2(pool).Square(t, pool)
|
||||
t.Sub(t2, A)
|
||||
t2.Sub(t, C_)
|
||||
d := newGFp2(pool).Add(t2, t2)
|
||||
t.Add(A, A)
|
||||
e := newGFp2(pool).Add(t, A)
|
||||
f := newGFp2(pool).Square(e, pool)
|
||||
|
||||
t.Add(d, d)
|
||||
c.x.Sub(f, t)
|
||||
|
||||
t.Add(C_, C_)
|
||||
t2.Add(t, t)
|
||||
t.Add(t2, t2)
|
||||
c.y.Sub(d, c.x)
|
||||
t2.Mul(e, c.y, pool)
|
||||
c.y.Sub(t2, t)
|
||||
|
||||
t.Mul(a.y, a.z, pool)
|
||||
c.z.Add(t, t)
|
||||
|
||||
A.Put(pool)
|
||||
B.Put(pool)
|
||||
C_.Put(pool)
|
||||
t.Put(pool)
|
||||
t2.Put(pool)
|
||||
d.Put(pool)
|
||||
e.Put(pool)
|
||||
f.Put(pool)
|
||||
}
|
||||
|
||||
func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint {
|
||||
sum := newTwistPoint(pool)
|
||||
sum.SetInfinity()
|
||||
t := newTwistPoint(pool)
|
||||
|
||||
for i := scalar.BitLen(); i >= 0; i-- {
|
||||
t.Double(sum, pool)
|
||||
if scalar.Bit(i) != 0 {
|
||||
sum.Add(t, a, pool)
|
||||
} else {
|
||||
sum.Set(t)
|
||||
}
|
||||
}
|
||||
|
||||
c.Set(sum)
|
||||
sum.Put(pool)
|
||||
t.Put(pool)
|
||||
return c
|
||||
}
|
||||
|
||||
// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets
|
||||
// c to 0 : 1 : 0.
|
||||
func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint {
|
||||
if c.z.IsOne() {
|
||||
return c
|
||||
}
|
||||
if c.IsInfinity() {
|
||||
c.x.SetZero()
|
||||
c.y.SetOne()
|
||||
c.z.SetZero()
|
||||
c.t.SetZero()
|
||||
return c
|
||||
}
|
||||
zInv := newGFp2(pool).Invert(c.z, pool)
|
||||
t := newGFp2(pool).Mul(c.y, zInv, pool)
|
||||
zInv2 := newGFp2(pool).Square(zInv, pool)
|
||||
c.y.Mul(t, zInv2, pool)
|
||||
t.Mul(c.x, zInv2, pool)
|
||||
c.x.Set(t)
|
||||
c.z.SetOne()
|
||||
c.t.SetOne()
|
||||
|
||||
zInv.Put(pool)
|
||||
t.Put(pool)
|
||||
zInv2.Put(pool)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) {
|
||||
c.x.Set(a.x)
|
||||
c.y.SetZero()
|
||||
c.y.Sub(c.y, a.y)
|
||||
c.z.Set(a.z)
|
||||
c.t.SetZero()
|
||||
}
|
||||
284
vendor/github.com/ethereum/go-ethereum/crypto/crypto.go
generated
vendored
Normal file
284
vendor/github.com/ethereum/go-ethereum/crypto/crypto.go
generated
vendored
Normal file
@@ -0,0 +1,284 @@
|
||||
// Copyright 2014 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 crypto
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"math/big"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
// SignatureLength indicates the byte length required to carry a signature with recovery id.
|
||||
const SignatureLength = 64 + 1 // 64 bytes ECDSA signature + 1 byte recovery id
|
||||
|
||||
// RecoveryIDOffset points to the byte offset within the signature that contains the recovery id.
|
||||
const RecoveryIDOffset = 64
|
||||
|
||||
// DigestLength sets the signature digest exact length
|
||||
const DigestLength = 32
|
||||
|
||||
var (
|
||||
secp256k1N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
|
||||
secp256k1halfN = new(big.Int).Div(secp256k1N, big.NewInt(2))
|
||||
)
|
||||
|
||||
var errInvalidPubkey = errors.New("invalid secp256k1 public key")
|
||||
|
||||
// KeccakState wraps sha3.state. In addition to the usual hash methods, it also supports
|
||||
// Read to get a variable amount of data from the hash state. Read is faster than Sum
|
||||
// because it doesn't copy the internal state, but also modifies the internal state.
|
||||
type KeccakState interface {
|
||||
hash.Hash
|
||||
Read([]byte) (int, error)
|
||||
}
|
||||
|
||||
// NewKeccakState creates a new KeccakState
|
||||
func NewKeccakState() KeccakState {
|
||||
return sha3.NewLegacyKeccak256().(KeccakState)
|
||||
}
|
||||
|
||||
// HashData hashes the provided data using the KeccakState and returns a 32 byte hash
|
||||
func HashData(kh KeccakState, data []byte) (h common.Hash) {
|
||||
kh.Reset()
|
||||
kh.Write(data)
|
||||
kh.Read(h[:])
|
||||
return h
|
||||
}
|
||||
|
||||
// Keccak256 calculates and returns the Keccak256 hash of the input data.
|
||||
func Keccak256(data ...[]byte) []byte {
|
||||
b := make([]byte, 32)
|
||||
d := NewKeccakState()
|
||||
for _, b := range data {
|
||||
d.Write(b)
|
||||
}
|
||||
d.Read(b)
|
||||
return b
|
||||
}
|
||||
|
||||
// Keccak256Hash calculates and returns the Keccak256 hash of the input data,
|
||||
// converting it to an internal Hash data structure.
|
||||
func Keccak256Hash(data ...[]byte) (h common.Hash) {
|
||||
d := NewKeccakState()
|
||||
for _, b := range data {
|
||||
d.Write(b)
|
||||
}
|
||||
d.Read(h[:])
|
||||
return h
|
||||
}
|
||||
|
||||
// Keccak512 calculates and returns the Keccak512 hash of the input data.
|
||||
func Keccak512(data ...[]byte) []byte {
|
||||
d := sha3.NewLegacyKeccak512()
|
||||
for _, b := range data {
|
||||
d.Write(b)
|
||||
}
|
||||
return d.Sum(nil)
|
||||
}
|
||||
|
||||
// CreateAddress creates an ethereum address given the bytes and the nonce
|
||||
func CreateAddress(b common.Address, nonce uint64) common.Address {
|
||||
data, _ := rlp.EncodeToBytes([]interface{}{b, nonce})
|
||||
return common.BytesToAddress(Keccak256(data)[12:])
|
||||
}
|
||||
|
||||
// CreateAddress2 creates an ethereum address given the address bytes, initial
|
||||
// contract code hash and a salt.
|
||||
func CreateAddress2(b common.Address, salt [32]byte, inithash []byte) common.Address {
|
||||
return common.BytesToAddress(Keccak256([]byte{0xff}, b.Bytes(), salt[:], inithash)[12:])
|
||||
}
|
||||
|
||||
// ToECDSA creates a private key with the given D value.
|
||||
func ToECDSA(d []byte) (*ecdsa.PrivateKey, error) {
|
||||
return toECDSA(d, true)
|
||||
}
|
||||
|
||||
// ToECDSAUnsafe blindly converts a binary blob to a private key. It should almost
|
||||
// never be used unless you are sure the input is valid and want to avoid hitting
|
||||
// errors due to bad origin encoding (0 prefixes cut off).
|
||||
func ToECDSAUnsafe(d []byte) *ecdsa.PrivateKey {
|
||||
priv, _ := toECDSA(d, false)
|
||||
return priv
|
||||
}
|
||||
|
||||
// toECDSA creates a private key with the given D value. The strict parameter
|
||||
// controls whether the key's length should be enforced at the curve size or
|
||||
// it can also accept legacy encodings (0 prefixes).
|
||||
func toECDSA(d []byte, strict bool) (*ecdsa.PrivateKey, error) {
|
||||
priv := new(ecdsa.PrivateKey)
|
||||
priv.PublicKey.Curve = S256()
|
||||
if strict && 8*len(d) != priv.Params().BitSize {
|
||||
return nil, fmt.Errorf("invalid length, need %d bits", priv.Params().BitSize)
|
||||
}
|
||||
priv.D = new(big.Int).SetBytes(d)
|
||||
|
||||
// The priv.D must < N
|
||||
if priv.D.Cmp(secp256k1N) >= 0 {
|
||||
return nil, fmt.Errorf("invalid private key, >=N")
|
||||
}
|
||||
// The priv.D must not be zero or negative.
|
||||
if priv.D.Sign() <= 0 {
|
||||
return nil, fmt.Errorf("invalid private key, zero or negative")
|
||||
}
|
||||
|
||||
priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(d)
|
||||
if priv.PublicKey.X == nil {
|
||||
return nil, errors.New("invalid private key")
|
||||
}
|
||||
return priv, nil
|
||||
}
|
||||
|
||||
// FromECDSA exports a private key into a binary dump.
|
||||
func FromECDSA(priv *ecdsa.PrivateKey) []byte {
|
||||
if priv == nil {
|
||||
return nil
|
||||
}
|
||||
return math.PaddedBigBytes(priv.D, priv.Params().BitSize/8)
|
||||
}
|
||||
|
||||
// UnmarshalPubkey converts bytes to a secp256k1 public key.
|
||||
func UnmarshalPubkey(pub []byte) (*ecdsa.PublicKey, error) {
|
||||
x, y := elliptic.Unmarshal(S256(), pub)
|
||||
if x == nil {
|
||||
return nil, errInvalidPubkey
|
||||
}
|
||||
return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}, nil
|
||||
}
|
||||
|
||||
func FromECDSAPub(pub *ecdsa.PublicKey) []byte {
|
||||
if pub == nil || pub.X == nil || pub.Y == nil {
|
||||
return nil
|
||||
}
|
||||
return elliptic.Marshal(S256(), pub.X, pub.Y)
|
||||
}
|
||||
|
||||
// HexToECDSA parses a secp256k1 private key.
|
||||
func HexToECDSA(hexkey string) (*ecdsa.PrivateKey, error) {
|
||||
b, err := hex.DecodeString(hexkey)
|
||||
if byteErr, ok := err.(hex.InvalidByteError); ok {
|
||||
return nil, fmt.Errorf("invalid hex character %q in private key", byte(byteErr))
|
||||
} else if err != nil {
|
||||
return nil, errors.New("invalid hex data for private key")
|
||||
}
|
||||
return ToECDSA(b)
|
||||
}
|
||||
|
||||
// LoadECDSA loads a secp256k1 private key from the given file.
|
||||
func LoadECDSA(file string) (*ecdsa.PrivateKey, error) {
|
||||
fd, err := os.Open(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fd.Close()
|
||||
|
||||
r := bufio.NewReader(fd)
|
||||
buf := make([]byte, 64)
|
||||
n, err := readASCII(buf, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if n != len(buf) {
|
||||
return nil, fmt.Errorf("key file too short, want 64 hex characters")
|
||||
}
|
||||
if err := checkKeyFileEnd(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return HexToECDSA(string(buf))
|
||||
}
|
||||
|
||||
// readASCII reads into 'buf', stopping when the buffer is full or
|
||||
// when a non-printable control character is encountered.
|
||||
func readASCII(buf []byte, r *bufio.Reader) (n int, err error) {
|
||||
for ; n < len(buf); n++ {
|
||||
buf[n], err = r.ReadByte()
|
||||
switch {
|
||||
case err == io.EOF || buf[n] < '!':
|
||||
return n, nil
|
||||
case err != nil:
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// checkKeyFileEnd skips over additional newlines at the end of a key file.
|
||||
func checkKeyFileEnd(r *bufio.Reader) error {
|
||||
for i := 0; ; i++ {
|
||||
b, err := r.ReadByte()
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
return nil
|
||||
case err != nil:
|
||||
return err
|
||||
case b != '\n' && b != '\r':
|
||||
return fmt.Errorf("invalid character %q at end of key file", b)
|
||||
case i >= 2:
|
||||
return errors.New("key file too long, want 64 hex characters")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SaveECDSA saves a secp256k1 private key to the given file with
|
||||
// restrictive permissions. The key data is saved hex-encoded.
|
||||
func SaveECDSA(file string, key *ecdsa.PrivateKey) error {
|
||||
k := hex.EncodeToString(FromECDSA(key))
|
||||
return os.WriteFile(file, []byte(k), 0600)
|
||||
}
|
||||
|
||||
// GenerateKey generates a new private key.
|
||||
func GenerateKey() (*ecdsa.PrivateKey, error) {
|
||||
return ecdsa.GenerateKey(S256(), rand.Reader)
|
||||
}
|
||||
|
||||
// ValidateSignatureValues verifies whether the signature values are valid with
|
||||
// the given chain rules. The v value is assumed to be either 0 or 1.
|
||||
func ValidateSignatureValues(v byte, r, s *big.Int, homestead bool) bool {
|
||||
if r.Cmp(common.Big1) < 0 || s.Cmp(common.Big1) < 0 {
|
||||
return false
|
||||
}
|
||||
// reject upper range of s values (ECDSA malleability)
|
||||
// see discussion in secp256k1/libsecp256k1/include/secp256k1.h
|
||||
if homestead && s.Cmp(secp256k1halfN) > 0 {
|
||||
return false
|
||||
}
|
||||
// Frontier: allow s to be in full N range
|
||||
return r.Cmp(secp256k1N) < 0 && s.Cmp(secp256k1N) < 0 && (v == 0 || v == 1)
|
||||
}
|
||||
|
||||
func PubkeyToAddress(p ecdsa.PublicKey) common.Address {
|
||||
pubBytes := FromECDSAPub(&p)
|
||||
return common.BytesToAddress(Keccak256(pubBytes[1:])[12:])
|
||||
}
|
||||
|
||||
func zeroBytes(bytes []byte) {
|
||||
for i := range bytes {
|
||||
bytes[i] = 0
|
||||
}
|
||||
}
|
||||
24
vendor/github.com/ethereum/go-ethereum/crypto/ecies/.gitignore
generated
vendored
Normal file
24
vendor/github.com/ethereum/go-ethereum/crypto/ecies/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
|
||||
*~
|
||||
28
vendor/github.com/ethereum/go-ethereum/crypto/ecies/LICENSE
generated
vendored
Normal file
28
vendor/github.com/ethereum/go-ethereum/crypto/ecies/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
Copyright (c) 2013 Kyle Isom <kyle@tyrfingr.is>
|
||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
94
vendor/github.com/ethereum/go-ethereum/crypto/ecies/README
generated
vendored
Normal file
94
vendor/github.com/ethereum/go-ethereum/crypto/ecies/README
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
# NOTE
|
||||
|
||||
This implementation is direct fork of Kylom's implementation. I claim no authorship over this code apart from some minor modifications.
|
||||
Please be aware this code **has not yet been reviewed**.
|
||||
|
||||
ecies implements the Elliptic Curve Integrated Encryption Scheme.
|
||||
|
||||
The package is designed to be compliant with the appropriate NIST
|
||||
standards, and therefore doesn't support the full SEC 1 algorithm set.
|
||||
|
||||
|
||||
STATUS:
|
||||
|
||||
ecies should be ready for use. The ASN.1 support is only complete so
|
||||
far as to supported the listed algorithms before.
|
||||
|
||||
|
||||
CAVEATS
|
||||
|
||||
1. CMAC support is currently not present.
|
||||
|
||||
|
||||
SUPPORTED ALGORITHMS
|
||||
|
||||
SYMMETRIC CIPHERS HASH FUNCTIONS
|
||||
AES128 SHA-1
|
||||
AES192 SHA-224
|
||||
AES256 SHA-256
|
||||
SHA-384
|
||||
ELLIPTIC CURVE SHA-512
|
||||
P256
|
||||
P384 KEY DERIVATION FUNCTION
|
||||
P521 NIST SP 800-65a Concatenation KDF
|
||||
|
||||
Curve P224 isn't supported because it does not provide a minimum security
|
||||
level of AES128 with HMAC-SHA1. According to NIST SP 800-57, the security
|
||||
level of P224 is 112 bits of security. Symmetric ciphers use CTR-mode;
|
||||
message tags are computed using HMAC-<HASH> function.
|
||||
|
||||
|
||||
CURVE SELECTION
|
||||
|
||||
According to NIST SP 800-57, the following curves should be selected:
|
||||
|
||||
+----------------+-------+
|
||||
| SYMMETRIC SIZE | CURVE |
|
||||
+----------------+-------+
|
||||
| 128-bit | P256 |
|
||||
+----------------+-------+
|
||||
| 192-bit | P384 |
|
||||
+----------------+-------+
|
||||
| 256-bit | P521 |
|
||||
+----------------+-------+
|
||||
|
||||
|
||||
TODO
|
||||
|
||||
1. Look at serialising the parameters with the SEC 1 ASN.1 module.
|
||||
2. Validate ASN.1 formats with SEC 1.
|
||||
|
||||
|
||||
TEST VECTORS
|
||||
|
||||
The only test vectors I've found so far date from 1993, predating AES
|
||||
and including only 163-bit curves. Therefore, there are no published
|
||||
test vectors to compare to.
|
||||
|
||||
|
||||
LICENSE
|
||||
|
||||
ecies is released under the same license as the Go source code. See the
|
||||
LICENSE file for details.
|
||||
|
||||
|
||||
REFERENCES
|
||||
|
||||
* SEC (Standard for Efficient Cryptography) 1, version 2.0: Elliptic
|
||||
Curve Cryptography; Certicom, May 2009.
|
||||
http://www.secg.org/sec1-v2.pdf
|
||||
* GEC (Guidelines for Efficient Cryptography) 2, version 0.3: Test
|
||||
Vectors for SEC 1; Certicom, September 1999.
|
||||
http://read.pudn.com/downloads168/doc/772358/TestVectorsforSEC%201-gec2.pdf
|
||||
* NIST SP 800-56a: Recommendation for Pair-Wise Key Establishment Schemes
|
||||
Using Discrete Logarithm Cryptography. National Institute of Standards
|
||||
and Technology, May 2007.
|
||||
http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf
|
||||
* Suite B Implementer’s Guide to NIST SP 800-56A. National Security
|
||||
Agency, July 28, 2009.
|
||||
http://www.nsa.gov/ia/_files/SuiteB_Implementer_G-113808.pdf
|
||||
* NIST SP 800-57: Recommendation for Key Management – Part 1: General
|
||||
(Revision 3). National Institute of Standards and Technology, July
|
||||
2012.
|
||||
http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf
|
||||
|
||||
317
vendor/github.com/ethereum/go-ethereum/crypto/ecies/ecies.go
generated
vendored
Normal file
317
vendor/github.com/ethereum/go-ethereum/crypto/ecies/ecies.go
generated
vendored
Normal file
@@ -0,0 +1,317 @@
|
||||
// Copyright (c) 2013 Kyle Isom <kyle@tyrfingr.is>
|
||||
// Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package ecies
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/hmac"
|
||||
"crypto/subtle"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrImport = fmt.Errorf("ecies: failed to import key")
|
||||
ErrInvalidCurve = fmt.Errorf("ecies: invalid elliptic curve")
|
||||
ErrInvalidPublicKey = fmt.Errorf("ecies: invalid public key")
|
||||
ErrSharedKeyIsPointAtInfinity = fmt.Errorf("ecies: shared key is point at infinity")
|
||||
ErrSharedKeyTooBig = fmt.Errorf("ecies: shared key params are too big")
|
||||
)
|
||||
|
||||
// PublicKey is a representation of an elliptic curve public key.
|
||||
type PublicKey struct {
|
||||
X *big.Int
|
||||
Y *big.Int
|
||||
elliptic.Curve
|
||||
Params *ECIESParams
|
||||
}
|
||||
|
||||
// Export an ECIES public key as an ECDSA public key.
|
||||
func (pub *PublicKey) ExportECDSA() *ecdsa.PublicKey {
|
||||
return &ecdsa.PublicKey{Curve: pub.Curve, X: pub.X, Y: pub.Y}
|
||||
}
|
||||
|
||||
// Import an ECDSA public key as an ECIES public key.
|
||||
func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey {
|
||||
return &PublicKey{
|
||||
X: pub.X,
|
||||
Y: pub.Y,
|
||||
Curve: pub.Curve,
|
||||
Params: ParamsFromCurve(pub.Curve),
|
||||
}
|
||||
}
|
||||
|
||||
// PrivateKey is a representation of an elliptic curve private key.
|
||||
type PrivateKey struct {
|
||||
PublicKey
|
||||
D *big.Int
|
||||
}
|
||||
|
||||
// Export an ECIES private key as an ECDSA private key.
|
||||
func (prv *PrivateKey) ExportECDSA() *ecdsa.PrivateKey {
|
||||
pub := &prv.PublicKey
|
||||
pubECDSA := pub.ExportECDSA()
|
||||
return &ecdsa.PrivateKey{PublicKey: *pubECDSA, D: prv.D}
|
||||
}
|
||||
|
||||
// Import an ECDSA private key as an ECIES private key.
|
||||
func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey {
|
||||
pub := ImportECDSAPublic(&prv.PublicKey)
|
||||
return &PrivateKey{*pub, prv.D}
|
||||
}
|
||||
|
||||
// Generate an elliptic curve public / private keypair. If params is nil,
|
||||
// the recommended default parameters for the key will be chosen.
|
||||
func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) {
|
||||
pb, x, y, err := elliptic.GenerateKey(curve, rand)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
prv = new(PrivateKey)
|
||||
prv.PublicKey.X = x
|
||||
prv.PublicKey.Y = y
|
||||
prv.PublicKey.Curve = curve
|
||||
prv.D = new(big.Int).SetBytes(pb)
|
||||
if params == nil {
|
||||
params = ParamsFromCurve(curve)
|
||||
}
|
||||
prv.PublicKey.Params = params
|
||||
return
|
||||
}
|
||||
|
||||
// MaxSharedKeyLength returns the maximum length of the shared key the
|
||||
// public key can produce.
|
||||
func MaxSharedKeyLength(pub *PublicKey) int {
|
||||
return (pub.Curve.Params().BitSize + 7) / 8
|
||||
}
|
||||
|
||||
// ECDH key agreement method used to establish secret keys for encryption.
|
||||
func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []byte, err error) {
|
||||
if prv.PublicKey.Curve != pub.Curve {
|
||||
return nil, ErrInvalidCurve
|
||||
}
|
||||
if skLen+macLen > MaxSharedKeyLength(pub) {
|
||||
return nil, ErrSharedKeyTooBig
|
||||
}
|
||||
|
||||
x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, prv.D.Bytes())
|
||||
if x == nil {
|
||||
return nil, ErrSharedKeyIsPointAtInfinity
|
||||
}
|
||||
|
||||
sk = make([]byte, skLen+macLen)
|
||||
skBytes := x.Bytes()
|
||||
copy(sk[len(sk)-len(skBytes):], skBytes)
|
||||
return sk, nil
|
||||
}
|
||||
|
||||
var (
|
||||
ErrSharedTooLong = fmt.Errorf("ecies: shared secret is too long")
|
||||
ErrInvalidMessage = fmt.Errorf("ecies: invalid message")
|
||||
)
|
||||
|
||||
// NIST SP 800-56 Concatenation Key Derivation Function (see section 5.8.1).
|
||||
func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) []byte {
|
||||
counterBytes := make([]byte, 4)
|
||||
k := make([]byte, 0, roundup(kdLen, hash.Size()))
|
||||
for counter := uint32(1); len(k) < kdLen; counter++ {
|
||||
binary.BigEndian.PutUint32(counterBytes, counter)
|
||||
hash.Reset()
|
||||
hash.Write(counterBytes)
|
||||
hash.Write(z)
|
||||
hash.Write(s1)
|
||||
k = hash.Sum(k)
|
||||
}
|
||||
return k[:kdLen]
|
||||
}
|
||||
|
||||
// roundup rounds size up to the next multiple of blocksize.
|
||||
func roundup(size, blocksize int) int {
|
||||
return size + blocksize - (size % blocksize)
|
||||
}
|
||||
|
||||
// deriveKeys creates the encryption and MAC keys using concatKDF.
|
||||
func deriveKeys(hash hash.Hash, z, s1 []byte, keyLen int) (Ke, Km []byte) {
|
||||
K := concatKDF(hash, z, s1, 2*keyLen)
|
||||
Ke = K[:keyLen]
|
||||
Km = K[keyLen:]
|
||||
hash.Reset()
|
||||
hash.Write(Km)
|
||||
Km = hash.Sum(Km[:0])
|
||||
return Ke, Km
|
||||
}
|
||||
|
||||
// messageTag computes the MAC of a message (called the tag) as per
|
||||
// SEC 1, 3.5.
|
||||
func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte {
|
||||
mac := hmac.New(hash, km)
|
||||
mac.Write(msg)
|
||||
mac.Write(shared)
|
||||
tag := mac.Sum(nil)
|
||||
return tag
|
||||
}
|
||||
|
||||
// Generate an initialisation vector for CTR mode.
|
||||
func generateIV(params *ECIESParams, rand io.Reader) (iv []byte, err error) {
|
||||
iv = make([]byte, params.BlockSize)
|
||||
_, err = io.ReadFull(rand, iv)
|
||||
return
|
||||
}
|
||||
|
||||
// symEncrypt carries out CTR encryption using the block cipher specified in the
|
||||
func symEncrypt(rand io.Reader, params *ECIESParams, key, m []byte) (ct []byte, err error) {
|
||||
c, err := params.Cipher(key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
iv, err := generateIV(params, rand)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ctr := cipher.NewCTR(c, iv)
|
||||
|
||||
ct = make([]byte, len(m)+params.BlockSize)
|
||||
copy(ct, iv)
|
||||
ctr.XORKeyStream(ct[params.BlockSize:], m)
|
||||
return
|
||||
}
|
||||
|
||||
// symDecrypt carries out CTR decryption using the block cipher specified in
|
||||
// the parameters
|
||||
func symDecrypt(params *ECIESParams, key, ct []byte) (m []byte, err error) {
|
||||
c, err := params.Cipher(key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctr := cipher.NewCTR(c, ct[:params.BlockSize])
|
||||
|
||||
m = make([]byte, len(ct)-params.BlockSize)
|
||||
ctr.XORKeyStream(m, ct[params.BlockSize:])
|
||||
return
|
||||
}
|
||||
|
||||
// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1.
|
||||
//
|
||||
// s1 and s2 contain shared information that is not part of the resulting
|
||||
// ciphertext. s1 is fed into key derivation, s2 is fed into the MAC. If the
|
||||
// shared information parameters aren't being used, they should be nil.
|
||||
func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) {
|
||||
params, err := pubkeyParams(pub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
R, err := GenerateKey(rand, pub.Curve, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
z, err := R.GenerateShared(pub, params.KeyLen, params.KeyLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hash := params.Hash()
|
||||
Ke, Km := deriveKeys(hash, z, s1, params.KeyLen)
|
||||
|
||||
em, err := symEncrypt(rand, params, Ke, m)
|
||||
if err != nil || len(em) <= params.BlockSize {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d := messageTag(params.Hash, Km, em, s2)
|
||||
|
||||
Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y)
|
||||
ct = make([]byte, len(Rb)+len(em)+len(d))
|
||||
copy(ct, Rb)
|
||||
copy(ct[len(Rb):], em)
|
||||
copy(ct[len(Rb)+len(em):], d)
|
||||
return ct, nil
|
||||
}
|
||||
|
||||
// Decrypt decrypts an ECIES ciphertext.
|
||||
func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) {
|
||||
if len(c) == 0 {
|
||||
return nil, ErrInvalidMessage
|
||||
}
|
||||
params, err := pubkeyParams(&prv.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hash := params.Hash()
|
||||
|
||||
var (
|
||||
rLen int
|
||||
hLen int = hash.Size()
|
||||
mStart int
|
||||
mEnd int
|
||||
)
|
||||
|
||||
switch c[0] {
|
||||
case 2, 3, 4:
|
||||
rLen = (prv.PublicKey.Curve.Params().BitSize + 7) / 4
|
||||
if len(c) < (rLen + hLen + 1) {
|
||||
return nil, ErrInvalidMessage
|
||||
}
|
||||
default:
|
||||
return nil, ErrInvalidPublicKey
|
||||
}
|
||||
|
||||
mStart = rLen
|
||||
mEnd = len(c) - hLen
|
||||
|
||||
R := new(PublicKey)
|
||||
R.Curve = prv.PublicKey.Curve
|
||||
R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen])
|
||||
if R.X == nil {
|
||||
return nil, ErrInvalidPublicKey
|
||||
}
|
||||
|
||||
z, err := prv.GenerateShared(R, params.KeyLen, params.KeyLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
Ke, Km := deriveKeys(hash, z, s1, params.KeyLen)
|
||||
|
||||
d := messageTag(params.Hash, Km, c[mStart:mEnd], s2)
|
||||
if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 {
|
||||
return nil, ErrInvalidMessage
|
||||
}
|
||||
|
||||
return symDecrypt(params, Ke, c[mStart:mEnd])
|
||||
}
|
||||
144
vendor/github.com/ethereum/go-ethereum/crypto/ecies/params.go
generated
vendored
Normal file
144
vendor/github.com/ethereum/go-ethereum/crypto/ecies/params.go
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
// Copyright (c) 2013 Kyle Isom <kyle@tyrfingr.is>
|
||||
// Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package ecies
|
||||
|
||||
// This file contains parameters for ECIES encryption, specifying the
|
||||
// symmetric encryption and HMAC parameters.
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/elliptic"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"fmt"
|
||||
"hash"
|
||||
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultCurve = ethcrypto.S256()
|
||||
ErrUnsupportedECDHAlgorithm = fmt.Errorf("ecies: unsupported ECDH algorithm")
|
||||
ErrUnsupportedECIESParameters = fmt.Errorf("ecies: unsupported ECIES parameters")
|
||||
ErrInvalidKeyLen = fmt.Errorf("ecies: invalid key size (> %d) in ECIESParams", maxKeyLen)
|
||||
)
|
||||
|
||||
// KeyLen is limited to prevent overflow of the counter
|
||||
// in concatKDF. While the theoretical limit is much higher,
|
||||
// no known cipher uses keys larger than 512 bytes.
|
||||
const maxKeyLen = 512
|
||||
|
||||
type ECIESParams struct {
|
||||
Hash func() hash.Hash // hash function
|
||||
hashAlgo crypto.Hash
|
||||
Cipher func([]byte) (cipher.Block, error) // symmetric cipher
|
||||
BlockSize int // block size of symmetric cipher
|
||||
KeyLen int // length of symmetric key
|
||||
}
|
||||
|
||||
// Standard ECIES parameters:
|
||||
// * ECIES using AES128 and HMAC-SHA-256-16
|
||||
// * ECIES using AES256 and HMAC-SHA-256-32
|
||||
// * ECIES using AES256 and HMAC-SHA-384-48
|
||||
// * ECIES using AES256 and HMAC-SHA-512-64
|
||||
|
||||
var (
|
||||
ECIES_AES128_SHA256 = &ECIESParams{
|
||||
Hash: sha256.New,
|
||||
hashAlgo: crypto.SHA256,
|
||||
Cipher: aes.NewCipher,
|
||||
BlockSize: aes.BlockSize,
|
||||
KeyLen: 16,
|
||||
}
|
||||
|
||||
ECIES_AES192_SHA384 = &ECIESParams{
|
||||
Hash: sha512.New384,
|
||||
hashAlgo: crypto.SHA384,
|
||||
Cipher: aes.NewCipher,
|
||||
BlockSize: aes.BlockSize,
|
||||
KeyLen: 24,
|
||||
}
|
||||
|
||||
ECIES_AES256_SHA256 = &ECIESParams{
|
||||
Hash: sha256.New,
|
||||
hashAlgo: crypto.SHA256,
|
||||
Cipher: aes.NewCipher,
|
||||
BlockSize: aes.BlockSize,
|
||||
KeyLen: 32,
|
||||
}
|
||||
|
||||
ECIES_AES256_SHA384 = &ECIESParams{
|
||||
Hash: sha512.New384,
|
||||
hashAlgo: crypto.SHA384,
|
||||
Cipher: aes.NewCipher,
|
||||
BlockSize: aes.BlockSize,
|
||||
KeyLen: 32,
|
||||
}
|
||||
|
||||
ECIES_AES256_SHA512 = &ECIESParams{
|
||||
Hash: sha512.New,
|
||||
hashAlgo: crypto.SHA512,
|
||||
Cipher: aes.NewCipher,
|
||||
BlockSize: aes.BlockSize,
|
||||
KeyLen: 32,
|
||||
}
|
||||
)
|
||||
|
||||
var paramsFromCurve = map[elliptic.Curve]*ECIESParams{
|
||||
ethcrypto.S256(): ECIES_AES128_SHA256,
|
||||
elliptic.P256(): ECIES_AES128_SHA256,
|
||||
elliptic.P384(): ECIES_AES192_SHA384,
|
||||
elliptic.P521(): ECIES_AES256_SHA512,
|
||||
}
|
||||
|
||||
func AddParamsForCurve(curve elliptic.Curve, params *ECIESParams) {
|
||||
paramsFromCurve[curve] = params
|
||||
}
|
||||
|
||||
// ParamsFromCurve selects parameters optimal for the selected elliptic curve.
|
||||
// Only the curves P256, P384, and P512 are supported.
|
||||
func ParamsFromCurve(curve elliptic.Curve) (params *ECIESParams) {
|
||||
return paramsFromCurve[curve]
|
||||
}
|
||||
|
||||
func pubkeyParams(key *PublicKey) (*ECIESParams, error) {
|
||||
params := key.Params
|
||||
if params == nil {
|
||||
if params = ParamsFromCurve(key.Curve); params == nil {
|
||||
return nil, ErrUnsupportedECIESParameters
|
||||
}
|
||||
}
|
||||
if params.KeyLen > maxKeyLen {
|
||||
return nil, ErrInvalidKeyLen
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
24
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/.gitignore
generated
vendored
Normal file
24
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
|
||||
*~
|
||||
31
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/LICENSE
generated
vendored
Normal file
31
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
Copyright (c) 2010 The Go Authors. All rights reserved.
|
||||
Copyright (c) 2011 ThePiachu. All rights reserved.
|
||||
Copyright (c) 2015 Jeffrey Wilcke. All rights reserved.
|
||||
Copyright (c) 2015 Felix Lange. All rights reserved.
|
||||
Copyright (c) 2015 Gustav Simonsson. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the copyright holder. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
297
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/curve.go
generated
vendored
Normal file
297
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/curve.go
generated
vendored
Normal file
@@ -0,0 +1,297 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Copyright 2011 ThePiachu. All rights reserved.
|
||||
// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
// * The name of ThePiachu may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package secp256k1
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
const (
|
||||
// number of bits in a big.Word
|
||||
wordBits = 32 << (uint64(^big.Word(0)) >> 63)
|
||||
// number of bytes in a big.Word
|
||||
wordBytes = wordBits / 8
|
||||
)
|
||||
|
||||
// readBits encodes the absolute value of bigint as big-endian bytes. Callers
|
||||
// must ensure that buf has enough space. If buf is too short the result will
|
||||
// be incomplete.
|
||||
func readBits(bigint *big.Int, buf []byte) {
|
||||
i := len(buf)
|
||||
for _, d := range bigint.Bits() {
|
||||
for j := 0; j < wordBytes && i > 0; j++ {
|
||||
i--
|
||||
buf[i] = byte(d)
|
||||
d >>= 8
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This code is from https://github.com/ThePiachu/GoBit and implements
|
||||
// several Koblitz elliptic curves over prime fields.
|
||||
//
|
||||
// The curve methods, internally, on Jacobian coordinates. For a given
|
||||
// (x, y) position on the curve, the Jacobian coordinates are (x1, y1,
|
||||
// z1) where x = x1/z1² and y = y1/z1³. The greatest speedups come
|
||||
// when the whole calculation can be performed within the transform
|
||||
// (as in ScalarMult and ScalarBaseMult). But even for Add and Double,
|
||||
// it's faster to apply and reverse the transform than to operate in
|
||||
// affine coordinates.
|
||||
|
||||
// A BitCurve represents a Koblitz Curve with a=0.
|
||||
// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
|
||||
type BitCurve struct {
|
||||
P *big.Int // the order of the underlying field
|
||||
N *big.Int // the order of the base point
|
||||
B *big.Int // the constant of the BitCurve equation
|
||||
Gx, Gy *big.Int // (x,y) of the base point
|
||||
BitSize int // the size of the underlying field
|
||||
}
|
||||
|
||||
func (BitCurve *BitCurve) Params() *elliptic.CurveParams {
|
||||
return &elliptic.CurveParams{
|
||||
P: BitCurve.P,
|
||||
N: BitCurve.N,
|
||||
B: BitCurve.B,
|
||||
Gx: BitCurve.Gx,
|
||||
Gy: BitCurve.Gy,
|
||||
BitSize: BitCurve.BitSize,
|
||||
}
|
||||
}
|
||||
|
||||
// IsOnCurve returns true if the given (x,y) lies on the BitCurve.
|
||||
func (BitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool {
|
||||
// y² = x³ + b
|
||||
y2 := new(big.Int).Mul(y, y) //y²
|
||||
y2.Mod(y2, BitCurve.P) //y²%P
|
||||
|
||||
x3 := new(big.Int).Mul(x, x) //x²
|
||||
x3.Mul(x3, x) //x³
|
||||
|
||||
x3.Add(x3, BitCurve.B) //x³+B
|
||||
x3.Mod(x3, BitCurve.P) //(x³+B)%P
|
||||
|
||||
return x3.Cmp(y2) == 0
|
||||
}
|
||||
|
||||
// affineFromJacobian reverses the Jacobian transform. See the comment at the
|
||||
// top of the file.
|
||||
func (BitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
|
||||
if z.Sign() == 0 {
|
||||
return new(big.Int), new(big.Int)
|
||||
}
|
||||
|
||||
zinv := new(big.Int).ModInverse(z, BitCurve.P)
|
||||
zinvsq := new(big.Int).Mul(zinv, zinv)
|
||||
|
||||
xOut = new(big.Int).Mul(x, zinvsq)
|
||||
xOut.Mod(xOut, BitCurve.P)
|
||||
zinvsq.Mul(zinvsq, zinv)
|
||||
yOut = new(big.Int).Mul(y, zinvsq)
|
||||
yOut.Mod(yOut, BitCurve.P)
|
||||
return
|
||||
}
|
||||
|
||||
// Add returns the sum of (x1,y1) and (x2,y2)
|
||||
func (BitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
|
||||
// If one point is at infinity, return the other point.
|
||||
// Adding the point at infinity to any point will preserve the other point.
|
||||
if x1.Sign() == 0 && y1.Sign() == 0 {
|
||||
return x2, y2
|
||||
}
|
||||
if x2.Sign() == 0 && y2.Sign() == 0 {
|
||||
return x1, y1
|
||||
}
|
||||
z := new(big.Int).SetInt64(1)
|
||||
if x1.Cmp(x2) == 0 && y1.Cmp(y2) == 0 {
|
||||
return BitCurve.affineFromJacobian(BitCurve.doubleJacobian(x1, y1, z))
|
||||
}
|
||||
return BitCurve.affineFromJacobian(BitCurve.addJacobian(x1, y1, z, x2, y2, z))
|
||||
}
|
||||
|
||||
// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
|
||||
// (x2, y2, z2) and returns their sum, also in Jacobian form.
|
||||
func (BitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
|
||||
z1z1 := new(big.Int).Mul(z1, z1)
|
||||
z1z1.Mod(z1z1, BitCurve.P)
|
||||
z2z2 := new(big.Int).Mul(z2, z2)
|
||||
z2z2.Mod(z2z2, BitCurve.P)
|
||||
|
||||
u1 := new(big.Int).Mul(x1, z2z2)
|
||||
u1.Mod(u1, BitCurve.P)
|
||||
u2 := new(big.Int).Mul(x2, z1z1)
|
||||
u2.Mod(u2, BitCurve.P)
|
||||
h := new(big.Int).Sub(u2, u1)
|
||||
if h.Sign() == -1 {
|
||||
h.Add(h, BitCurve.P)
|
||||
}
|
||||
i := new(big.Int).Lsh(h, 1)
|
||||
i.Mul(i, i)
|
||||
j := new(big.Int).Mul(h, i)
|
||||
|
||||
s1 := new(big.Int).Mul(y1, z2)
|
||||
s1.Mul(s1, z2z2)
|
||||
s1.Mod(s1, BitCurve.P)
|
||||
s2 := new(big.Int).Mul(y2, z1)
|
||||
s2.Mul(s2, z1z1)
|
||||
s2.Mod(s2, BitCurve.P)
|
||||
r := new(big.Int).Sub(s2, s1)
|
||||
if r.Sign() == -1 {
|
||||
r.Add(r, BitCurve.P)
|
||||
}
|
||||
r.Lsh(r, 1)
|
||||
v := new(big.Int).Mul(u1, i)
|
||||
|
||||
x3 := new(big.Int).Set(r)
|
||||
x3.Mul(x3, x3)
|
||||
x3.Sub(x3, j)
|
||||
x3.Sub(x3, v)
|
||||
x3.Sub(x3, v)
|
||||
x3.Mod(x3, BitCurve.P)
|
||||
|
||||
y3 := new(big.Int).Set(r)
|
||||
v.Sub(v, x3)
|
||||
y3.Mul(y3, v)
|
||||
s1.Mul(s1, j)
|
||||
s1.Lsh(s1, 1)
|
||||
y3.Sub(y3, s1)
|
||||
y3.Mod(y3, BitCurve.P)
|
||||
|
||||
z3 := new(big.Int).Add(z1, z2)
|
||||
z3.Mul(z3, z3)
|
||||
z3.Sub(z3, z1z1)
|
||||
if z3.Sign() == -1 {
|
||||
z3.Add(z3, BitCurve.P)
|
||||
}
|
||||
z3.Sub(z3, z2z2)
|
||||
if z3.Sign() == -1 {
|
||||
z3.Add(z3, BitCurve.P)
|
||||
}
|
||||
z3.Mul(z3, h)
|
||||
z3.Mod(z3, BitCurve.P)
|
||||
|
||||
return x3, y3, z3
|
||||
}
|
||||
|
||||
// Double returns 2*(x,y)
|
||||
func (BitCurve *BitCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
|
||||
z1 := new(big.Int).SetInt64(1)
|
||||
return BitCurve.affineFromJacobian(BitCurve.doubleJacobian(x1, y1, z1))
|
||||
}
|
||||
|
||||
// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and
|
||||
// returns its double, also in Jacobian form.
|
||||
func (BitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
|
||||
|
||||
a := new(big.Int).Mul(x, x) //X1²
|
||||
b := new(big.Int).Mul(y, y) //Y1²
|
||||
c := new(big.Int).Mul(b, b) //B²
|
||||
|
||||
d := new(big.Int).Add(x, b) //X1+B
|
||||
d.Mul(d, d) //(X1+B)²
|
||||
d.Sub(d, a) //(X1+B)²-A
|
||||
d.Sub(d, c) //(X1+B)²-A-C
|
||||
d.Mul(d, big.NewInt(2)) //2*((X1+B)²-A-C)
|
||||
|
||||
e := new(big.Int).Mul(big.NewInt(3), a) //3*A
|
||||
f := new(big.Int).Mul(e, e) //E²
|
||||
|
||||
x3 := new(big.Int).Mul(big.NewInt(2), d) //2*D
|
||||
x3.Sub(f, x3) //F-2*D
|
||||
x3.Mod(x3, BitCurve.P)
|
||||
|
||||
y3 := new(big.Int).Sub(d, x3) //D-X3
|
||||
y3.Mul(e, y3) //E*(D-X3)
|
||||
y3.Sub(y3, new(big.Int).Mul(big.NewInt(8), c)) //E*(D-X3)-8*C
|
||||
y3.Mod(y3, BitCurve.P)
|
||||
|
||||
z3 := new(big.Int).Mul(y, z) //Y1*Z1
|
||||
z3.Mul(big.NewInt(2), z3) //3*Y1*Z1
|
||||
z3.Mod(z3, BitCurve.P)
|
||||
|
||||
return x3, y3, z3
|
||||
}
|
||||
|
||||
// ScalarBaseMult returns k*G, where G is the base point of the group and k is
|
||||
// an integer in big-endian form.
|
||||
func (BitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
|
||||
return BitCurve.ScalarMult(BitCurve.Gx, BitCurve.Gy, k)
|
||||
}
|
||||
|
||||
// Marshal converts a point into the form specified in section 4.3.6 of ANSI
|
||||
// X9.62.
|
||||
func (BitCurve *BitCurve) Marshal(x, y *big.Int) []byte {
|
||||
byteLen := (BitCurve.BitSize + 7) >> 3
|
||||
ret := make([]byte, 1+2*byteLen)
|
||||
ret[0] = 4 // uncompressed point flag
|
||||
readBits(x, ret[1:1+byteLen])
|
||||
readBits(y, ret[1+byteLen:])
|
||||
return ret
|
||||
}
|
||||
|
||||
// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On
|
||||
// error, x = nil.
|
||||
func (BitCurve *BitCurve) Unmarshal(data []byte) (x, y *big.Int) {
|
||||
byteLen := (BitCurve.BitSize + 7) >> 3
|
||||
if len(data) != 1+2*byteLen {
|
||||
return
|
||||
}
|
||||
if data[0] != 4 { // uncompressed form
|
||||
return
|
||||
}
|
||||
x = new(big.Int).SetBytes(data[1 : 1+byteLen])
|
||||
y = new(big.Int).SetBytes(data[1+byteLen:])
|
||||
return
|
||||
}
|
||||
|
||||
var theCurve = new(BitCurve)
|
||||
|
||||
func init() {
|
||||
// See SEC 2 section 2.7.1
|
||||
// curve parameters taken from:
|
||||
// http://www.secg.org/sec2-v2.pdf
|
||||
theCurve.P, _ = new(big.Int).SetString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 0)
|
||||
theCurve.N, _ = new(big.Int).SetString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 0)
|
||||
theCurve.B, _ = new(big.Int).SetString("0x0000000000000000000000000000000000000000000000000000000000000007", 0)
|
||||
theCurve.Gx, _ = new(big.Int).SetString("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 0)
|
||||
theCurve.Gy, _ = new(big.Int).SetString("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 0)
|
||||
theCurve.BitSize = 256
|
||||
}
|
||||
|
||||
// S256 returns a BitCurve which implements secp256k1.
|
||||
func S256() *BitCurve {
|
||||
return theCurve
|
||||
}
|
||||
21
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/dummy.go
generated
vendored
Normal file
21
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/dummy.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
//go:build dummy
|
||||
// +build dummy
|
||||
|
||||
// This file is part of a workaround for `go mod vendor` which won't vendor
|
||||
// C files if there's no Go file in the same directory.
|
||||
// This would prevent the crypto/secp256k1/libsecp256k1/include/secp256k1.h file to be vendored.
|
||||
//
|
||||
// This Go file imports the c directory where there is another dummy.go file which
|
||||
// is the second part of this workaround.
|
||||
//
|
||||
// These two files combined make it so `go mod vendor` behaves correctly.
|
||||
//
|
||||
// See this issue for reference: https://github.com/golang/go/issues/26366
|
||||
|
||||
package secp256k1
|
||||
|
||||
import (
|
||||
_ "github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include"
|
||||
_ "github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src"
|
||||
_ "github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery"
|
||||
)
|
||||
130
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/ext.h
generated
vendored
Normal file
130
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/ext.h
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
// secp256k1_context_create_sign_verify creates a context for signing and signature verification.
|
||||
static secp256k1_context* secp256k1_context_create_sign_verify() {
|
||||
return secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
}
|
||||
|
||||
// secp256k1_ext_ecdsa_recover recovers the public key of an encoded compact signature.
|
||||
//
|
||||
// Returns: 1: recovery was successful
|
||||
// 0: recovery was not successful
|
||||
// Args: ctx: pointer to a context object (cannot be NULL)
|
||||
// Out: pubkey_out: the serialized 65-byte public key of the signer (cannot be NULL)
|
||||
// In: sigdata: pointer to a 65-byte signature with the recovery id at the end (cannot be NULL)
|
||||
// msgdata: pointer to a 32-byte message (cannot be NULL)
|
||||
static int secp256k1_ext_ecdsa_recover(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *pubkey_out,
|
||||
const unsigned char *sigdata,
|
||||
const unsigned char *msgdata
|
||||
) {
|
||||
secp256k1_ecdsa_recoverable_signature sig;
|
||||
secp256k1_pubkey pubkey;
|
||||
|
||||
if (!secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &sig, sigdata, (int)sigdata[64])) {
|
||||
return 0;
|
||||
}
|
||||
if (!secp256k1_ecdsa_recover(ctx, &pubkey, &sig, msgdata)) {
|
||||
return 0;
|
||||
}
|
||||
size_t outputlen = 65;
|
||||
return secp256k1_ec_pubkey_serialize(ctx, pubkey_out, &outputlen, &pubkey, SECP256K1_EC_UNCOMPRESSED);
|
||||
}
|
||||
|
||||
// secp256k1_ext_ecdsa_verify verifies an encoded compact signature.
|
||||
//
|
||||
// Returns: 1: signature is valid
|
||||
// 0: signature is invalid
|
||||
// Args: ctx: pointer to a context object (cannot be NULL)
|
||||
// In: sigdata: pointer to a 64-byte signature (cannot be NULL)
|
||||
// msgdata: pointer to a 32-byte message (cannot be NULL)
|
||||
// pubkeydata: pointer to public key data (cannot be NULL)
|
||||
// pubkeylen: length of pubkeydata
|
||||
static int secp256k1_ext_ecdsa_verify(
|
||||
const secp256k1_context* ctx,
|
||||
const unsigned char *sigdata,
|
||||
const unsigned char *msgdata,
|
||||
const unsigned char *pubkeydata,
|
||||
size_t pubkeylen
|
||||
) {
|
||||
secp256k1_ecdsa_signature sig;
|
||||
secp256k1_pubkey pubkey;
|
||||
|
||||
if (!secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sigdata)) {
|
||||
return 0;
|
||||
}
|
||||
if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeydata, pubkeylen)) {
|
||||
return 0;
|
||||
}
|
||||
return secp256k1_ecdsa_verify(ctx, &sig, msgdata, &pubkey);
|
||||
}
|
||||
|
||||
// secp256k1_ext_reencode_pubkey decodes then encodes a public key. It can be used to
|
||||
// convert between public key formats. The input/output formats are chosen depending on the
|
||||
// length of the input/output buffers.
|
||||
//
|
||||
// Returns: 1: conversion successful
|
||||
// 0: conversion unsuccessful
|
||||
// Args: ctx: pointer to a context object (cannot be NULL)
|
||||
// Out: out: output buffer that will contain the reencoded key (cannot be NULL)
|
||||
// In: outlen: length of out (33 for compressed keys, 65 for uncompressed keys)
|
||||
// pubkeydata: the input public key (cannot be NULL)
|
||||
// pubkeylen: length of pubkeydata
|
||||
static int secp256k1_ext_reencode_pubkey(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *out,
|
||||
size_t outlen,
|
||||
const unsigned char *pubkeydata,
|
||||
size_t pubkeylen
|
||||
) {
|
||||
secp256k1_pubkey pubkey;
|
||||
|
||||
if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeydata, pubkeylen)) {
|
||||
return 0;
|
||||
}
|
||||
unsigned int flag = (outlen == 33) ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED;
|
||||
return secp256k1_ec_pubkey_serialize(ctx, out, &outlen, &pubkey, flag);
|
||||
}
|
||||
|
||||
// secp256k1_ext_scalar_mul multiplies a point by a scalar in constant time.
|
||||
//
|
||||
// Returns: 1: multiplication was successful
|
||||
// 0: scalar was invalid (zero or overflow)
|
||||
// Args: ctx: pointer to a context object (cannot be NULL)
|
||||
// Out: point: the multiplied point (usually secret)
|
||||
// In: point: pointer to a 64-byte public point,
|
||||
// encoded as two 256bit big-endian numbers.
|
||||
// scalar: a 32-byte scalar with which to multiply the point
|
||||
int secp256k1_ext_scalar_mul(const secp256k1_context* ctx, unsigned char *point, const unsigned char *scalar) {
|
||||
int ret = 0;
|
||||
int overflow = 0;
|
||||
secp256k1_fe feX, feY;
|
||||
secp256k1_gej res;
|
||||
secp256k1_ge ge;
|
||||
secp256k1_scalar s;
|
||||
ARG_CHECK(point != NULL);
|
||||
ARG_CHECK(scalar != NULL);
|
||||
(void)ctx;
|
||||
|
||||
secp256k1_fe_set_b32(&feX, point);
|
||||
secp256k1_fe_set_b32(&feY, point+32);
|
||||
secp256k1_ge_set_xy(&ge, &feX, &feY);
|
||||
secp256k1_scalar_set_b32(&s, scalar, &overflow);
|
||||
if (overflow || secp256k1_scalar_is_zero(&s)) {
|
||||
ret = 0;
|
||||
} else {
|
||||
secp256k1_ecmult_const(&res, &ge, &s);
|
||||
secp256k1_ge_set_gej(&ge, &res);
|
||||
/* Note: can't use secp256k1_pubkey_save here because it is not constant time. */
|
||||
secp256k1_fe_normalize(&ge.x);
|
||||
secp256k1_fe_normalize(&ge.y);
|
||||
secp256k1_fe_get_b32(point, &ge.x);
|
||||
secp256k1_fe_get_b32(point+32, &ge.y);
|
||||
ret = 1;
|
||||
}
|
||||
secp256k1_scalar_clear(&s);
|
||||
return ret;
|
||||
}
|
||||
19
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/COPYING
generated
vendored
Normal file
19
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/COPYING
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2013 Pieter Wuille
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
8
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/dummy.go
generated
vendored
Normal file
8
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/dummy.go
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
//go:build dummy
|
||||
// +build dummy
|
||||
|
||||
// Package c contains only a C file.
|
||||
//
|
||||
// This Go file is part of a workaround for `go mod vendor`.
|
||||
// Please see the file crypto/secp256k1/dummy.go for more information.
|
||||
package include
|
||||
577
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1.h
generated
vendored
Normal file
577
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1.h
generated
vendored
Normal file
@@ -0,0 +1,577 @@
|
||||
#ifndef _SECP256K1_
|
||||
# define _SECP256K1_
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* These rules specify the order of arguments in API calls:
|
||||
*
|
||||
* 1. Context pointers go first, followed by output arguments, combined
|
||||
* output/input arguments, and finally input-only arguments.
|
||||
* 2. Array lengths always immediately the follow the argument whose length
|
||||
* they describe, even if this violates rule 1.
|
||||
* 3. Within the OUT/OUTIN/IN groups, pointers to data that is typically generated
|
||||
* later go first. This means: signatures, public nonces, private nonces,
|
||||
* messages, public keys, secret keys, tweaks.
|
||||
* 4. Arguments that are not data pointers go last, from more complex to less
|
||||
* complex: function pointers, algorithm names, messages, void pointers,
|
||||
* counts, flags, booleans.
|
||||
* 5. Opaque data pointers follow the function pointer they are to be passed to.
|
||||
*/
|
||||
|
||||
/** Opaque data structure that holds context information (precomputed tables etc.).
|
||||
*
|
||||
* The purpose of context structures is to cache large precomputed data tables
|
||||
* that are expensive to construct, and also to maintain the randomization data
|
||||
* for blinding.
|
||||
*
|
||||
* Do not create a new context object for each operation, as construction is
|
||||
* far slower than all other API calls (~100 times slower than an ECDSA
|
||||
* verification).
|
||||
*
|
||||
* A constructed context can safely be used from multiple threads
|
||||
* simultaneously, but API call that take a non-const pointer to a context
|
||||
* need exclusive access to it. In particular this is the case for
|
||||
* secp256k1_context_destroy and secp256k1_context_randomize.
|
||||
*
|
||||
* Regarding randomization, either do it once at creation time (in which case
|
||||
* you do not need any locking for the other calls), or use a read-write lock.
|
||||
*/
|
||||
typedef struct secp256k1_context_struct secp256k1_context;
|
||||
|
||||
/** Opaque data structure that holds a parsed and valid public key.
|
||||
*
|
||||
* The exact representation of data inside is implementation defined and not
|
||||
* guaranteed to be portable between different platforms or versions. It is
|
||||
* however guaranteed to be 64 bytes in size, and can be safely copied/moved.
|
||||
* If you need to convert to a format suitable for storage, transmission, or
|
||||
* comparison, use secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char data[64];
|
||||
} secp256k1_pubkey;
|
||||
|
||||
/** Opaque data structured that holds a parsed ECDSA signature.
|
||||
*
|
||||
* The exact representation of data inside is implementation defined and not
|
||||
* guaranteed to be portable between different platforms or versions. It is
|
||||
* however guaranteed to be 64 bytes in size, and can be safely copied/moved.
|
||||
* If you need to convert to a format suitable for storage, transmission, or
|
||||
* comparison, use the secp256k1_ecdsa_signature_serialize_* and
|
||||
* secp256k1_ecdsa_signature_serialize_* functions.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char data[64];
|
||||
} secp256k1_ecdsa_signature;
|
||||
|
||||
/** A pointer to a function to deterministically generate a nonce.
|
||||
*
|
||||
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail.
|
||||
* Out: nonce32: pointer to a 32-byte array to be filled by the function.
|
||||
* In: msg32: the 32-byte message hash being verified (will not be NULL)
|
||||
* key32: pointer to a 32-byte secret key (will not be NULL)
|
||||
* algo16: pointer to a 16-byte array describing the signature
|
||||
* algorithm (will be NULL for ECDSA for compatibility).
|
||||
* data: Arbitrary data pointer that is passed through.
|
||||
* attempt: how many iterations we have tried to find a nonce.
|
||||
* This will almost always be 0, but different attempt values
|
||||
* are required to result in a different nonce.
|
||||
*
|
||||
* Except for test cases, this function should compute some cryptographic hash of
|
||||
* the message, the algorithm, the key and the attempt.
|
||||
*/
|
||||
typedef int (*secp256k1_nonce_function)(
|
||||
unsigned char *nonce32,
|
||||
const unsigned char *msg32,
|
||||
const unsigned char *key32,
|
||||
const unsigned char *algo16,
|
||||
void *data,
|
||||
unsigned int attempt
|
||||
);
|
||||
|
||||
# if !defined(SECP256K1_GNUC_PREREQ)
|
||||
# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
|
||||
# define SECP256K1_GNUC_PREREQ(_maj,_min) \
|
||||
((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
|
||||
# else
|
||||
# define SECP256K1_GNUC_PREREQ(_maj,_min) 0
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
|
||||
# if SECP256K1_GNUC_PREREQ(2,7)
|
||||
# define SECP256K1_INLINE __inline__
|
||||
# elif (defined(_MSC_VER))
|
||||
# define SECP256K1_INLINE __inline
|
||||
# else
|
||||
# define SECP256K1_INLINE
|
||||
# endif
|
||||
# else
|
||||
# define SECP256K1_INLINE inline
|
||||
# endif
|
||||
|
||||
#ifndef SECP256K1_API
|
||||
# if defined(_WIN32)
|
||||
# ifdef SECP256K1_BUILD
|
||||
# define SECP256K1_API __declspec(dllexport)
|
||||
# else
|
||||
# define SECP256K1_API
|
||||
# endif
|
||||
# elif defined(__GNUC__) && defined(SECP256K1_BUILD)
|
||||
# define SECP256K1_API __attribute__ ((visibility ("default")))
|
||||
# else
|
||||
# define SECP256K1_API
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/**Warning attributes
|
||||
* NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out
|
||||
* some paranoid null checks. */
|
||||
# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4)
|
||||
# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
|
||||
# else
|
||||
# define SECP256K1_WARN_UNUSED_RESULT
|
||||
# endif
|
||||
# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4)
|
||||
# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x)))
|
||||
# else
|
||||
# define SECP256K1_ARG_NONNULL(_x)
|
||||
# endif
|
||||
|
||||
/** All flags' lower 8 bits indicate what they're for. Do not use directly. */
|
||||
#define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1)
|
||||
#define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0)
|
||||
#define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1)
|
||||
/** The higher bits contain the actual data. Do not use directly. */
|
||||
#define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8)
|
||||
#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9)
|
||||
#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8)
|
||||
|
||||
/** Flags to pass to secp256k1_context_create. */
|
||||
#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY)
|
||||
#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN)
|
||||
#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT)
|
||||
|
||||
/** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */
|
||||
#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION)
|
||||
#define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION)
|
||||
|
||||
/** Create a secp256k1 context object.
|
||||
*
|
||||
* Returns: a newly created context object.
|
||||
* In: flags: which parts of the context to initialize.
|
||||
*/
|
||||
SECP256K1_API secp256k1_context* secp256k1_context_create(
|
||||
unsigned int flags
|
||||
) SECP256K1_WARN_UNUSED_RESULT;
|
||||
|
||||
/** Copies a secp256k1 context object.
|
||||
*
|
||||
* Returns: a newly created context object.
|
||||
* Args: ctx: an existing context to copy (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API secp256k1_context* secp256k1_context_clone(
|
||||
const secp256k1_context* ctx
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT;
|
||||
|
||||
/** Destroy a secp256k1 context object.
|
||||
*
|
||||
* The context pointer may not be used afterwards.
|
||||
* Args: ctx: an existing context to destroy (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API void secp256k1_context_destroy(
|
||||
secp256k1_context* ctx
|
||||
);
|
||||
|
||||
/** Set a callback function to be called when an illegal argument is passed to
|
||||
* an API call. It will only trigger for violations that are mentioned
|
||||
* explicitly in the header.
|
||||
*
|
||||
* The philosophy is that these shouldn't be dealt with through a
|
||||
* specific return value, as calling code should not have branches to deal with
|
||||
* the case that this code itself is broken.
|
||||
*
|
||||
* On the other hand, during debug stage, one would want to be informed about
|
||||
* such mistakes, and the default (crashing) may be inadvisable.
|
||||
* When this callback is triggered, the API function called is guaranteed not
|
||||
* to cause a crash, though its return value and output arguments are
|
||||
* undefined.
|
||||
*
|
||||
* Args: ctx: an existing context object (cannot be NULL)
|
||||
* In: fun: a pointer to a function to call when an illegal argument is
|
||||
* passed to the API, taking a message and an opaque pointer
|
||||
* (NULL restores a default handler that calls abort).
|
||||
* data: the opaque pointer to pass to fun above.
|
||||
*/
|
||||
SECP256K1_API void secp256k1_context_set_illegal_callback(
|
||||
secp256k1_context* ctx,
|
||||
void (*fun)(const char* message, void* data),
|
||||
const void* data
|
||||
) SECP256K1_ARG_NONNULL(1);
|
||||
|
||||
/** Set a callback function to be called when an internal consistency check
|
||||
* fails. The default is crashing.
|
||||
*
|
||||
* This can only trigger in case of a hardware failure, miscompilation,
|
||||
* memory corruption, serious bug in the library, or other error would can
|
||||
* otherwise result in undefined behaviour. It will not trigger due to mere
|
||||
* incorrect usage of the API (see secp256k1_context_set_illegal_callback
|
||||
* for that). After this callback returns, anything may happen, including
|
||||
* crashing.
|
||||
*
|
||||
* Args: ctx: an existing context object (cannot be NULL)
|
||||
* In: fun: a pointer to a function to call when an internal error occurs,
|
||||
* taking a message and an opaque pointer (NULL restores a default
|
||||
* handler that calls abort).
|
||||
* data: the opaque pointer to pass to fun above.
|
||||
*/
|
||||
SECP256K1_API void secp256k1_context_set_error_callback(
|
||||
secp256k1_context* ctx,
|
||||
void (*fun)(const char* message, void* data),
|
||||
const void* data
|
||||
) SECP256K1_ARG_NONNULL(1);
|
||||
|
||||
/** Parse a variable-length public key into the pubkey object.
|
||||
*
|
||||
* Returns: 1 if the public key was fully valid.
|
||||
* 0 if the public key could not be parsed or is invalid.
|
||||
* Args: ctx: a secp256k1 context object.
|
||||
* Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a
|
||||
* parsed version of input. If not, its value is undefined.
|
||||
* In: input: pointer to a serialized public key
|
||||
* inputlen: length of the array pointed to by input
|
||||
*
|
||||
* This function supports parsing compressed (33 bytes, header byte 0x02 or
|
||||
* 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header
|
||||
* byte 0x06 or 0x07) format public keys.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey* pubkey,
|
||||
const unsigned char *input,
|
||||
size_t inputlen
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Serialize a pubkey object into a serialized byte sequence.
|
||||
*
|
||||
* Returns: 1 always.
|
||||
* Args: ctx: a secp256k1 context object.
|
||||
* Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if
|
||||
* compressed==1) byte array to place the serialized key
|
||||
* in.
|
||||
* In/Out: outputlen: a pointer to an integer which is initially set to the
|
||||
* size of output, and is overwritten with the written
|
||||
* size.
|
||||
* In: pubkey: a pointer to a secp256k1_pubkey containing an
|
||||
* initialized public key.
|
||||
* flags: SECP256K1_EC_COMPRESSED if serialization should be in
|
||||
* compressed format, otherwise SECP256K1_EC_UNCOMPRESSED.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ec_pubkey_serialize(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *output,
|
||||
size_t *outputlen,
|
||||
const secp256k1_pubkey* pubkey,
|
||||
unsigned int flags
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Parse an ECDSA signature in compact (64 bytes) format.
|
||||
*
|
||||
* Returns: 1 when the signature could be parsed, 0 otherwise.
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: sig: a pointer to a signature object
|
||||
* In: input64: a pointer to the 64-byte array to parse
|
||||
*
|
||||
* The signature must consist of a 32-byte big endian R value, followed by a
|
||||
* 32-byte big endian S value. If R or S fall outside of [0..order-1], the
|
||||
* encoding is invalid. R and S with value 0 are allowed in the encoding.
|
||||
*
|
||||
* After the call, sig will always be initialized. If parsing failed or R or
|
||||
* S are zero, the resulting sig value is guaranteed to fail validation for any
|
||||
* message and public key.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_signature_parse_compact(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_signature* sig,
|
||||
const unsigned char *input64
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Parse a DER ECDSA signature.
|
||||
*
|
||||
* Returns: 1 when the signature could be parsed, 0 otherwise.
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: sig: a pointer to a signature object
|
||||
* In: input: a pointer to the signature to be parsed
|
||||
* inputlen: the length of the array pointed to be input
|
||||
*
|
||||
* This function will accept any valid DER encoded signature, even if the
|
||||
* encoded numbers are out of range.
|
||||
*
|
||||
* After the call, sig will always be initialized. If parsing failed or the
|
||||
* encoded numbers are out of range, signature validation with it is
|
||||
* guaranteed to fail for every message and public key.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_signature_parse_der(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_signature* sig,
|
||||
const unsigned char *input,
|
||||
size_t inputlen
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Serialize an ECDSA signature in DER format.
|
||||
*
|
||||
* Returns: 1 if enough space was available to serialize, 0 otherwise
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: output: a pointer to an array to store the DER serialization
|
||||
* In/Out: outputlen: a pointer to a length integer. Initially, this integer
|
||||
* should be set to the length of output. After the call
|
||||
* it will be set to the length of the serialization (even
|
||||
* if 0 was returned).
|
||||
* In: sig: a pointer to an initialized signature object
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_signature_serialize_der(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *output,
|
||||
size_t *outputlen,
|
||||
const secp256k1_ecdsa_signature* sig
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Serialize an ECDSA signature in compact (64 byte) format.
|
||||
*
|
||||
* Returns: 1
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: output64: a pointer to a 64-byte array to store the compact serialization
|
||||
* In: sig: a pointer to an initialized signature object
|
||||
*
|
||||
* See secp256k1_ecdsa_signature_parse_compact for details about the encoding.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *output64,
|
||||
const secp256k1_ecdsa_signature* sig
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Verify an ECDSA signature.
|
||||
*
|
||||
* Returns: 1: correct signature
|
||||
* 0: incorrect or unparseable signature
|
||||
* Args: ctx: a secp256k1 context object, initialized for verification.
|
||||
* In: sig: the signature being verified (cannot be NULL)
|
||||
* msg32: the 32-byte message hash being verified (cannot be NULL)
|
||||
* pubkey: pointer to an initialized public key to verify with (cannot be NULL)
|
||||
*
|
||||
* To avoid accepting malleable signatures, only ECDSA signatures in lower-S
|
||||
* form are accepted.
|
||||
*
|
||||
* If you need to accept ECDSA signatures from sources that do not obey this
|
||||
* rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to
|
||||
* validation, but be aware that doing so results in malleable signatures.
|
||||
*
|
||||
* For details, see the comments for that function.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
|
||||
const secp256k1_context* ctx,
|
||||
const secp256k1_ecdsa_signature *sig,
|
||||
const unsigned char *msg32,
|
||||
const secp256k1_pubkey *pubkey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Convert a signature to a normalized lower-S form.
|
||||
*
|
||||
* Returns: 1 if sigin was not normalized, 0 if it already was.
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: sigout: a pointer to a signature to fill with the normalized form,
|
||||
* or copy if the input was already normalized. (can be NULL if
|
||||
* you're only interested in whether the input was already
|
||||
* normalized).
|
||||
* In: sigin: a pointer to a signature to check/normalize (cannot be NULL,
|
||||
* can be identical to sigout)
|
||||
*
|
||||
* With ECDSA a third-party can forge a second distinct signature of the same
|
||||
* message, given a single initial signature, but without knowing the key. This
|
||||
* is done by negating the S value modulo the order of the curve, 'flipping'
|
||||
* the sign of the random point R which is not included in the signature.
|
||||
*
|
||||
* Forgery of the same message isn't universally problematic, but in systems
|
||||
* where message malleability or uniqueness of signatures is important this can
|
||||
* cause issues. This forgery can be blocked by all verifiers forcing signers
|
||||
* to use a normalized form.
|
||||
*
|
||||
* The lower-S form reduces the size of signatures slightly on average when
|
||||
* variable length encodings (such as DER) are used and is cheap to verify,
|
||||
* making it a good choice. Security of always using lower-S is assured because
|
||||
* anyone can trivially modify a signature after the fact to enforce this
|
||||
* property anyway.
|
||||
*
|
||||
* The lower S value is always between 0x1 and
|
||||
* 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
|
||||
* inclusive.
|
||||
*
|
||||
* No other forms of ECDSA malleability are known and none seem likely, but
|
||||
* there is no formal proof that ECDSA, even with this additional restriction,
|
||||
* is free of other malleability. Commonly used serialization schemes will also
|
||||
* accept various non-unique encodings, so care should be taken when this
|
||||
* property is required for an application.
|
||||
*
|
||||
* The secp256k1_ecdsa_sign function will by default create signatures in the
|
||||
* lower-S form, and secp256k1_ecdsa_verify will not accept others. In case
|
||||
* signatures come from a system that cannot enforce this property,
|
||||
* secp256k1_ecdsa_signature_normalize must be called before verification.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_signature_normalize(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_signature *sigout,
|
||||
const secp256k1_ecdsa_signature *sigin
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function.
|
||||
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
|
||||
* extra entropy.
|
||||
*/
|
||||
SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979;
|
||||
|
||||
/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */
|
||||
SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_default;
|
||||
|
||||
/** Create an ECDSA signature.
|
||||
*
|
||||
* Returns: 1: signature created
|
||||
* 0: the nonce generation function failed, or the private key was invalid.
|
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
|
||||
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
|
||||
* seckey: pointer to a 32-byte secret key (cannot be NULL)
|
||||
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
|
||||
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
|
||||
*
|
||||
* The created signature is always in lower-S form. See
|
||||
* secp256k1_ecdsa_signature_normalize for more details.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_sign(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_signature *sig,
|
||||
const unsigned char *msg32,
|
||||
const unsigned char *seckey,
|
||||
secp256k1_nonce_function noncefp,
|
||||
const void *ndata
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Verify an ECDSA secret key.
|
||||
*
|
||||
* Returns: 1: secret key is valid
|
||||
* 0: secret key is invalid
|
||||
* Args: ctx: pointer to a context object (cannot be NULL)
|
||||
* In: seckey: pointer to a 32-byte secret key (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
|
||||
const secp256k1_context* ctx,
|
||||
const unsigned char *seckey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
|
||||
|
||||
/** Compute the public key for a secret key.
|
||||
*
|
||||
* Returns: 1: secret was valid, public key stores
|
||||
* 0: secret was invalid, try again
|
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
* Out: pubkey: pointer to the created public key (cannot be NULL)
|
||||
* In: seckey: pointer to a 32-byte private key (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey *pubkey,
|
||||
const unsigned char *seckey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Tweak a private key by adding tweak to it.
|
||||
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
|
||||
* uniformly random 32-byte arrays, or if the resulting private key
|
||||
* would be invalid (only when the tweak is the complement of the
|
||||
* private key). 1 otherwise.
|
||||
* Args: ctx: pointer to a context object (cannot be NULL).
|
||||
* In/Out: seckey: pointer to a 32-byte private key.
|
||||
* In: tweak: pointer to a 32-byte tweak.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *seckey,
|
||||
const unsigned char *tweak
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Tweak a public key by adding tweak times the generator to it.
|
||||
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
|
||||
* uniformly random 32-byte arrays, or if the resulting public key
|
||||
* would be invalid (only when the tweak is the complement of the
|
||||
* corresponding private key). 1 otherwise.
|
||||
* Args: ctx: pointer to a context object initialized for validation
|
||||
* (cannot be NULL).
|
||||
* In/Out: pubkey: pointer to a public key object.
|
||||
* In: tweak: pointer to a 32-byte tweak.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey *pubkey,
|
||||
const unsigned char *tweak
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Tweak a private key by multiplying it by a tweak.
|
||||
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
|
||||
* uniformly random 32-byte arrays, or equal to zero. 1 otherwise.
|
||||
* Args: ctx: pointer to a context object (cannot be NULL).
|
||||
* In/Out: seckey: pointer to a 32-byte private key.
|
||||
* In: tweak: pointer to a 32-byte tweak.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *seckey,
|
||||
const unsigned char *tweak
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Tweak a public key by multiplying it by a tweak value.
|
||||
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
|
||||
* uniformly random 32-byte arrays, or equal to zero. 1 otherwise.
|
||||
* Args: ctx: pointer to a context object initialized for validation
|
||||
* (cannot be NULL).
|
||||
* In/Out: pubkey: pointer to a public key obkect.
|
||||
* In: tweak: pointer to a 32-byte tweak.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey *pubkey,
|
||||
const unsigned char *tweak
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Updates the context randomization.
|
||||
* Returns: 1: randomization successfully updated
|
||||
* 0: error
|
||||
* Args: ctx: pointer to a context object (cannot be NULL)
|
||||
* In: seed32: pointer to a 32-byte random seed (NULL resets to initial state)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
|
||||
secp256k1_context* ctx,
|
||||
const unsigned char *seed32
|
||||
) SECP256K1_ARG_NONNULL(1);
|
||||
|
||||
/** Add a number of public keys together.
|
||||
* Returns: 1: the sum of the public keys is valid.
|
||||
* 0: the sum of the public keys is not valid.
|
||||
* Args: ctx: pointer to a context object
|
||||
* Out: out: pointer to a public key object for placing the resulting public key
|
||||
* (cannot be NULL)
|
||||
* In: ins: pointer to array of pointers to public keys (cannot be NULL)
|
||||
* n: the number of public keys to add together (must be at least 1)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey *out,
|
||||
const secp256k1_pubkey * const * ins,
|
||||
size_t n
|
||||
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
31
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h
generated
vendored
Normal file
31
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef _SECP256K1_ECDH_
|
||||
# define _SECP256K1_ECDH_
|
||||
|
||||
# include "secp256k1.h"
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
/** Compute an EC Diffie-Hellman secret in constant time
|
||||
* Returns: 1: exponentiation was successful
|
||||
* 0: scalar was invalid (zero or overflow)
|
||||
* Args: ctx: pointer to a context object (cannot be NULL)
|
||||
* Out: result: a 32-byte array which will be populated by an ECDH
|
||||
* secret computed from the point and scalar
|
||||
* In: pubkey: a pointer to a secp256k1_pubkey containing an
|
||||
* initialized public key
|
||||
* privkey: a 32-byte scalar with which to multiply the point
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *result,
|
||||
const secp256k1_pubkey *pubkey,
|
||||
const unsigned char *privkey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
110
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h
generated
vendored
Normal file
110
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
#ifndef _SECP256K1_RECOVERY_
|
||||
# define _SECP256K1_RECOVERY_
|
||||
|
||||
# include "secp256k1.h"
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
/** Opaque data structured that holds a parsed ECDSA signature,
|
||||
* supporting pubkey recovery.
|
||||
*
|
||||
* The exact representation of data inside is implementation defined and not
|
||||
* guaranteed to be portable between different platforms or versions. It is
|
||||
* however guaranteed to be 65 bytes in size, and can be safely copied/moved.
|
||||
* If you need to convert to a format suitable for storage or transmission, use
|
||||
* the secp256k1_ecdsa_signature_serialize_* and
|
||||
* secp256k1_ecdsa_signature_parse_* functions.
|
||||
*
|
||||
* Furthermore, it is guaranteed that identical signatures (including their
|
||||
* recoverability) will have identical representation, so they can be
|
||||
* memcmp'ed.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char data[65];
|
||||
} secp256k1_ecdsa_recoverable_signature;
|
||||
|
||||
/** Parse a compact ECDSA signature (64 bytes + recovery id).
|
||||
*
|
||||
* Returns: 1 when the signature could be parsed, 0 otherwise
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: sig: a pointer to a signature object
|
||||
* In: input64: a pointer to a 64-byte compact signature
|
||||
* recid: the recovery id (0, 1, 2 or 3)
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_recoverable_signature* sig,
|
||||
const unsigned char *input64,
|
||||
int recid
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Convert a recoverable signature into a normal signature.
|
||||
*
|
||||
* Returns: 1
|
||||
* Out: sig: a pointer to a normal signature (cannot be NULL).
|
||||
* In: sigin: a pointer to a recoverable signature (cannot be NULL).
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_signature* sig,
|
||||
const secp256k1_ecdsa_recoverable_signature* sigin
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Serialize an ECDSA signature in compact format (64 bytes + recovery id).
|
||||
*
|
||||
* Returns: 1
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: output64: a pointer to a 64-byte array of the compact signature (cannot be NULL)
|
||||
* recid: a pointer to an integer to hold the recovery id (can be NULL).
|
||||
* In: sig: a pointer to an initialized signature object (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *output64,
|
||||
int *recid,
|
||||
const secp256k1_ecdsa_recoverable_signature* sig
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Create a recoverable ECDSA signature.
|
||||
*
|
||||
* Returns: 1: signature created
|
||||
* 0: the nonce generation function failed, or the private key was invalid.
|
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
|
||||
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
|
||||
* seckey: pointer to a 32-byte secret key (cannot be NULL)
|
||||
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
|
||||
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_sign_recoverable(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_recoverable_signature *sig,
|
||||
const unsigned char *msg32,
|
||||
const unsigned char *seckey,
|
||||
secp256k1_nonce_function noncefp,
|
||||
const void *ndata
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Recover an ECDSA public key from a signature.
|
||||
*
|
||||
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
|
||||
* 0: otherwise.
|
||||
* Args: ctx: pointer to a context object, initialized for verification (cannot be NULL)
|
||||
* Out: pubkey: pointer to the recovered public key (cannot be NULL)
|
||||
* In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL)
|
||||
* msg32: the 32-byte message hash assumed to be signed (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey *pubkey,
|
||||
const secp256k1_ecdsa_recoverable_signature *sig,
|
||||
const unsigned char *msg32
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
32
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/basic-config.h
generated
vendored
Normal file
32
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/basic-config.h
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_BASIC_CONFIG_
|
||||
#define _SECP256K1_BASIC_CONFIG_
|
||||
|
||||
#ifdef USE_BASIC_CONFIG
|
||||
|
||||
#undef USE_ASM_X86_64
|
||||
#undef USE_ENDOMORPHISM
|
||||
#undef USE_FIELD_10X26
|
||||
#undef USE_FIELD_5X52
|
||||
#undef USE_FIELD_INV_BUILTIN
|
||||
#undef USE_FIELD_INV_NUM
|
||||
#undef USE_NUM_GMP
|
||||
#undef USE_NUM_NONE
|
||||
#undef USE_SCALAR_4X64
|
||||
#undef USE_SCALAR_8X32
|
||||
#undef USE_SCALAR_INV_BUILTIN
|
||||
#undef USE_SCALAR_INV_NUM
|
||||
|
||||
#define USE_NUM_NONE 1
|
||||
#define USE_FIELD_INV_BUILTIN 1
|
||||
#define USE_SCALAR_INV_BUILTIN 1
|
||||
#define USE_FIELD_10X26 1
|
||||
#define USE_SCALAR_8X32 1
|
||||
|
||||
#endif // USE_BASIC_CONFIG
|
||||
#endif // _SECP256K1_BASIC_CONFIG_
|
||||
66
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench.h
generated
vendored
Normal file
66
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench.h
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_BENCH_H_
|
||||
#define _SECP256K1_BENCH_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "sys/time.h"
|
||||
|
||||
static double gettimedouble(void) {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_usec * 0.000001 + tv.tv_sec;
|
||||
}
|
||||
|
||||
void print_number(double x) {
|
||||
double y = x;
|
||||
int c = 0;
|
||||
if (y < 0.0) {
|
||||
y = -y;
|
||||
}
|
||||
while (y < 100.0) {
|
||||
y *= 10.0;
|
||||
c++;
|
||||
}
|
||||
printf("%.*f", c, x);
|
||||
}
|
||||
|
||||
void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) {
|
||||
int i;
|
||||
double min = HUGE_VAL;
|
||||
double sum = 0.0;
|
||||
double max = 0.0;
|
||||
for (i = 0; i < count; i++) {
|
||||
double begin, total;
|
||||
if (setup != NULL) {
|
||||
setup(data);
|
||||
}
|
||||
begin = gettimedouble();
|
||||
benchmark(data);
|
||||
total = gettimedouble() - begin;
|
||||
if (teardown != NULL) {
|
||||
teardown(data);
|
||||
}
|
||||
if (total < min) {
|
||||
min = total;
|
||||
}
|
||||
if (total > max) {
|
||||
max = total;
|
||||
}
|
||||
sum += total;
|
||||
}
|
||||
printf("%s: min ", name);
|
||||
print_number(min * 1000000.0 / iter);
|
||||
printf("us / avg ");
|
||||
print_number((sum / count) * 1000000.0 / iter);
|
||||
printf("us / max ");
|
||||
print_number(max * 1000000.0 / iter);
|
||||
printf("us\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
54
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c
generated
vendored
Normal file
54
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2015 Pieter Wuille, Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "include/secp256k1.h"
|
||||
#include "include/secp256k1_ecdh.h"
|
||||
#include "util.h"
|
||||
#include "bench.h"
|
||||
|
||||
typedef struct {
|
||||
secp256k1_context *ctx;
|
||||
secp256k1_pubkey point;
|
||||
unsigned char scalar[32];
|
||||
} bench_ecdh_t;
|
||||
|
||||
static void bench_ecdh_setup(void* arg) {
|
||||
int i;
|
||||
bench_ecdh_t *data = (bench_ecdh_t*)arg;
|
||||
const unsigned char point[] = {
|
||||
0x03,
|
||||
0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06,
|
||||
0xc2, 0x39, 0x5f, 0x94, 0x34, 0x87, 0x45, 0xfd,
|
||||
0x75, 0x7c, 0xe3, 0x0e, 0x4e, 0x8c, 0x90, 0xfb,
|
||||
0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f
|
||||
};
|
||||
|
||||
/* create a context with no capabilities */
|
||||
data->ctx = secp256k1_context_create(SECP256K1_FLAGS_TYPE_CONTEXT);
|
||||
for (i = 0; i < 32; i++) {
|
||||
data->scalar[i] = i + 1;
|
||||
}
|
||||
CHECK(secp256k1_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1);
|
||||
}
|
||||
|
||||
static void bench_ecdh(void* arg) {
|
||||
int i;
|
||||
unsigned char res[32];
|
||||
bench_ecdh_t *data = (bench_ecdh_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar) == 1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
bench_ecdh_t data;
|
||||
|
||||
run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, 20000);
|
||||
return 0;
|
||||
}
|
||||
382
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_internal.c
generated
vendored
Normal file
382
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_internal.c
generated
vendored
Normal file
@@ -0,0 +1,382 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014-2015 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
#include <stdio.h>
|
||||
|
||||
#include "include/secp256k1.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "hash_impl.h"
|
||||
#include "num_impl.h"
|
||||
#include "field_impl.h"
|
||||
#include "group_impl.h"
|
||||
#include "scalar_impl.h"
|
||||
#include "ecmult_const_impl.h"
|
||||
#include "ecmult_impl.h"
|
||||
#include "bench.h"
|
||||
#include "secp256k1.c"
|
||||
|
||||
typedef struct {
|
||||
secp256k1_scalar scalar_x, scalar_y;
|
||||
secp256k1_fe fe_x, fe_y;
|
||||
secp256k1_ge ge_x, ge_y;
|
||||
secp256k1_gej gej_x, gej_y;
|
||||
unsigned char data[64];
|
||||
int wnaf[256];
|
||||
} bench_inv_t;
|
||||
|
||||
void bench_setup(void* arg) {
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
static const unsigned char init_x[32] = {
|
||||
0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13,
|
||||
0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35,
|
||||
0x3b, 0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59,
|
||||
0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83
|
||||
};
|
||||
|
||||
static const unsigned char init_y[32] = {
|
||||
0x82, 0x83, 0x85, 0x87, 0x8b, 0x8d, 0x81, 0x83,
|
||||
0x97, 0xad, 0xaf, 0xb5, 0xb9, 0xbb, 0xbf, 0xc5,
|
||||
0xdb, 0xdd, 0xe3, 0xe7, 0xe9, 0xef, 0xf3, 0xf9,
|
||||
0x11, 0x15, 0x17, 0x1b, 0x1d, 0xb1, 0xbf, 0xd3
|
||||
};
|
||||
|
||||
secp256k1_scalar_set_b32(&data->scalar_x, init_x, NULL);
|
||||
secp256k1_scalar_set_b32(&data->scalar_y, init_y, NULL);
|
||||
secp256k1_fe_set_b32(&data->fe_x, init_x);
|
||||
secp256k1_fe_set_b32(&data->fe_y, init_y);
|
||||
CHECK(secp256k1_ge_set_xo_var(&data->ge_x, &data->fe_x, 0));
|
||||
CHECK(secp256k1_ge_set_xo_var(&data->ge_y, &data->fe_y, 1));
|
||||
secp256k1_gej_set_ge(&data->gej_x, &data->ge_x);
|
||||
secp256k1_gej_set_ge(&data->gej_y, &data->ge_y);
|
||||
memcpy(data->data, init_x, 32);
|
||||
memcpy(data->data + 32, init_y, 32);
|
||||
}
|
||||
|
||||
void bench_scalar_add(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 2000000; i++) {
|
||||
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_scalar_negate(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 2000000; i++) {
|
||||
secp256k1_scalar_negate(&data->scalar_x, &data->scalar_x);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_scalar_sqr(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 200000; i++) {
|
||||
secp256k1_scalar_sqr(&data->scalar_x, &data->scalar_x);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_scalar_mul(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 200000; i++) {
|
||||
secp256k1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
void bench_scalar_split(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_scalar l, r;
|
||||
secp256k1_scalar_split_lambda(&l, &r, &data->scalar_x);
|
||||
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void bench_scalar_inverse(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 2000; i++) {
|
||||
secp256k1_scalar_inverse(&data->scalar_x, &data->scalar_x);
|
||||
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_scalar_inverse_var(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 2000; i++) {
|
||||
secp256k1_scalar_inverse_var(&data->scalar_x, &data->scalar_x);
|
||||
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_field_normalize(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 2000000; i++) {
|
||||
secp256k1_fe_normalize(&data->fe_x);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_field_normalize_weak(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 2000000; i++) {
|
||||
secp256k1_fe_normalize_weak(&data->fe_x);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_field_mul(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 200000; i++) {
|
||||
secp256k1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_field_sqr(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 200000; i++) {
|
||||
secp256k1_fe_sqr(&data->fe_x, &data->fe_x);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_field_inverse(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_fe_inv(&data->fe_x, &data->fe_x);
|
||||
secp256k1_fe_add(&data->fe_x, &data->fe_y);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_field_inverse_var(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_fe_inv_var(&data->fe_x, &data->fe_x);
|
||||
secp256k1_fe_add(&data->fe_x, &data->fe_y);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_field_sqrt(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_fe_sqrt(&data->fe_x, &data->fe_x);
|
||||
secp256k1_fe_add(&data->fe_x, &data->fe_y);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_group_double_var(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 200000; i++) {
|
||||
secp256k1_gej_double_var(&data->gej_x, &data->gej_x, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_group_add_var(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 200000; i++) {
|
||||
secp256k1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_group_add_affine(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 200000; i++) {
|
||||
secp256k1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_group_add_affine_var(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 200000; i++) {
|
||||
secp256k1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_group_jacobi_var(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_gej_has_quad_y_var(&data->gej_x);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_ecmult_wnaf(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A);
|
||||
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_wnaf_const(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A);
|
||||
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void bench_sha256(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
secp256k1_sha256_t sha;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_sha256_initialize(&sha);
|
||||
secp256k1_sha256_write(&sha, data->data, 32);
|
||||
secp256k1_sha256_finalize(&sha, data->data);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_hmac_sha256(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
secp256k1_hmac_sha256_t hmac;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_hmac_sha256_initialize(&hmac, data->data, 32);
|
||||
secp256k1_hmac_sha256_write(&hmac, data->data, 32);
|
||||
secp256k1_hmac_sha256_finalize(&hmac, data->data);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_rfc6979_hmac_sha256(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
secp256k1_rfc6979_hmac_sha256_t rng;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64);
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_context_verify(void* arg) {
|
||||
int i;
|
||||
(void)arg;
|
||||
for (i = 0; i < 20; i++) {
|
||||
secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY));
|
||||
}
|
||||
}
|
||||
|
||||
void bench_context_sign(void* arg) {
|
||||
int i;
|
||||
(void)arg;
|
||||
for (i = 0; i < 200; i++) {
|
||||
secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_SIGN));
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef USE_NUM_NONE
|
||||
void bench_num_jacobi(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
secp256k1_num nx, norder;
|
||||
|
||||
secp256k1_scalar_get_num(&nx, &data->scalar_x);
|
||||
secp256k1_scalar_order_get_num(&norder);
|
||||
secp256k1_scalar_get_num(&norder, &data->scalar_y);
|
||||
|
||||
for (i = 0; i < 200000; i++) {
|
||||
secp256k1_num_jacobi(&nx, &norder);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int have_flag(int argc, char** argv, char *flag) {
|
||||
char** argm = argv + argc;
|
||||
argv++;
|
||||
if (argv == argm) {
|
||||
return 1;
|
||||
}
|
||||
while (argv != NULL && argv != argm) {
|
||||
if (strcmp(*argv, flag) == 0) {
|
||||
return 1;
|
||||
}
|
||||
argv++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
bench_inv_t data;
|
||||
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, 2000000);
|
||||
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, 2000000);
|
||||
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, 200000);
|
||||
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "mul")) run_benchmark("scalar_mul", bench_scalar_mul, bench_setup, NULL, &data, 10, 200000);
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "split")) run_benchmark("scalar_split", bench_scalar_split, bench_setup, NULL, &data, 10, 20000);
|
||||
#endif
|
||||
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse", bench_scalar_inverse, bench_setup, NULL, &data, 10, 2000);
|
||||
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse_var", bench_scalar_inverse_var, bench_setup, NULL, &data, 10, 2000);
|
||||
|
||||
if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize", bench_field_normalize, bench_setup, NULL, &data, 10, 2000000);
|
||||
if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_weak", bench_field_normalize_weak, bench_setup, NULL, &data, 10, 2000000);
|
||||
if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, 200000);
|
||||
if (have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, 200000);
|
||||
if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, 20000);
|
||||
if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse_var", bench_field_inverse_var, bench_setup, NULL, &data, 10, 20000);
|
||||
if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, 20000);
|
||||
|
||||
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_double_var", bench_group_double_var, bench_setup, NULL, &data, 10, 200000);
|
||||
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, 200000);
|
||||
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, 200000);
|
||||
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, 200000);
|
||||
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "jacobi")) run_benchmark("group_jacobi_var", bench_group_jacobi_var, bench_setup, NULL, &data, 10, 20000);
|
||||
|
||||
if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, 20000);
|
||||
if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, 20000);
|
||||
|
||||
if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "sha256")) run_benchmark("hash_sha256", bench_sha256, bench_setup, NULL, &data, 10, 20000);
|
||||
if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "hmac")) run_benchmark("hash_hmac_sha256", bench_hmac_sha256, bench_setup, NULL, &data, 10, 20000);
|
||||
if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "rng6979")) run_benchmark("hash_rfc6979_hmac_sha256", bench_rfc6979_hmac_sha256, bench_setup, NULL, &data, 10, 20000);
|
||||
|
||||
if (have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 20);
|
||||
if (have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 200);
|
||||
|
||||
#ifndef USE_NUM_NONE
|
||||
if (have_flag(argc, argv, "num") || have_flag(argc, argv, "jacobi")) run_benchmark("num_jacobi", bench_num_jacobi, bench_setup, NULL, &data, 10, 200000);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
60
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_recover.c
generated
vendored
Normal file
60
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_recover.c
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014-2015 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#include "include/secp256k1.h"
|
||||
#include "include/secp256k1_recovery.h"
|
||||
#include "util.h"
|
||||
#include "bench.h"
|
||||
|
||||
typedef struct {
|
||||
secp256k1_context *ctx;
|
||||
unsigned char msg[32];
|
||||
unsigned char sig[64];
|
||||
} bench_recover_t;
|
||||
|
||||
void bench_recover(void* arg) {
|
||||
int i;
|
||||
bench_recover_t *data = (bench_recover_t*)arg;
|
||||
secp256k1_pubkey pubkey;
|
||||
unsigned char pubkeyc[33];
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
int j;
|
||||
size_t pubkeylen = 33;
|
||||
secp256k1_ecdsa_recoverable_signature sig;
|
||||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(data->ctx, &sig, data->sig, i % 2));
|
||||
CHECK(secp256k1_ecdsa_recover(data->ctx, &pubkey, &sig, data->msg));
|
||||
CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED));
|
||||
for (j = 0; j < 32; j++) {
|
||||
data->sig[j + 32] = data->msg[j]; /* Move former message to S. */
|
||||
data->msg[j] = data->sig[j]; /* Move former R to message. */
|
||||
data->sig[j] = pubkeyc[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bench_recover_setup(void* arg) {
|
||||
int i;
|
||||
bench_recover_t *data = (bench_recover_t*)arg;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
data->msg[i] = 1 + i;
|
||||
}
|
||||
for (i = 0; i < 64; i++) {
|
||||
data->sig[i] = 65 + i;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
bench_recover_t data;
|
||||
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||
|
||||
run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, 20000);
|
||||
|
||||
secp256k1_context_destroy(data.ctx);
|
||||
return 0;
|
||||
}
|
||||
73
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c
generated
vendored
Normal file
73
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "include/secp256k1.h"
|
||||
#include "include/secp256k1_schnorr.h"
|
||||
#include "util.h"
|
||||
#include "bench.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned char key[32];
|
||||
unsigned char sig[64];
|
||||
unsigned char pubkey[33];
|
||||
size_t pubkeylen;
|
||||
} benchmark_schnorr_sig_t;
|
||||
|
||||
typedef struct {
|
||||
secp256k1_context *ctx;
|
||||
unsigned char msg[32];
|
||||
benchmark_schnorr_sig_t sigs[64];
|
||||
int numsigs;
|
||||
} benchmark_schnorr_verify_t;
|
||||
|
||||
static void benchmark_schnorr_init(void* arg) {
|
||||
int i, k;
|
||||
benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
data->msg[i] = 1 + i;
|
||||
}
|
||||
for (k = 0; k < data->numsigs; k++) {
|
||||
secp256k1_pubkey pubkey;
|
||||
for (i = 0; i < 32; i++) {
|
||||
data->sigs[k].key[i] = 33 + i + k;
|
||||
}
|
||||
secp256k1_schnorr_sign(data->ctx, data->sigs[k].sig, data->msg, data->sigs[k].key, NULL, NULL);
|
||||
data->sigs[k].pubkeylen = 33;
|
||||
CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->sigs[k].key));
|
||||
CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->sigs[k].pubkey, &data->sigs[k].pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED));
|
||||
}
|
||||
}
|
||||
|
||||
static void benchmark_schnorr_verify(void* arg) {
|
||||
int i;
|
||||
benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000 / data->numsigs; i++) {
|
||||
secp256k1_pubkey pubkey;
|
||||
data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF);
|
||||
CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->sigs[0].pubkey, data->sigs[0].pubkeylen));
|
||||
CHECK(secp256k1_schnorr_verify(data->ctx, data->sigs[0].sig, data->msg, &pubkey) == ((i & 0xFF) == 0));
|
||||
data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(void) {
|
||||
benchmark_schnorr_verify_t data;
|
||||
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
|
||||
data.numsigs = 1;
|
||||
run_benchmark("schnorr_verify", benchmark_schnorr_verify, benchmark_schnorr_init, NULL, &data, 10, 20000);
|
||||
|
||||
secp256k1_context_destroy(data.ctx);
|
||||
return 0;
|
||||
}
|
||||
56
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_sign.c
generated
vendored
Normal file
56
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_sign.c
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#include "include/secp256k1.h"
|
||||
#include "util.h"
|
||||
#include "bench.h"
|
||||
|
||||
typedef struct {
|
||||
secp256k1_context* ctx;
|
||||
unsigned char msg[32];
|
||||
unsigned char key[32];
|
||||
} bench_sign_t;
|
||||
|
||||
static void bench_sign_setup(void* arg) {
|
||||
int i;
|
||||
bench_sign_t *data = (bench_sign_t*)arg;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
data->msg[i] = i + 1;
|
||||
}
|
||||
for (i = 0; i < 32; i++) {
|
||||
data->key[i] = i + 65;
|
||||
}
|
||||
}
|
||||
|
||||
static void bench_sign(void* arg) {
|
||||
int i;
|
||||
bench_sign_t *data = (bench_sign_t*)arg;
|
||||
|
||||
unsigned char sig[74];
|
||||
for (i = 0; i < 20000; i++) {
|
||||
size_t siglen = 74;
|
||||
int j;
|
||||
secp256k1_ecdsa_signature signature;
|
||||
CHECK(secp256k1_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL));
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &signature));
|
||||
for (j = 0; j < 32; j++) {
|
||||
data->msg[j] = sig[j];
|
||||
data->key[j] = sig[j + 32];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
bench_sign_t data;
|
||||
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
|
||||
|
||||
run_benchmark("ecdsa_sign", bench_sign, bench_sign_setup, NULL, &data, 10, 20000);
|
||||
|
||||
secp256k1_context_destroy(data.ctx);
|
||||
return 0;
|
||||
}
|
||||
112
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_verify.c
generated
vendored
Normal file
112
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_verify.c
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "include/secp256k1.h"
|
||||
#include "util.h"
|
||||
#include "bench.h"
|
||||
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
secp256k1_context *ctx;
|
||||
unsigned char msg[32];
|
||||
unsigned char key[32];
|
||||
unsigned char sig[72];
|
||||
size_t siglen;
|
||||
unsigned char pubkey[33];
|
||||
size_t pubkeylen;
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
EC_GROUP* ec_group;
|
||||
#endif
|
||||
} benchmark_verify_t;
|
||||
|
||||
static void benchmark_verify(void* arg) {
|
||||
int i;
|
||||
benchmark_verify_t* data = (benchmark_verify_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_pubkey pubkey;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
data->sig[data->siglen - 1] ^= (i & 0xFF);
|
||||
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
|
||||
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
|
||||
CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(data->ctx, &sig, data->msg, &pubkey) == (i == 0));
|
||||
data->sig[data->siglen - 1] ^= (i & 0xFF);
|
||||
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
|
||||
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
static void benchmark_verify_openssl(void* arg) {
|
||||
int i;
|
||||
benchmark_verify_t* data = (benchmark_verify_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
data->sig[data->siglen - 1] ^= (i & 0xFF);
|
||||
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
|
||||
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
|
||||
{
|
||||
EC_KEY *pkey = EC_KEY_new();
|
||||
const unsigned char *pubkey = &data->pubkey[0];
|
||||
int result;
|
||||
|
||||
CHECK(pkey != NULL);
|
||||
result = EC_KEY_set_group(pkey, data->ec_group);
|
||||
CHECK(result);
|
||||
result = (o2i_ECPublicKey(&pkey, &pubkey, data->pubkeylen)) != NULL;
|
||||
CHECK(result);
|
||||
result = ECDSA_verify(0, &data->msg[0], sizeof(data->msg), &data->sig[0], data->siglen, pkey) == (i == 0);
|
||||
CHECK(result);
|
||||
EC_KEY_free(pkey);
|
||||
}
|
||||
data->sig[data->siglen - 1] ^= (i & 0xFF);
|
||||
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
|
||||
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(void) {
|
||||
int i;
|
||||
secp256k1_pubkey pubkey;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
benchmark_verify_t data;
|
||||
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
data.msg[i] = 1 + i;
|
||||
}
|
||||
for (i = 0; i < 32; i++) {
|
||||
data.key[i] = 33 + i;
|
||||
}
|
||||
data.siglen = 72;
|
||||
CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL));
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig));
|
||||
CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key));
|
||||
data.pubkeylen = 33;
|
||||
CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1);
|
||||
|
||||
run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000);
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
data.ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||
run_benchmark("ecdsa_verify_openssl", benchmark_verify_openssl, NULL, NULL, &data, 10, 20000);
|
||||
EC_GROUP_free(data.ec_group);
|
||||
#endif
|
||||
|
||||
secp256k1_context_destroy(data.ctx);
|
||||
return 0;
|
||||
}
|
||||
8
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/dummy.go
generated
vendored
Normal file
8
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/dummy.go
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
//go:build dummy
|
||||
// +build dummy
|
||||
|
||||
// Package c contains only a C file.
|
||||
//
|
||||
// This Go file is part of a workaround for `go mod vendor`.
|
||||
// Please see the file crypto/secp256k1/dummy.go for more information.
|
||||
package src
|
||||
21
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa.h
generated
vendored
Normal file
21
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa.h
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_ECDSA_
|
||||
#define _SECP256K1_ECDSA_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "scalar.h"
|
||||
#include "group.h"
|
||||
#include "ecmult.h"
|
||||
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size);
|
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s);
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message);
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid);
|
||||
|
||||
#endif
|
||||
315
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h
generated
vendored
Normal file
315
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h
generated
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013-2015 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
|
||||
#ifndef _SECP256K1_ECDSA_IMPL_H_
|
||||
#define _SECP256K1_ECDSA_IMPL_H_
|
||||
|
||||
#include "scalar.h"
|
||||
#include "field.h"
|
||||
#include "group.h"
|
||||
#include "ecmult.h"
|
||||
#include "ecmult_gen.h"
|
||||
#include "ecdsa.h"
|
||||
|
||||
/** Group order for secp256k1 defined as 'n' in "Standards for Efficient Cryptography" (SEC2) 2.7.1
|
||||
* sage: for t in xrange(1023, -1, -1):
|
||||
* .. p = 2**256 - 2**32 - t
|
||||
* .. if p.is_prime():
|
||||
* .. print '%x'%p
|
||||
* .. break
|
||||
* 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'
|
||||
* sage: a = 0
|
||||
* sage: b = 7
|
||||
* sage: F = FiniteField (p)
|
||||
* sage: '%x' % (EllipticCurve ([F (a), F (b)]).order())
|
||||
* 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'
|
||||
*/
|
||||
static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST(
|
||||
0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL,
|
||||
0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364141UL
|
||||
);
|
||||
|
||||
/** Difference between field and order, values 'p' and 'n' values defined in
|
||||
* "Standards for Efficient Cryptography" (SEC2) 2.7.1.
|
||||
* sage: p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
|
||||
* sage: a = 0
|
||||
* sage: b = 7
|
||||
* sage: F = FiniteField (p)
|
||||
* sage: '%x' % (p - EllipticCurve ([F (a), F (b)]).order())
|
||||
* '14551231950b75fc4402da1722fc9baee'
|
||||
*/
|
||||
static const secp256k1_fe secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_CONST(
|
||||
0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL
|
||||
);
|
||||
|
||||
static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned char *sigend) {
|
||||
int lenleft, b1;
|
||||
size_t ret = 0;
|
||||
if (*sigp >= sigend) {
|
||||
return -1;
|
||||
}
|
||||
b1 = *((*sigp)++);
|
||||
if (b1 == 0xFF) {
|
||||
/* X.690-0207 8.1.3.5.c the value 0xFF shall not be used. */
|
||||
return -1;
|
||||
}
|
||||
if ((b1 & 0x80) == 0) {
|
||||
/* X.690-0207 8.1.3.4 short form length octets */
|
||||
return b1;
|
||||
}
|
||||
if (b1 == 0x80) {
|
||||
/* Indefinite length is not allowed in DER. */
|
||||
return -1;
|
||||
}
|
||||
/* X.690-207 8.1.3.5 long form length octets */
|
||||
lenleft = b1 & 0x7F;
|
||||
if (lenleft > sigend - *sigp) {
|
||||
return -1;
|
||||
}
|
||||
if (**sigp == 0) {
|
||||
/* Not the shortest possible length encoding. */
|
||||
return -1;
|
||||
}
|
||||
if ((size_t)lenleft > sizeof(size_t)) {
|
||||
/* The resulting length would exceed the range of a size_t, so
|
||||
* certainly longer than the passed array size.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
while (lenleft > 0) {
|
||||
if ((ret >> ((sizeof(size_t) - 1) * 8)) != 0) {
|
||||
}
|
||||
ret = (ret << 8) | **sigp;
|
||||
if (ret + lenleft > (size_t)(sigend - *sigp)) {
|
||||
/* Result exceeds the length of the passed array. */
|
||||
return -1;
|
||||
}
|
||||
(*sigp)++;
|
||||
lenleft--;
|
||||
}
|
||||
if (ret < 128) {
|
||||
/* Not the shortest possible length encoding. */
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int secp256k1_der_parse_integer(secp256k1_scalar *r, const unsigned char **sig, const unsigned char *sigend) {
|
||||
int overflow = 0;
|
||||
unsigned char ra[32] = {0};
|
||||
int rlen;
|
||||
|
||||
if (*sig == sigend || **sig != 0x02) {
|
||||
/* Not a primitive integer (X.690-0207 8.3.1). */
|
||||
return 0;
|
||||
}
|
||||
(*sig)++;
|
||||
rlen = secp256k1_der_read_len(sig, sigend);
|
||||
if (rlen <= 0 || (*sig) + rlen > sigend) {
|
||||
/* Exceeds bounds or not at least length 1 (X.690-0207 8.3.1). */
|
||||
return 0;
|
||||
}
|
||||
if (**sig == 0x00 && rlen > 1 && (((*sig)[1]) & 0x80) == 0x00) {
|
||||
/* Excessive 0x00 padding. */
|
||||
return 0;
|
||||
}
|
||||
if (**sig == 0xFF && rlen > 1 && (((*sig)[1]) & 0x80) == 0x80) {
|
||||
/* Excessive 0xFF padding. */
|
||||
return 0;
|
||||
}
|
||||
if ((**sig & 0x80) == 0x80) {
|
||||
/* Negative. */
|
||||
overflow = 1;
|
||||
}
|
||||
while (rlen > 0 && **sig == 0) {
|
||||
/* Skip leading zero bytes */
|
||||
rlen--;
|
||||
(*sig)++;
|
||||
}
|
||||
if (rlen > 32) {
|
||||
overflow = 1;
|
||||
}
|
||||
if (!overflow) {
|
||||
memcpy(ra + 32 - rlen, *sig, rlen);
|
||||
secp256k1_scalar_set_b32(r, ra, &overflow);
|
||||
}
|
||||
if (overflow) {
|
||||
secp256k1_scalar_set_int(r, 0);
|
||||
}
|
||||
(*sig) += rlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *rr, secp256k1_scalar *rs, const unsigned char *sig, size_t size) {
|
||||
const unsigned char *sigend = sig + size;
|
||||
int rlen;
|
||||
if (sig == sigend || *(sig++) != 0x30) {
|
||||
/* The encoding doesn't start with a constructed sequence (X.690-0207 8.9.1). */
|
||||
return 0;
|
||||
}
|
||||
rlen = secp256k1_der_read_len(&sig, sigend);
|
||||
if (rlen < 0 || sig + rlen > sigend) {
|
||||
/* Tuple exceeds bounds */
|
||||
return 0;
|
||||
}
|
||||
if (sig + rlen != sigend) {
|
||||
/* Garbage after tuple. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!secp256k1_der_parse_integer(rr, &sig, sigend)) {
|
||||
return 0;
|
||||
}
|
||||
if (!secp256k1_der_parse_integer(rs, &sig, sigend)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sig != sigend) {
|
||||
/* Trailing garbage inside tuple. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar* ar, const secp256k1_scalar* as) {
|
||||
unsigned char r[33] = {0}, s[33] = {0};
|
||||
unsigned char *rp = r, *sp = s;
|
||||
size_t lenR = 33, lenS = 33;
|
||||
secp256k1_scalar_get_b32(&r[1], ar);
|
||||
secp256k1_scalar_get_b32(&s[1], as);
|
||||
while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; }
|
||||
while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; }
|
||||
if (*size < 6+lenS+lenR) {
|
||||
*size = 6 + lenS + lenR;
|
||||
return 0;
|
||||
}
|
||||
*size = 6 + lenS + lenR;
|
||||
sig[0] = 0x30;
|
||||
sig[1] = 4 + lenS + lenR;
|
||||
sig[2] = 0x02;
|
||||
sig[3] = lenR;
|
||||
memcpy(sig+4, rp, lenR);
|
||||
sig[4+lenR] = 0x02;
|
||||
sig[5+lenR] = lenS;
|
||||
memcpy(sig+lenR+6, sp, lenS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) {
|
||||
unsigned char c[32];
|
||||
secp256k1_scalar sn, u1, u2;
|
||||
#if !defined(EXHAUSTIVE_TEST_ORDER)
|
||||
secp256k1_fe xr;
|
||||
#endif
|
||||
secp256k1_gej pubkeyj;
|
||||
secp256k1_gej pr;
|
||||
|
||||
if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_scalar_inverse_var(&sn, sigs);
|
||||
secp256k1_scalar_mul(&u1, &sn, message);
|
||||
secp256k1_scalar_mul(&u2, &sn, sigr);
|
||||
secp256k1_gej_set_ge(&pubkeyj, pubkey);
|
||||
secp256k1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1);
|
||||
if (secp256k1_gej_is_infinity(&pr)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(EXHAUSTIVE_TEST_ORDER)
|
||||
{
|
||||
secp256k1_scalar computed_r;
|
||||
secp256k1_ge pr_ge;
|
||||
secp256k1_ge_set_gej(&pr_ge, &pr);
|
||||
secp256k1_fe_normalize(&pr_ge.x);
|
||||
|
||||
secp256k1_fe_get_b32(c, &pr_ge.x);
|
||||
secp256k1_scalar_set_b32(&computed_r, c, NULL);
|
||||
return secp256k1_scalar_eq(sigr, &computed_r);
|
||||
}
|
||||
#else
|
||||
secp256k1_scalar_get_b32(c, sigr);
|
||||
secp256k1_fe_set_b32(&xr, c);
|
||||
|
||||
/** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n)
|
||||
* in xr. Naively, we would extract the x coordinate from pr (requiring a inversion modulo p),
|
||||
* compute the remainder modulo n, and compare it to xr. However:
|
||||
*
|
||||
* xr == X(pr) mod n
|
||||
* <=> exists h. (xr + h * n < p && xr + h * n == X(pr))
|
||||
* [Since 2 * n > p, h can only be 0 or 1]
|
||||
* <=> (xr == X(pr)) || (xr + n < p && xr + n == X(pr))
|
||||
* [In Jacobian coordinates, X(pr) is pr.x / pr.z^2 mod p]
|
||||
* <=> (xr == pr.x / pr.z^2 mod p) || (xr + n < p && xr + n == pr.x / pr.z^2 mod p)
|
||||
* [Multiplying both sides of the equations by pr.z^2 mod p]
|
||||
* <=> (xr * pr.z^2 mod p == pr.x) || (xr + n < p && (xr + n) * pr.z^2 mod p == pr.x)
|
||||
*
|
||||
* Thus, we can avoid the inversion, but we have to check both cases separately.
|
||||
* secp256k1_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test.
|
||||
*/
|
||||
if (secp256k1_gej_eq_x_var(&xr, &pr)) {
|
||||
/* xr * pr.z^2 mod p == pr.x, so the signature is valid. */
|
||||
return 1;
|
||||
}
|
||||
if (secp256k1_fe_cmp_var(&xr, &secp256k1_ecdsa_const_p_minus_order) >= 0) {
|
||||
/* xr + n >= p, so we can skip testing the second case. */
|
||||
return 0;
|
||||
}
|
||||
secp256k1_fe_add(&xr, &secp256k1_ecdsa_const_order_as_fe);
|
||||
if (secp256k1_gej_eq_x_var(&xr, &pr)) {
|
||||
/* (xr + n) * pr.z^2 mod p == pr.x, so the signature is valid. */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) {
|
||||
unsigned char b[32];
|
||||
secp256k1_gej rp;
|
||||
secp256k1_ge r;
|
||||
secp256k1_scalar n;
|
||||
int overflow = 0;
|
||||
|
||||
secp256k1_ecmult_gen(ctx, &rp, nonce);
|
||||
secp256k1_ge_set_gej(&r, &rp);
|
||||
secp256k1_fe_normalize(&r.x);
|
||||
secp256k1_fe_normalize(&r.y);
|
||||
secp256k1_fe_get_b32(b, &r.x);
|
||||
secp256k1_scalar_set_b32(sigr, b, &overflow);
|
||||
/* These two conditions should be checked before calling */
|
||||
VERIFY_CHECK(!secp256k1_scalar_is_zero(sigr));
|
||||
VERIFY_CHECK(overflow == 0);
|
||||
|
||||
if (recid) {
|
||||
/* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log
|
||||
* of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria.
|
||||
*/
|
||||
*recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
|
||||
}
|
||||
secp256k1_scalar_mul(&n, sigr, seckey);
|
||||
secp256k1_scalar_add(&n, &n, message);
|
||||
secp256k1_scalar_inverse(sigs, nonce);
|
||||
secp256k1_scalar_mul(sigs, sigs, &n);
|
||||
secp256k1_scalar_clear(&n);
|
||||
secp256k1_gej_clear(&rp);
|
||||
secp256k1_ge_clear(&r);
|
||||
if (secp256k1_scalar_is_zero(sigs)) {
|
||||
return 0;
|
||||
}
|
||||
if (secp256k1_scalar_is_high(sigs)) {
|
||||
secp256k1_scalar_negate(sigs, sigs);
|
||||
if (recid) {
|
||||
*recid ^= 1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
25
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey.h
generated
vendored
Normal file
25
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey.h
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_ECKEY_
|
||||
#define _SECP256K1_ECKEY_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "group.h"
|
||||
#include "scalar.h"
|
||||
#include "ecmult.h"
|
||||
#include "ecmult_gen.h"
|
||||
|
||||
static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size);
|
||||
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed);
|
||||
|
||||
static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak);
|
||||
static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak);
|
||||
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak);
|
||||
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak);
|
||||
|
||||
#endif
|
||||
99
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey_impl.h
generated
vendored
Normal file
99
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey_impl.h
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_ECKEY_IMPL_H_
|
||||
#define _SECP256K1_ECKEY_IMPL_H_
|
||||
|
||||
#include "eckey.h"
|
||||
|
||||
#include "scalar.h"
|
||||
#include "field.h"
|
||||
#include "group.h"
|
||||
#include "ecmult_gen.h"
|
||||
|
||||
static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) {
|
||||
if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) {
|
||||
secp256k1_fe x;
|
||||
return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == 0x03);
|
||||
} else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) {
|
||||
secp256k1_fe x, y;
|
||||
if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_ge_set_xy(elem, &x, &y);
|
||||
if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) {
|
||||
return 0;
|
||||
}
|
||||
return secp256k1_ge_is_valid_var(elem);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) {
|
||||
if (secp256k1_ge_is_infinity(elem)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_fe_normalize_var(&elem->x);
|
||||
secp256k1_fe_normalize_var(&elem->y);
|
||||
secp256k1_fe_get_b32(&pub[1], &elem->x);
|
||||
if (compressed) {
|
||||
*size = 33;
|
||||
pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00);
|
||||
} else {
|
||||
*size = 65;
|
||||
pub[0] = 0x04;
|
||||
secp256k1_fe_get_b32(&pub[33], &elem->y);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) {
|
||||
secp256k1_scalar_add(key, key, tweak);
|
||||
if (secp256k1_scalar_is_zero(key)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) {
|
||||
secp256k1_gej pt;
|
||||
secp256k1_scalar one;
|
||||
secp256k1_gej_set_ge(&pt, key);
|
||||
secp256k1_scalar_set_int(&one, 1);
|
||||
secp256k1_ecmult(ctx, &pt, &pt, &one, tweak);
|
||||
|
||||
if (secp256k1_gej_is_infinity(&pt)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_ge_set_gej(key, &pt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak) {
|
||||
if (secp256k1_scalar_is_zero(tweak)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_scalar_mul(key, key, tweak);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) {
|
||||
secp256k1_scalar zero;
|
||||
secp256k1_gej pt;
|
||||
if (secp256k1_scalar_is_zero(tweak)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_scalar_set_int(&zero, 0);
|
||||
secp256k1_gej_set_ge(&pt, key);
|
||||
secp256k1_ecmult(ctx, &pt, &pt, tweak, &zero);
|
||||
secp256k1_ge_set_gej(key, &pt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
31
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult.h
generated
vendored
Normal file
31
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult.h
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_ECMULT_
|
||||
#define _SECP256K1_ECMULT_
|
||||
|
||||
#include "num.h"
|
||||
#include "group.h"
|
||||
|
||||
typedef struct {
|
||||
/* For accelerating the computation of a*P + b*G: */
|
||||
secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */
|
||||
#endif
|
||||
} secp256k1_ecmult_context;
|
||||
|
||||
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx);
|
||||
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb);
|
||||
static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst,
|
||||
const secp256k1_ecmult_context *src, const secp256k1_callback *cb);
|
||||
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx);
|
||||
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx);
|
||||
|
||||
/** Double multiply: R = na*A + ng*G */
|
||||
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng);
|
||||
|
||||
#endif
|
||||
15
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const.h
generated
vendored
Normal file
15
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const.h
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2015 Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_ECMULT_CONST_
|
||||
#define _SECP256K1_ECMULT_CONST_
|
||||
|
||||
#include "scalar.h"
|
||||
#include "group.h"
|
||||
|
||||
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q);
|
||||
|
||||
#endif
|
||||
239
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h
generated
vendored
Normal file
239
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h
generated
vendored
Normal file
@@ -0,0 +1,239 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2015 Pieter Wuille, Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_ECMULT_CONST_IMPL_
|
||||
#define _SECP256K1_ECMULT_CONST_IMPL_
|
||||
|
||||
#include "scalar.h"
|
||||
#include "group.h"
|
||||
#include "ecmult_const.h"
|
||||
#include "ecmult_impl.h"
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
#define WNAF_BITS 128
|
||||
#else
|
||||
#define WNAF_BITS 256
|
||||
#endif
|
||||
#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w))
|
||||
|
||||
/* This is like `ECMULT_TABLE_GET_GE` but is constant time */
|
||||
#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \
|
||||
int m; \
|
||||
int abs_n = (n) * (((n) > 0) * 2 - 1); \
|
||||
int idx_n = abs_n / 2; \
|
||||
secp256k1_fe neg_y; \
|
||||
VERIFY_CHECK(((n) & 1) == 1); \
|
||||
VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
|
||||
VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
|
||||
VERIFY_SETUP(secp256k1_fe_clear(&(r)->x)); \
|
||||
VERIFY_SETUP(secp256k1_fe_clear(&(r)->y)); \
|
||||
for (m = 0; m < ECMULT_TABLE_SIZE(w); m++) { \
|
||||
/* This loop is used to avoid secret data in array indices. See
|
||||
* the comment in ecmult_gen_impl.h for rationale. */ \
|
||||
secp256k1_fe_cmov(&(r)->x, &(pre)[m].x, m == idx_n); \
|
||||
secp256k1_fe_cmov(&(r)->y, &(pre)[m].y, m == idx_n); \
|
||||
} \
|
||||
(r)->infinity = 0; \
|
||||
secp256k1_fe_negate(&neg_y, &(r)->y, 1); \
|
||||
secp256k1_fe_cmov(&(r)->y, &neg_y, (n) != abs_n); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/** Convert a number to WNAF notation. The number becomes represented by sum(2^{wi} * wnaf[i], i=0..return_val)
|
||||
* with the following guarantees:
|
||||
* - each wnaf[i] an odd integer between -(1 << w) and (1 << w)
|
||||
* - each wnaf[i] is nonzero
|
||||
* - the number of words set is returned; this is always (WNAF_BITS + w - 1) / w
|
||||
*
|
||||
* Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar
|
||||
* Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.)
|
||||
* CT-RSA 2003, LNCS 2612, pp. 328-443, 2003. Springer-Verlagy Berlin Heidelberg 2003
|
||||
*
|
||||
* Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335
|
||||
*/
|
||||
static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) {
|
||||
int global_sign;
|
||||
int skew = 0;
|
||||
int word = 0;
|
||||
|
||||
/* 1 2 3 */
|
||||
int u_last;
|
||||
int u;
|
||||
|
||||
int flip;
|
||||
int bit;
|
||||
secp256k1_scalar neg_s;
|
||||
int not_neg_one;
|
||||
/* Note that we cannot handle even numbers by negating them to be odd, as is
|
||||
* done in other implementations, since if our scalars were specified to have
|
||||
* width < 256 for performance reasons, their negations would have width 256
|
||||
* and we'd lose any performance benefit. Instead, we use a technique from
|
||||
* Section 4.2 of the Okeya/Tagaki paper, which is to add either 1 (for even)
|
||||
* or 2 (for odd) to the number we are encoding, returning a skew value indicating
|
||||
* this, and having the caller compensate after doing the multiplication. */
|
||||
|
||||
/* Negative numbers will be negated to keep their bit representation below the maximum width */
|
||||
flip = secp256k1_scalar_is_high(&s);
|
||||
/* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */
|
||||
bit = flip ^ !secp256k1_scalar_is_even(&s);
|
||||
/* We check for negative one, since adding 2 to it will cause an overflow */
|
||||
secp256k1_scalar_negate(&neg_s, &s);
|
||||
not_neg_one = !secp256k1_scalar_is_one(&neg_s);
|
||||
secp256k1_scalar_cadd_bit(&s, bit, not_neg_one);
|
||||
/* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so caller expects
|
||||
* that we added two to it and flipped it. In fact for -1 these operations are
|
||||
* identical. We only flipped, but since skewing is required (in the sense that
|
||||
* the skew must be 1 or 2, never zero) and flipping is not, we need to change
|
||||
* our flags to claim that we only skewed. */
|
||||
global_sign = secp256k1_scalar_cond_negate(&s, flip);
|
||||
global_sign *= not_neg_one * 2 - 1;
|
||||
skew = 1 << bit;
|
||||
|
||||
/* 4 */
|
||||
u_last = secp256k1_scalar_shr_int(&s, w);
|
||||
while (word * w < WNAF_BITS) {
|
||||
int sign;
|
||||
int even;
|
||||
|
||||
/* 4.1 4.4 */
|
||||
u = secp256k1_scalar_shr_int(&s, w);
|
||||
/* 4.2 */
|
||||
even = ((u & 1) == 0);
|
||||
sign = 2 * (u_last > 0) - 1;
|
||||
u += sign * even;
|
||||
u_last -= sign * even * (1 << w);
|
||||
|
||||
/* 4.3, adapted for global sign change */
|
||||
wnaf[word++] = u_last * global_sign;
|
||||
|
||||
u_last = u;
|
||||
}
|
||||
wnaf[word] = u * global_sign;
|
||||
|
||||
VERIFY_CHECK(secp256k1_scalar_is_zero(&s));
|
||||
VERIFY_CHECK(word == WNAF_SIZE(w));
|
||||
return skew;
|
||||
}
|
||||
|
||||
|
||||
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar) {
|
||||
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||
secp256k1_ge tmpa;
|
||||
secp256k1_fe Z;
|
||||
|
||||
int skew_1;
|
||||
int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)];
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||
int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)];
|
||||
int skew_lam;
|
||||
secp256k1_scalar q_1, q_lam;
|
||||
#endif
|
||||
|
||||
int i;
|
||||
secp256k1_scalar sc = *scalar;
|
||||
|
||||
/* build wnaf representation for q. */
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
/* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */
|
||||
secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc);
|
||||
skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1);
|
||||
skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1);
|
||||
#else
|
||||
skew_1 = secp256k1_wnaf_const(wnaf_1, sc, WINDOW_A - 1);
|
||||
#endif
|
||||
|
||||
/* Calculate odd multiples of a.
|
||||
* All multiples are brought to the same Z 'denominator', which is stored
|
||||
* in Z. Due to secp256k1' isomorphism we can do all operations pretending
|
||||
* that the Z coordinate was 1, use affine addition formulae, and correct
|
||||
* the Z coordinate of the result once at the end.
|
||||
*/
|
||||
secp256k1_gej_set_ge(r, a);
|
||||
secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, r);
|
||||
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
|
||||
secp256k1_fe_normalize_weak(&pre_a[i].y);
|
||||
}
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
|
||||
secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* first loop iteration (separated out so we can directly set r, rather
|
||||
* than having it start at infinity, get doubled several times, then have
|
||||
* its new value added to it) */
|
||||
i = wnaf_1[WNAF_SIZE(WINDOW_A - 1)];
|
||||
VERIFY_CHECK(i != 0);
|
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A);
|
||||
secp256k1_gej_set_ge(r, &tmpa);
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
i = wnaf_lam[WNAF_SIZE(WINDOW_A - 1)];
|
||||
VERIFY_CHECK(i != 0);
|
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A);
|
||||
secp256k1_gej_add_ge(r, r, &tmpa);
|
||||
#endif
|
||||
/* remaining loop iterations */
|
||||
for (i = WNAF_SIZE(WINDOW_A - 1) - 1; i >= 0; i--) {
|
||||
int n;
|
||||
int j;
|
||||
for (j = 0; j < WINDOW_A - 1; ++j) {
|
||||
secp256k1_gej_double_nonzero(r, r, NULL);
|
||||
}
|
||||
|
||||
n = wnaf_1[i];
|
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A);
|
||||
VERIFY_CHECK(n != 0);
|
||||
secp256k1_gej_add_ge(r, r, &tmpa);
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
n = wnaf_lam[i];
|
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A);
|
||||
VERIFY_CHECK(n != 0);
|
||||
secp256k1_gej_add_ge(r, r, &tmpa);
|
||||
#endif
|
||||
}
|
||||
|
||||
secp256k1_fe_mul(&r->z, &r->z, &Z);
|
||||
|
||||
{
|
||||
/* Correct for wNAF skew */
|
||||
secp256k1_ge correction = *a;
|
||||
secp256k1_ge_storage correction_1_stor;
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
secp256k1_ge_storage correction_lam_stor;
|
||||
#endif
|
||||
secp256k1_ge_storage a2_stor;
|
||||
secp256k1_gej tmpj;
|
||||
secp256k1_gej_set_ge(&tmpj, &correction);
|
||||
secp256k1_gej_double_var(&tmpj, &tmpj, NULL);
|
||||
secp256k1_ge_set_gej(&correction, &tmpj);
|
||||
secp256k1_ge_to_storage(&correction_1_stor, a);
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
secp256k1_ge_to_storage(&correction_lam_stor, a);
|
||||
#endif
|
||||
secp256k1_ge_to_storage(&a2_stor, &correction);
|
||||
|
||||
/* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */
|
||||
secp256k1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2);
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2);
|
||||
#endif
|
||||
|
||||
/* Apply the correction */
|
||||
secp256k1_ge_from_storage(&correction, &correction_1_stor);
|
||||
secp256k1_ge_neg(&correction, &correction);
|
||||
secp256k1_gej_add_ge(r, r, &correction);
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
secp256k1_ge_from_storage(&correction, &correction_lam_stor);
|
||||
secp256k1_ge_neg(&correction, &correction);
|
||||
secp256k1_ge_mul_lambda(&correction, &correction);
|
||||
secp256k1_gej_add_ge(r, r, &correction);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
43
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h
generated
vendored
Normal file
43
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_ECMULT_GEN_
|
||||
#define _SECP256K1_ECMULT_GEN_
|
||||
|
||||
#include "scalar.h"
|
||||
#include "group.h"
|
||||
|
||||
typedef struct {
|
||||
/* For accelerating the computation of a*G:
|
||||
* To harden against timing attacks, use the following mechanism:
|
||||
* * Break up the multiplicand into groups of 4 bits, called n_0, n_1, n_2, ..., n_63.
|
||||
* * Compute sum(n_i * 16^i * G + U_i, i=0..63), where:
|
||||
* * U_i = U * 2^i (for i=0..62)
|
||||
* * U_i = U * (1-2^63) (for i=63)
|
||||
* where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0.
|
||||
* For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is
|
||||
* precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63).
|
||||
* None of the resulting prec group elements have a known scalar, and neither do any of
|
||||
* the intermediate sums while computing a*G.
|
||||
*/
|
||||
secp256k1_ge_storage (*prec)[64][16]; /* prec[j][i] = 16^j * i * G + U_i */
|
||||
secp256k1_scalar blind;
|
||||
secp256k1_gej initial;
|
||||
} secp256k1_ecmult_gen_context;
|
||||
|
||||
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context* ctx);
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, const secp256k1_callback* cb);
|
||||
static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst,
|
||||
const secp256k1_ecmult_gen_context* src, const secp256k1_callback* cb);
|
||||
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx);
|
||||
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx);
|
||||
|
||||
/** Multiply with the generator: R = a*G */
|
||||
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a);
|
||||
|
||||
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32);
|
||||
|
||||
#endif
|
||||
210
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h
generated
vendored
Normal file
210
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h
generated
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_ECMULT_GEN_IMPL_H_
|
||||
#define _SECP256K1_ECMULT_GEN_IMPL_H_
|
||||
|
||||
#include "scalar.h"
|
||||
#include "group.h"
|
||||
#include "ecmult_gen.h"
|
||||
#include "hash_impl.h"
|
||||
#ifdef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
#include "ecmult_static_context.h"
|
||||
#endif
|
||||
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context *ctx) {
|
||||
ctx->prec = NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, const secp256k1_callback* cb) {
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
secp256k1_ge prec[1024];
|
||||
secp256k1_gej gj;
|
||||
secp256k1_gej nums_gej;
|
||||
int i, j;
|
||||
#endif
|
||||
|
||||
if (ctx->prec != NULL) {
|
||||
return;
|
||||
}
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
ctx->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*ctx->prec));
|
||||
|
||||
/* get the generator */
|
||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
|
||||
|
||||
/* Construct a group element with no known corresponding scalar (nothing up my sleeve). */
|
||||
{
|
||||
static const unsigned char nums_b32[33] = "The scalar for this x is unknown";
|
||||
secp256k1_fe nums_x;
|
||||
secp256k1_ge nums_ge;
|
||||
int r;
|
||||
r = secp256k1_fe_set_b32(&nums_x, nums_b32);
|
||||
(void)r;
|
||||
VERIFY_CHECK(r);
|
||||
r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0);
|
||||
(void)r;
|
||||
VERIFY_CHECK(r);
|
||||
secp256k1_gej_set_ge(&nums_gej, &nums_ge);
|
||||
/* Add G to make the bits in x uniformly distributed. */
|
||||
secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g, NULL);
|
||||
}
|
||||
|
||||
/* compute prec. */
|
||||
{
|
||||
secp256k1_gej precj[1024]; /* Jacobian versions of prec. */
|
||||
secp256k1_gej gbase;
|
||||
secp256k1_gej numsbase;
|
||||
gbase = gj; /* 16^j * G */
|
||||
numsbase = nums_gej; /* 2^j * nums. */
|
||||
for (j = 0; j < 64; j++) {
|
||||
/* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */
|
||||
precj[j*16] = numsbase;
|
||||
for (i = 1; i < 16; i++) {
|
||||
secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase, NULL);
|
||||
}
|
||||
/* Multiply gbase by 16. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
secp256k1_gej_double_var(&gbase, &gbase, NULL);
|
||||
}
|
||||
/* Multiply numbase by 2. */
|
||||
secp256k1_gej_double_var(&numsbase, &numsbase, NULL);
|
||||
if (j == 62) {
|
||||
/* In the last iteration, numsbase is (1 - 2^j) * nums instead. */
|
||||
secp256k1_gej_neg(&numsbase, &numsbase);
|
||||
secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL);
|
||||
}
|
||||
}
|
||||
secp256k1_ge_set_all_gej_var(prec, precj, 1024, cb);
|
||||
}
|
||||
for (j = 0; j < 64; j++) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)cb;
|
||||
ctx->prec = (secp256k1_ge_storage (*)[64][16])secp256k1_ecmult_static_context;
|
||||
#endif
|
||||
secp256k1_ecmult_gen_blind(ctx, NULL);
|
||||
}
|
||||
|
||||
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx) {
|
||||
return ctx->prec != NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst,
|
||||
const secp256k1_ecmult_gen_context *src, const secp256k1_callback* cb) {
|
||||
if (src->prec == NULL) {
|
||||
dst->prec = NULL;
|
||||
} else {
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
dst->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*dst->prec));
|
||||
memcpy(dst->prec, src->prec, sizeof(*dst->prec));
|
||||
#else
|
||||
(void)cb;
|
||||
dst->prec = src->prec;
|
||||
#endif
|
||||
dst->initial = src->initial;
|
||||
dst->blind = src->blind;
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) {
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
free(ctx->prec);
|
||||
#endif
|
||||
secp256k1_scalar_clear(&ctx->blind);
|
||||
secp256k1_gej_clear(&ctx->initial);
|
||||
ctx->prec = NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) {
|
||||
secp256k1_ge add;
|
||||
secp256k1_ge_storage adds;
|
||||
secp256k1_scalar gnb;
|
||||
int bits;
|
||||
int i, j;
|
||||
memset(&adds, 0, sizeof(adds));
|
||||
*r = ctx->initial;
|
||||
/* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */
|
||||
secp256k1_scalar_add(&gnb, gn, &ctx->blind);
|
||||
add.infinity = 0;
|
||||
for (j = 0; j < 64; j++) {
|
||||
bits = secp256k1_scalar_get_bits(&gnb, j * 4, 4);
|
||||
for (i = 0; i < 16; i++) {
|
||||
/** This uses a conditional move to avoid any secret data in array indexes.
|
||||
* _Any_ use of secret indexes has been demonstrated to result in timing
|
||||
* sidechannels, even when the cache-line access patterns are uniform.
|
||||
* See also:
|
||||
* "A word of warning", CHES 2013 Rump Session, by Daniel J. Bernstein and Peter Schwabe
|
||||
* (https://cryptojedi.org/peter/data/chesrump-20130822.pdf) and
|
||||
* "Cache Attacks and Countermeasures: the Case of AES", RSA 2006,
|
||||
* by Dag Arne Osvik, Adi Shamir, and Eran Tromer
|
||||
* (http://www.tau.ac.il/~tromer/papers/cache.pdf)
|
||||
*/
|
||||
secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits);
|
||||
}
|
||||
secp256k1_ge_from_storage(&add, &adds);
|
||||
secp256k1_gej_add_ge(r, r, &add);
|
||||
}
|
||||
bits = 0;
|
||||
secp256k1_ge_clear(&add);
|
||||
secp256k1_scalar_clear(&gnb);
|
||||
}
|
||||
|
||||
/* Setup blinding values for secp256k1_ecmult_gen. */
|
||||
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) {
|
||||
secp256k1_scalar b;
|
||||
secp256k1_gej gb;
|
||||
secp256k1_fe s;
|
||||
unsigned char nonce32[32];
|
||||
secp256k1_rfc6979_hmac_sha256_t rng;
|
||||
int retry;
|
||||
unsigned char keydata[64] = {0};
|
||||
if (seed32 == NULL) {
|
||||
/* When seed is NULL, reset the initial point and blinding value. */
|
||||
secp256k1_gej_set_ge(&ctx->initial, &secp256k1_ge_const_g);
|
||||
secp256k1_gej_neg(&ctx->initial, &ctx->initial);
|
||||
secp256k1_scalar_set_int(&ctx->blind, 1);
|
||||
}
|
||||
/* The prior blinding value (if not reset) is chained forward by including it in the hash. */
|
||||
secp256k1_scalar_get_b32(nonce32, &ctx->blind);
|
||||
/** Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data,
|
||||
* and guards against weak or adversarial seeds. This is a simpler and safer interface than
|
||||
* asking the caller for blinding values directly and expecting them to retry on failure.
|
||||
*/
|
||||
memcpy(keydata, nonce32, 32);
|
||||
if (seed32 != NULL) {
|
||||
memcpy(keydata + 32, seed32, 32);
|
||||
}
|
||||
secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, seed32 ? 64 : 32);
|
||||
memset(keydata, 0, sizeof(keydata));
|
||||
/* Retry for out of range results to achieve uniformity. */
|
||||
do {
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
|
||||
retry = !secp256k1_fe_set_b32(&s, nonce32);
|
||||
retry |= secp256k1_fe_is_zero(&s);
|
||||
} while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > Fp. */
|
||||
/* Randomize the projection to defend against multiplier sidechannels. */
|
||||
secp256k1_gej_rescale(&ctx->initial, &s);
|
||||
secp256k1_fe_clear(&s);
|
||||
do {
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
|
||||
secp256k1_scalar_set_b32(&b, nonce32, &retry);
|
||||
/* A blinding value of 0 works, but would undermine the projection hardening. */
|
||||
retry |= secp256k1_scalar_is_zero(&b);
|
||||
} while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > order. */
|
||||
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
|
||||
memset(nonce32, 0, 32);
|
||||
secp256k1_ecmult_gen(ctx, &gb, &b);
|
||||
secp256k1_scalar_negate(&b, &b);
|
||||
ctx->blind = b;
|
||||
ctx->initial = gb;
|
||||
secp256k1_scalar_clear(&b);
|
||||
secp256k1_gej_clear(&gb);
|
||||
}
|
||||
|
||||
#endif
|
||||
406
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h
generated
vendored
Normal file
406
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h
generated
vendored
Normal file
@@ -0,0 +1,406 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_ECMULT_IMPL_H_
|
||||
#define _SECP256K1_ECMULT_IMPL_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "group.h"
|
||||
#include "scalar.h"
|
||||
#include "ecmult.h"
|
||||
|
||||
#if defined(EXHAUSTIVE_TEST_ORDER)
|
||||
/* We need to lower these values for exhaustive tests because
|
||||
* the tables cannot have infinities in them (this breaks the
|
||||
* affine-isomorphism stuff which tracks z-ratios) */
|
||||
# if EXHAUSTIVE_TEST_ORDER > 128
|
||||
# define WINDOW_A 5
|
||||
# define WINDOW_G 8
|
||||
# elif EXHAUSTIVE_TEST_ORDER > 8
|
||||
# define WINDOW_A 4
|
||||
# define WINDOW_G 4
|
||||
# else
|
||||
# define WINDOW_A 2
|
||||
# define WINDOW_G 2
|
||||
# endif
|
||||
#else
|
||||
/* optimal for 128-bit and 256-bit exponents. */
|
||||
#define WINDOW_A 5
|
||||
/** larger numbers may result in slightly better performance, at the cost of
|
||||
exponentially larger precomputed tables. */
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
/** Two tables for window size 15: 1.375 MiB. */
|
||||
#define WINDOW_G 15
|
||||
#else
|
||||
/** One table for window size 16: 1.375 MiB. */
|
||||
#define WINDOW_G 16
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** The number of entries a table with precomputed multiples needs to have. */
|
||||
#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2))
|
||||
|
||||
/** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain
|
||||
* the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will
|
||||
* contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z.
|
||||
* Prej's Z values are undefined, except for the last value.
|
||||
*/
|
||||
static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, secp256k1_fe *zr, const secp256k1_gej *a) {
|
||||
secp256k1_gej d;
|
||||
secp256k1_ge a_ge, d_ge;
|
||||
int i;
|
||||
|
||||
VERIFY_CHECK(!a->infinity);
|
||||
|
||||
secp256k1_gej_double_var(&d, a, NULL);
|
||||
|
||||
/*
|
||||
* Perform the additions on an isomorphism where 'd' is affine: drop the z coordinate
|
||||
* of 'd', and scale the 1P starting value's x/y coordinates without changing its z.
|
||||
*/
|
||||
d_ge.x = d.x;
|
||||
d_ge.y = d.y;
|
||||
d_ge.infinity = 0;
|
||||
|
||||
secp256k1_ge_set_gej_zinv(&a_ge, a, &d.z);
|
||||
prej[0].x = a_ge.x;
|
||||
prej[0].y = a_ge.y;
|
||||
prej[0].z = a->z;
|
||||
prej[0].infinity = 0;
|
||||
|
||||
zr[0] = d.z;
|
||||
for (i = 1; i < n; i++) {
|
||||
secp256k1_gej_add_ge_var(&prej[i], &prej[i-1], &d_ge, &zr[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Each point in 'prej' has a z coordinate too small by a factor of 'd.z'. Only
|
||||
* the final point's z coordinate is actually used though, so just update that.
|
||||
*/
|
||||
secp256k1_fe_mul(&prej[n-1].z, &prej[n-1].z, &d.z);
|
||||
}
|
||||
|
||||
/** Fill a table 'pre' with precomputed odd multiples of a.
|
||||
*
|
||||
* There are two versions of this function:
|
||||
* - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its
|
||||
* resulting point set to a single constant Z denominator, stores the X and Y
|
||||
* coordinates as ge_storage points in pre, and stores the global Z in rz.
|
||||
* It only operates on tables sized for WINDOW_A wnaf multiples.
|
||||
* - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its
|
||||
* resulting point set to actually affine points, and stores those in pre.
|
||||
* It operates on tables of any size, but uses heap-allocated temporaries.
|
||||
*
|
||||
* To compute a*P + b*G, we compute a table for P using the first function,
|
||||
* and for G using the second (which requires an inverse, but it only needs to
|
||||
* happen once).
|
||||
*/
|
||||
static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) {
|
||||
secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||
secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||
|
||||
/* Compute the odd multiples in Jacobian form. */
|
||||
secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), prej, zr, a);
|
||||
/* Bring them to the same Z denominator. */
|
||||
secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr);
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_odd_multiples_table_storage_var(int n, secp256k1_ge_storage *pre, const secp256k1_gej *a, const secp256k1_callback *cb) {
|
||||
secp256k1_gej *prej = (secp256k1_gej*)checked_malloc(cb, sizeof(secp256k1_gej) * n);
|
||||
secp256k1_ge *prea = (secp256k1_ge*)checked_malloc(cb, sizeof(secp256k1_ge) * n);
|
||||
secp256k1_fe *zr = (secp256k1_fe*)checked_malloc(cb, sizeof(secp256k1_fe) * n);
|
||||
int i;
|
||||
|
||||
/* Compute the odd multiples in Jacobian form. */
|
||||
secp256k1_ecmult_odd_multiples_table(n, prej, zr, a);
|
||||
/* Convert them in batch to affine coordinates. */
|
||||
secp256k1_ge_set_table_gej_var(prea, prej, zr, n);
|
||||
/* Convert them to compact storage form. */
|
||||
for (i = 0; i < n; i++) {
|
||||
secp256k1_ge_to_storage(&pre[i], &prea[i]);
|
||||
}
|
||||
|
||||
free(prea);
|
||||
free(prej);
|
||||
free(zr);
|
||||
}
|
||||
|
||||
/** The following two macro retrieves a particular odd multiple from a table
|
||||
* of precomputed multiples. */
|
||||
#define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \
|
||||
VERIFY_CHECK(((n) & 1) == 1); \
|
||||
VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
|
||||
VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
|
||||
if ((n) > 0) { \
|
||||
*(r) = (pre)[((n)-1)/2]; \
|
||||
} else { \
|
||||
secp256k1_ge_neg((r), &(pre)[(-(n)-1)/2]); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define ECMULT_TABLE_GET_GE_STORAGE(r,pre,n,w) do { \
|
||||
VERIFY_CHECK(((n) & 1) == 1); \
|
||||
VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
|
||||
VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
|
||||
if ((n) > 0) { \
|
||||
secp256k1_ge_from_storage((r), &(pre)[((n)-1)/2]); \
|
||||
} else { \
|
||||
secp256k1_ge_from_storage((r), &(pre)[(-(n)-1)/2]); \
|
||||
secp256k1_ge_neg((r), (r)); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) {
|
||||
ctx->pre_g = NULL;
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
ctx->pre_g_128 = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb) {
|
||||
secp256k1_gej gj;
|
||||
|
||||
if (ctx->pre_g != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* get the generator */
|
||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
|
||||
|
||||
ctx->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G));
|
||||
|
||||
/* precompute the tables with odd multiples */
|
||||
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj, cb);
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
{
|
||||
secp256k1_gej g_128j;
|
||||
int i;
|
||||
|
||||
ctx->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G));
|
||||
|
||||
/* calculate 2^128*generator */
|
||||
g_128j = gj;
|
||||
for (i = 0; i < 128; i++) {
|
||||
secp256k1_gej_double_var(&g_128j, &g_128j, NULL);
|
||||
}
|
||||
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j, cb);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst,
|
||||
const secp256k1_ecmult_context *src, const secp256k1_callback *cb) {
|
||||
if (src->pre_g == NULL) {
|
||||
dst->pre_g = NULL;
|
||||
} else {
|
||||
size_t size = sizeof((*dst->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G);
|
||||
dst->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, size);
|
||||
memcpy(dst->pre_g, src->pre_g, size);
|
||||
}
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
if (src->pre_g_128 == NULL) {
|
||||
dst->pre_g_128 = NULL;
|
||||
} else {
|
||||
size_t size = sizeof((*dst->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G);
|
||||
dst->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, size);
|
||||
memcpy(dst->pre_g_128, src->pre_g_128, size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx) {
|
||||
return ctx->pre_g != NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) {
|
||||
free(ctx->pre_g);
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
free(ctx->pre_g_128);
|
||||
#endif
|
||||
secp256k1_ecmult_context_init(ctx);
|
||||
}
|
||||
|
||||
/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
|
||||
* with the following guarantees:
|
||||
* - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1)
|
||||
* - two non-zero entries in wnaf are separated by at least w-1 zeroes.
|
||||
* - the number of set values in wnaf is returned. This number is at most 256, and at most one more
|
||||
* than the number of bits in the (absolute value) of the input.
|
||||
*/
|
||||
static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, int w) {
|
||||
secp256k1_scalar s = *a;
|
||||
int last_set_bit = -1;
|
||||
int bit = 0;
|
||||
int sign = 1;
|
||||
int carry = 0;
|
||||
|
||||
VERIFY_CHECK(wnaf != NULL);
|
||||
VERIFY_CHECK(0 <= len && len <= 256);
|
||||
VERIFY_CHECK(a != NULL);
|
||||
VERIFY_CHECK(2 <= w && w <= 31);
|
||||
|
||||
memset(wnaf, 0, len * sizeof(wnaf[0]));
|
||||
|
||||
if (secp256k1_scalar_get_bits(&s, 255, 1)) {
|
||||
secp256k1_scalar_negate(&s, &s);
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
while (bit < len) {
|
||||
int now;
|
||||
int word;
|
||||
if (secp256k1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) {
|
||||
bit++;
|
||||
continue;
|
||||
}
|
||||
|
||||
now = w;
|
||||
if (now > len - bit) {
|
||||
now = len - bit;
|
||||
}
|
||||
|
||||
word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry;
|
||||
|
||||
carry = (word >> (w-1)) & 1;
|
||||
word -= carry << w;
|
||||
|
||||
wnaf[bit] = sign * word;
|
||||
last_set_bit = bit;
|
||||
|
||||
bit += now;
|
||||
}
|
||||
#ifdef VERIFY
|
||||
CHECK(carry == 0);
|
||||
while (bit < 256) {
|
||||
CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0);
|
||||
}
|
||||
#endif
|
||||
return last_set_bit + 1;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
|
||||
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||
secp256k1_ge tmpa;
|
||||
secp256k1_fe Z;
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||
secp256k1_scalar na_1, na_lam;
|
||||
/* Splitted G factors. */
|
||||
secp256k1_scalar ng_1, ng_128;
|
||||
int wnaf_na_1[130];
|
||||
int wnaf_na_lam[130];
|
||||
int bits_na_1;
|
||||
int bits_na_lam;
|
||||
int wnaf_ng_1[129];
|
||||
int bits_ng_1;
|
||||
int wnaf_ng_128[129];
|
||||
int bits_ng_128;
|
||||
#else
|
||||
int wnaf_na[256];
|
||||
int bits_na;
|
||||
int wnaf_ng[256];
|
||||
int bits_ng;
|
||||
#endif
|
||||
int i;
|
||||
int bits;
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
|
||||
secp256k1_scalar_split_lambda(&na_1, &na_lam, na);
|
||||
|
||||
/* build wnaf representation for na_1 and na_lam. */
|
||||
bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, 130, &na_1, WINDOW_A);
|
||||
bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, 130, &na_lam, WINDOW_A);
|
||||
VERIFY_CHECK(bits_na_1 <= 130);
|
||||
VERIFY_CHECK(bits_na_lam <= 130);
|
||||
bits = bits_na_1;
|
||||
if (bits_na_lam > bits) {
|
||||
bits = bits_na_lam;
|
||||
}
|
||||
#else
|
||||
/* build wnaf representation for na. */
|
||||
bits_na = secp256k1_ecmult_wnaf(wnaf_na, 256, na, WINDOW_A);
|
||||
bits = bits_na;
|
||||
#endif
|
||||
|
||||
/* Calculate odd multiples of a.
|
||||
* All multiples are brought to the same Z 'denominator', which is stored
|
||||
* in Z. Due to secp256k1' isomorphism we can do all operations pretending
|
||||
* that the Z coordinate was 1, use affine addition formulae, and correct
|
||||
* the Z coordinate of the result once at the end.
|
||||
* The exception is the precomputed G table points, which are actually
|
||||
* affine. Compared to the base used for other points, they have a Z ratio
|
||||
* of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same
|
||||
* isomorphism to efficiently add with a known Z inverse.
|
||||
*/
|
||||
secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, a);
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
|
||||
secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]);
|
||||
}
|
||||
|
||||
/* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */
|
||||
secp256k1_scalar_split_128(&ng_1, &ng_128, ng);
|
||||
|
||||
/* Build wnaf representation for ng_1 and ng_128 */
|
||||
bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G);
|
||||
bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G);
|
||||
if (bits_ng_1 > bits) {
|
||||
bits = bits_ng_1;
|
||||
}
|
||||
if (bits_ng_128 > bits) {
|
||||
bits = bits_ng_128;
|
||||
}
|
||||
#else
|
||||
bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G);
|
||||
if (bits_ng > bits) {
|
||||
bits = bits_ng;
|
||||
}
|
||||
#endif
|
||||
|
||||
secp256k1_gej_set_infinity(r);
|
||||
|
||||
for (i = bits - 1; i >= 0; i--) {
|
||||
int n;
|
||||
secp256k1_gej_double_var(r, r, NULL);
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
if (i < bits_na_1 && (n = wnaf_na_1[i])) {
|
||||
ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A);
|
||||
secp256k1_gej_add_ge_var(r, r, &tmpa, NULL);
|
||||
}
|
||||
if (i < bits_na_lam && (n = wnaf_na_lam[i])) {
|
||||
ECMULT_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A);
|
||||
secp256k1_gej_add_ge_var(r, r, &tmpa, NULL);
|
||||
}
|
||||
if (i < bits_ng_1 && (n = wnaf_ng_1[i])) {
|
||||
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G);
|
||||
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
|
||||
}
|
||||
if (i < bits_ng_128 && (n = wnaf_ng_128[i])) {
|
||||
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G);
|
||||
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
|
||||
}
|
||||
#else
|
||||
if (i < bits_na && (n = wnaf_na[i])) {
|
||||
ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A);
|
||||
secp256k1_gej_add_ge_var(r, r, &tmpa, NULL);
|
||||
}
|
||||
if (i < bits_ng && (n = wnaf_ng[i])) {
|
||||
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G);
|
||||
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!r->infinity) {
|
||||
secp256k1_fe_mul(&r->z, &r->z, &Z);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
132
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field.h
generated
vendored
Normal file
132
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field.h
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_FIELD_
|
||||
#define _SECP256K1_FIELD_
|
||||
|
||||
/** Field element module.
|
||||
*
|
||||
* Field elements can be represented in several ways, but code accessing
|
||||
* it (and implementations) need to take certain properties into account:
|
||||
* - Each field element can be normalized or not.
|
||||
* - Each field element has a magnitude, which represents how far away
|
||||
* its representation is away from normalization. Normalized elements
|
||||
* always have a magnitude of 1, but a magnitude of 1 doesn't imply
|
||||
* normality.
|
||||
*/
|
||||
|
||||
#if defined HAVE_CONFIG_H
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_FIELD_10X26)
|
||||
#include "field_10x26.h"
|
||||
#elif defined(USE_FIELD_5X52)
|
||||
#include "field_5x52.h"
|
||||
#else
|
||||
#error "Please select field implementation"
|
||||
#endif
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/** Normalize a field element. */
|
||||
static void secp256k1_fe_normalize(secp256k1_fe *r);
|
||||
|
||||
/** Weakly normalize a field element: reduce it magnitude to 1, but don't fully normalize. */
|
||||
static void secp256k1_fe_normalize_weak(secp256k1_fe *r);
|
||||
|
||||
/** Normalize a field element, without constant-time guarantee. */
|
||||
static void secp256k1_fe_normalize_var(secp256k1_fe *r);
|
||||
|
||||
/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field
|
||||
* implementation may optionally normalize the input, but this should not be relied upon. */
|
||||
static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r);
|
||||
|
||||
/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field
|
||||
* implementation may optionally normalize the input, but this should not be relied upon. */
|
||||
static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r);
|
||||
|
||||
/** Set a field element equal to a small integer. Resulting field element is normalized. */
|
||||
static void secp256k1_fe_set_int(secp256k1_fe *r, int a);
|
||||
|
||||
/** Sets a field element equal to zero, initializing all fields. */
|
||||
static void secp256k1_fe_clear(secp256k1_fe *a);
|
||||
|
||||
/** Verify whether a field element is zero. Requires the input to be normalized. */
|
||||
static int secp256k1_fe_is_zero(const secp256k1_fe *a);
|
||||
|
||||
/** Check the "oddness" of a field element. Requires the input to be normalized. */
|
||||
static int secp256k1_fe_is_odd(const secp256k1_fe *a);
|
||||
|
||||
/** Compare two field elements. Requires magnitude-1 inputs. */
|
||||
static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b);
|
||||
|
||||
/** Same as secp256k1_fe_equal, but may be variable time. */
|
||||
static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b);
|
||||
|
||||
/** Compare two field elements. Requires both inputs to be normalized */
|
||||
static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b);
|
||||
|
||||
/** Set a field element equal to 32-byte big endian value. If successful, the resulting field element is normalized. */
|
||||
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a);
|
||||
|
||||
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
|
||||
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a);
|
||||
|
||||
/** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input
|
||||
* as an argument. The magnitude of the output is one higher. */
|
||||
static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
|
||||
|
||||
/** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that
|
||||
* small integer. */
|
||||
static void secp256k1_fe_mul_int(secp256k1_fe *r, int a);
|
||||
|
||||
/** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */
|
||||
static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a);
|
||||
|
||||
/** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8.
|
||||
* The output magnitude is 1 (but not guaranteed to be normalized). */
|
||||
static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b);
|
||||
|
||||
/** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8.
|
||||
* The output magnitude is 1 (but not guaranteed to be normalized). */
|
||||
static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a);
|
||||
|
||||
/** If a has a square root, it is computed in r and 1 is returned. If a does not
|
||||
* have a square root, the root of its negation is computed and 0 is returned.
|
||||
* The input's magnitude can be at most 8. The output magnitude is 1 (but not
|
||||
* guaranteed to be normalized). The result in r will always be a square
|
||||
* itself. */
|
||||
static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a);
|
||||
|
||||
/** Checks whether a field element is a quadratic residue. */
|
||||
static int secp256k1_fe_is_quad_var(const secp256k1_fe *a);
|
||||
|
||||
/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be
|
||||
* at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */
|
||||
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a);
|
||||
|
||||
/** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */
|
||||
static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a);
|
||||
|
||||
/** Calculate the (modular) inverses of a batch of field elements. Requires the inputs' magnitudes to be
|
||||
* at most 8. The output magnitudes are 1 (but not guaranteed to be normalized). The inputs and
|
||||
* outputs must not overlap in memory. */
|
||||
static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len);
|
||||
|
||||
/** Convert a field element to the storage type. */
|
||||
static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a);
|
||||
|
||||
/** Convert a field element back from the storage type. */
|
||||
static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a);
|
||||
|
||||
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
|
||||
static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag);
|
||||
|
||||
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
|
||||
static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
|
||||
|
||||
#endif
|
||||
47
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26.h
generated
vendored
Normal file
47
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26.h
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_FIELD_REPR_
|
||||
#define _SECP256K1_FIELD_REPR_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
/* X = sum(i=0..9, elem[i]*2^26) mod n */
|
||||
uint32_t n[10];
|
||||
#ifdef VERIFY
|
||||
int magnitude;
|
||||
int normalized;
|
||||
#endif
|
||||
} secp256k1_fe;
|
||||
|
||||
/* Unpacks a constant into a overlapping multi-limbed FE element. */
|
||||
#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \
|
||||
(d0) & 0x3FFFFFFUL, \
|
||||
(((uint32_t)d0) >> 26) | (((uint32_t)(d1) & 0xFFFFFUL) << 6), \
|
||||
(((uint32_t)d1) >> 20) | (((uint32_t)(d2) & 0x3FFFUL) << 12), \
|
||||
(((uint32_t)d2) >> 14) | (((uint32_t)(d3) & 0xFFUL) << 18), \
|
||||
(((uint32_t)d3) >> 8) | (((uint32_t)(d4) & 0x3UL) << 24), \
|
||||
(((uint32_t)d4) >> 2) & 0x3FFFFFFUL, \
|
||||
(((uint32_t)d4) >> 28) | (((uint32_t)(d5) & 0x3FFFFFUL) << 4), \
|
||||
(((uint32_t)d5) >> 22) | (((uint32_t)(d6) & 0xFFFFUL) << 10), \
|
||||
(((uint32_t)d6) >> 16) | (((uint32_t)(d7) & 0x3FFUL) << 16), \
|
||||
(((uint32_t)d7) >> 10) \
|
||||
}
|
||||
|
||||
#ifdef VERIFY
|
||||
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1}
|
||||
#else
|
||||
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))}
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t n[8];
|
||||
} secp256k1_fe_storage;
|
||||
|
||||
#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}
|
||||
#define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0]
|
||||
#endif
|
||||
1140
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h
generated
vendored
Normal file
1140
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
47
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52.h
generated
vendored
Normal file
47
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52.h
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_FIELD_REPR_
|
||||
#define _SECP256K1_FIELD_REPR_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
/* X = sum(i=0..4, elem[i]*2^52) mod n */
|
||||
uint64_t n[5];
|
||||
#ifdef VERIFY
|
||||
int magnitude;
|
||||
int normalized;
|
||||
#endif
|
||||
} secp256k1_fe;
|
||||
|
||||
/* Unpacks a constant into a overlapping multi-limbed FE element. */
|
||||
#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \
|
||||
(d0) | (((uint64_t)(d1) & 0xFFFFFUL) << 32), \
|
||||
((uint64_t)(d1) >> 20) | (((uint64_t)(d2)) << 12) | (((uint64_t)(d3) & 0xFFUL) << 44), \
|
||||
((uint64_t)(d3) >> 8) | (((uint64_t)(d4) & 0xFFFFFFFUL) << 24), \
|
||||
((uint64_t)(d4) >> 28) | (((uint64_t)(d5)) << 4) | (((uint64_t)(d6) & 0xFFFFUL) << 36), \
|
||||
((uint64_t)(d6) >> 16) | (((uint64_t)(d7)) << 16) \
|
||||
}
|
||||
|
||||
#ifdef VERIFY
|
||||
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1}
|
||||
#else
|
||||
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))}
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint64_t n[4];
|
||||
} secp256k1_fe_storage;
|
||||
|
||||
#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ \
|
||||
(d0) | (((uint64_t)(d1)) << 32), \
|
||||
(d2) | (((uint64_t)(d3)) << 32), \
|
||||
(d4) | (((uint64_t)(d5)) << 32), \
|
||||
(d6) | (((uint64_t)(d7)) << 32) \
|
||||
}}
|
||||
|
||||
#endif
|
||||
502
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h
generated
vendored
Normal file
502
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h
generated
vendored
Normal file
@@ -0,0 +1,502 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013-2014 Diederik Huys, Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
/**
|
||||
* Changelog:
|
||||
* - March 2013, Diederik Huys: original version
|
||||
* - November 2014, Pieter Wuille: updated to use Peter Dettman's parallel multiplication algorithm
|
||||
* - December 2014, Pieter Wuille: converted from YASM to GCC inline assembly
|
||||
*/
|
||||
|
||||
#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_
|
||||
#define _SECP256K1_FIELD_INNER5X52_IMPL_H_
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
|
||||
/**
|
||||
* Registers: rdx:rax = multiplication accumulator
|
||||
* r9:r8 = c
|
||||
* r15:rcx = d
|
||||
* r10-r14 = a0-a4
|
||||
* rbx = b
|
||||
* rdi = r
|
||||
* rsi = a / t?
|
||||
*/
|
||||
uint64_t tmp1, tmp2, tmp3;
|
||||
__asm__ __volatile__(
|
||||
"movq 0(%%rsi),%%r10\n"
|
||||
"movq 8(%%rsi),%%r11\n"
|
||||
"movq 16(%%rsi),%%r12\n"
|
||||
"movq 24(%%rsi),%%r13\n"
|
||||
"movq 32(%%rsi),%%r14\n"
|
||||
|
||||
/* d += a3 * b0 */
|
||||
"movq 0(%%rbx),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"movq %%rax,%%rcx\n"
|
||||
"movq %%rdx,%%r15\n"
|
||||
/* d += a2 * b1 */
|
||||
"movq 8(%%rbx),%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a1 * b2 */
|
||||
"movq 16(%%rbx),%%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d = a0 * b3 */
|
||||
"movq 24(%%rbx),%%rax\n"
|
||||
"mulq %%r10\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* c = a4 * b4 */
|
||||
"movq 32(%%rbx),%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"movq %%rax,%%r8\n"
|
||||
"movq %%rdx,%%r9\n"
|
||||
/* d += (c & M) * R */
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* c >>= 52 (%%r8 only) */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
/* t3 (tmp1) = d & M */
|
||||
"movq %%rcx,%%rsi\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rsi\n"
|
||||
"movq %%rsi,%q1\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%r15,%%rcx\n"
|
||||
"xorq %%r15,%%r15\n"
|
||||
/* d += a4 * b0 */
|
||||
"movq 0(%%rbx),%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a3 * b1 */
|
||||
"movq 8(%%rbx),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a2 * b2 */
|
||||
"movq 16(%%rbx),%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a1 * b3 */
|
||||
"movq 24(%%rbx),%%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a0 * b4 */
|
||||
"movq 32(%%rbx),%%rax\n"
|
||||
"mulq %%r10\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += c * R */
|
||||
"movq %%r8,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* t4 = d & M (%%rsi) */
|
||||
"movq %%rcx,%%rsi\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rsi\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%r15,%%rcx\n"
|
||||
"xorq %%r15,%%r15\n"
|
||||
/* tx = t4 >> 48 (tmp3) */
|
||||
"movq %%rsi,%%rax\n"
|
||||
"shrq $48,%%rax\n"
|
||||
"movq %%rax,%q3\n"
|
||||
/* t4 &= (M >> 4) (tmp2) */
|
||||
"movq $0xffffffffffff,%%rax\n"
|
||||
"andq %%rax,%%rsi\n"
|
||||
"movq %%rsi,%q2\n"
|
||||
/* c = a0 * b0 */
|
||||
"movq 0(%%rbx),%%rax\n"
|
||||
"mulq %%r10\n"
|
||||
"movq %%rax,%%r8\n"
|
||||
"movq %%rdx,%%r9\n"
|
||||
/* d += a4 * b1 */
|
||||
"movq 8(%%rbx),%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a3 * b2 */
|
||||
"movq 16(%%rbx),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a2 * b3 */
|
||||
"movq 24(%%rbx),%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a1 * b4 */
|
||||
"movq 32(%%rbx),%%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* u0 = d & M (%%rsi) */
|
||||
"movq %%rcx,%%rsi\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rsi\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%r15,%%rcx\n"
|
||||
"xorq %%r15,%%r15\n"
|
||||
/* u0 = (u0 << 4) | tx (%%rsi) */
|
||||
"shlq $4,%%rsi\n"
|
||||
"movq %q3,%%rax\n"
|
||||
"orq %%rax,%%rsi\n"
|
||||
/* c += u0 * (R >> 4) */
|
||||
"movq $0x1000003d1,%%rax\n"
|
||||
"mulq %%rsi\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* r[0] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rax\n"
|
||||
"movq %%rax,0(%%rdi)\n"
|
||||
/* c >>= 52 */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
"xorq %%r9,%%r9\n"
|
||||
/* c += a1 * b0 */
|
||||
"movq 0(%%rbx),%%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* c += a0 * b1 */
|
||||
"movq 8(%%rbx),%%rax\n"
|
||||
"mulq %%r10\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* d += a4 * b2 */
|
||||
"movq 16(%%rbx),%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a3 * b3 */
|
||||
"movq 24(%%rbx),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a2 * b4 */
|
||||
"movq 32(%%rbx),%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* c += (d & M) * R */
|
||||
"movq %%rcx,%%rax\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%r15,%%rcx\n"
|
||||
"xorq %%r15,%%r15\n"
|
||||
/* r[1] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rax\n"
|
||||
"movq %%rax,8(%%rdi)\n"
|
||||
/* c >>= 52 */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
"xorq %%r9,%%r9\n"
|
||||
/* c += a2 * b0 */
|
||||
"movq 0(%%rbx),%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* c += a1 * b1 */
|
||||
"movq 8(%%rbx),%%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* c += a0 * b2 (last use of %%r10 = a0) */
|
||||
"movq 16(%%rbx),%%rax\n"
|
||||
"mulq %%r10\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* fetch t3 (%%r10, overwrites a0), t4 (%%rsi) */
|
||||
"movq %q2,%%rsi\n"
|
||||
"movq %q1,%%r10\n"
|
||||
/* d += a4 * b3 */
|
||||
"movq 24(%%rbx),%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a3 * b4 */
|
||||
"movq 32(%%rbx),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* c += (d & M) * R */
|
||||
"movq %%rcx,%%rax\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* d >>= 52 (%%rcx only) */
|
||||
"shrdq $52,%%r15,%%rcx\n"
|
||||
/* r[2] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rax\n"
|
||||
"movq %%rax,16(%%rdi)\n"
|
||||
/* c >>= 52 */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
"xorq %%r9,%%r9\n"
|
||||
/* c += t3 */
|
||||
"addq %%r10,%%r8\n"
|
||||
/* c += d * R */
|
||||
"movq %%rcx,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* r[3] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rax\n"
|
||||
"movq %%rax,24(%%rdi)\n"
|
||||
/* c >>= 52 (%%r8 only) */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
/* c += t4 (%%r8 only) */
|
||||
"addq %%rsi,%%r8\n"
|
||||
/* r[4] = c */
|
||||
"movq %%r8,32(%%rdi)\n"
|
||||
: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3)
|
||||
: "b"(b), "D"(r)
|
||||
: "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) {
|
||||
/**
|
||||
* Registers: rdx:rax = multiplication accumulator
|
||||
* r9:r8 = c
|
||||
* rcx:rbx = d
|
||||
* r10-r14 = a0-a4
|
||||
* r15 = M (0xfffffffffffff)
|
||||
* rdi = r
|
||||
* rsi = a / t?
|
||||
*/
|
||||
uint64_t tmp1, tmp2, tmp3;
|
||||
__asm__ __volatile__(
|
||||
"movq 0(%%rsi),%%r10\n"
|
||||
"movq 8(%%rsi),%%r11\n"
|
||||
"movq 16(%%rsi),%%r12\n"
|
||||
"movq 24(%%rsi),%%r13\n"
|
||||
"movq 32(%%rsi),%%r14\n"
|
||||
"movq $0xfffffffffffff,%%r15\n"
|
||||
|
||||
/* d = (a0*2) * a3 */
|
||||
"leaq (%%r10,%%r10,1),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"movq %%rax,%%rbx\n"
|
||||
"movq %%rdx,%%rcx\n"
|
||||
/* d += (a1*2) * a2 */
|
||||
"leaq (%%r11,%%r11,1),%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* c = a4 * a4 */
|
||||
"movq %%r14,%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"movq %%rax,%%r8\n"
|
||||
"movq %%rdx,%%r9\n"
|
||||
/* d += (c & M) * R */
|
||||
"andq %%r15,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* c >>= 52 (%%r8 only) */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
/* t3 (tmp1) = d & M */
|
||||
"movq %%rbx,%%rsi\n"
|
||||
"andq %%r15,%%rsi\n"
|
||||
"movq %%rsi,%q1\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%rcx,%%rbx\n"
|
||||
"xorq %%rcx,%%rcx\n"
|
||||
/* a4 *= 2 */
|
||||
"addq %%r14,%%r14\n"
|
||||
/* d += a0 * a4 */
|
||||
"movq %%r10,%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* d+= (a1*2) * a3 */
|
||||
"leaq (%%r11,%%r11,1),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* d += a2 * a2 */
|
||||
"movq %%r12,%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* d += c * R */
|
||||
"movq %%r8,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* t4 = d & M (%%rsi) */
|
||||
"movq %%rbx,%%rsi\n"
|
||||
"andq %%r15,%%rsi\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%rcx,%%rbx\n"
|
||||
"xorq %%rcx,%%rcx\n"
|
||||
/* tx = t4 >> 48 (tmp3) */
|
||||
"movq %%rsi,%%rax\n"
|
||||
"shrq $48,%%rax\n"
|
||||
"movq %%rax,%q3\n"
|
||||
/* t4 &= (M >> 4) (tmp2) */
|
||||
"movq $0xffffffffffff,%%rax\n"
|
||||
"andq %%rax,%%rsi\n"
|
||||
"movq %%rsi,%q2\n"
|
||||
/* c = a0 * a0 */
|
||||
"movq %%r10,%%rax\n"
|
||||
"mulq %%r10\n"
|
||||
"movq %%rax,%%r8\n"
|
||||
"movq %%rdx,%%r9\n"
|
||||
/* d += a1 * a4 */
|
||||
"movq %%r11,%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* d += (a2*2) * a3 */
|
||||
"leaq (%%r12,%%r12,1),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* u0 = d & M (%%rsi) */
|
||||
"movq %%rbx,%%rsi\n"
|
||||
"andq %%r15,%%rsi\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%rcx,%%rbx\n"
|
||||
"xorq %%rcx,%%rcx\n"
|
||||
/* u0 = (u0 << 4) | tx (%%rsi) */
|
||||
"shlq $4,%%rsi\n"
|
||||
"movq %q3,%%rax\n"
|
||||
"orq %%rax,%%rsi\n"
|
||||
/* c += u0 * (R >> 4) */
|
||||
"movq $0x1000003d1,%%rax\n"
|
||||
"mulq %%rsi\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* r[0] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"andq %%r15,%%rax\n"
|
||||
"movq %%rax,0(%%rdi)\n"
|
||||
/* c >>= 52 */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
"xorq %%r9,%%r9\n"
|
||||
/* a0 *= 2 */
|
||||
"addq %%r10,%%r10\n"
|
||||
/* c += a0 * a1 */
|
||||
"movq %%r10,%%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* d += a2 * a4 */
|
||||
"movq %%r12,%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* d += a3 * a3 */
|
||||
"movq %%r13,%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* c += (d & M) * R */
|
||||
"movq %%rbx,%%rax\n"
|
||||
"andq %%r15,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%rcx,%%rbx\n"
|
||||
"xorq %%rcx,%%rcx\n"
|
||||
/* r[1] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"andq %%r15,%%rax\n"
|
||||
"movq %%rax,8(%%rdi)\n"
|
||||
/* c >>= 52 */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
"xorq %%r9,%%r9\n"
|
||||
/* c += a0 * a2 (last use of %%r10) */
|
||||
"movq %%r10,%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* fetch t3 (%%r10, overwrites a0),t4 (%%rsi) */
|
||||
"movq %q2,%%rsi\n"
|
||||
"movq %q1,%%r10\n"
|
||||
/* c += a1 * a1 */
|
||||
"movq %%r11,%%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* d += a3 * a4 */
|
||||
"movq %%r13,%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* c += (d & M) * R */
|
||||
"movq %%rbx,%%rax\n"
|
||||
"andq %%r15,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* d >>= 52 (%%rbx only) */
|
||||
"shrdq $52,%%rcx,%%rbx\n"
|
||||
/* r[2] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"andq %%r15,%%rax\n"
|
||||
"movq %%rax,16(%%rdi)\n"
|
||||
/* c >>= 52 */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
"xorq %%r9,%%r9\n"
|
||||
/* c += t3 */
|
||||
"addq %%r10,%%r8\n"
|
||||
/* c += d * R */
|
||||
"movq %%rbx,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* r[3] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"andq %%r15,%%rax\n"
|
||||
"movq %%rax,24(%%rdi)\n"
|
||||
/* c >>= 52 (%%r8 only) */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
/* c += t4 (%%r8 only) */
|
||||
"addq %%rsi,%%r8\n"
|
||||
/* r[4] = c */
|
||||
"movq %%r8,32(%%rdi)\n"
|
||||
: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3)
|
||||
: "D"(r)
|
||||
: "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
451
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h
generated
vendored
Normal file
451
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h
generated
vendored
Normal file
@@ -0,0 +1,451 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_FIELD_REPR_IMPL_H_
|
||||
#define _SECP256K1_FIELD_REPR_IMPL_H_
|
||||
|
||||
#if defined HAVE_CONFIG_H
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
#include "util.h"
|
||||
#include "num.h"
|
||||
#include "field.h"
|
||||
|
||||
#if defined(USE_ASM_X86_64)
|
||||
#include "field_5x52_asm_impl.h"
|
||||
#else
|
||||
#include "field_5x52_int128_impl.h"
|
||||
#endif
|
||||
|
||||
/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F,
|
||||
* represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular,
|
||||
* each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element
|
||||
* is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations
|
||||
* accept any input with magnitude at most M, and have different rules for propagating magnitude to their
|
||||
* output.
|
||||
*/
|
||||
|
||||
#ifdef VERIFY
|
||||
static void secp256k1_fe_verify(const secp256k1_fe *a) {
|
||||
const uint64_t *d = a->n;
|
||||
int m = a->normalized ? 1 : 2 * a->magnitude, r = 1;
|
||||
/* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */
|
||||
r &= (d[0] <= 0xFFFFFFFFFFFFFULL * m);
|
||||
r &= (d[1] <= 0xFFFFFFFFFFFFFULL * m);
|
||||
r &= (d[2] <= 0xFFFFFFFFFFFFFULL * m);
|
||||
r &= (d[3] <= 0xFFFFFFFFFFFFFULL * m);
|
||||
r &= (d[4] <= 0x0FFFFFFFFFFFFULL * m);
|
||||
r &= (a->magnitude >= 0);
|
||||
r &= (a->magnitude <= 2048);
|
||||
if (a->normalized) {
|
||||
r &= (a->magnitude <= 1);
|
||||
if (r && (d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) {
|
||||
r &= (d[0] < 0xFFFFEFFFFFC2FULL);
|
||||
}
|
||||
}
|
||||
VERIFY_CHECK(r == 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void secp256k1_fe_normalize(secp256k1_fe *r) {
|
||||
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
||||
|
||||
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
||||
uint64_t m;
|
||||
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
|
||||
|
||||
/* The first pass ensures the magnitude is 1, ... */
|
||||
t0 += x * 0x1000003D1ULL;
|
||||
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL;
|
||||
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1;
|
||||
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2;
|
||||
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3;
|
||||
|
||||
/* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
|
||||
VERIFY_CHECK(t4 >> 49 == 0);
|
||||
|
||||
/* At most a single final reduction is needed; check if the value is >= the field characteristic */
|
||||
x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL)
|
||||
& (t0 >= 0xFFFFEFFFFFC2FULL));
|
||||
|
||||
/* Apply the final reduction (for constant-time behaviour, we do it always) */
|
||||
t0 += x * 0x1000003D1ULL;
|
||||
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL;
|
||||
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL;
|
||||
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL;
|
||||
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL;
|
||||
|
||||
/* If t4 didn't carry to bit 48 already, then it should have after any final reduction */
|
||||
VERIFY_CHECK(t4 >> 48 == x);
|
||||
|
||||
/* Mask off the possible multiple of 2^256 from the final reduction */
|
||||
t4 &= 0x0FFFFFFFFFFFFULL;
|
||||
|
||||
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_fe_normalize_weak(secp256k1_fe *r) {
|
||||
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
||||
|
||||
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
||||
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
|
||||
|
||||
/* The first pass ensures the magnitude is 1, ... */
|
||||
t0 += x * 0x1000003D1ULL;
|
||||
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL;
|
||||
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL;
|
||||
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL;
|
||||
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL;
|
||||
|
||||
/* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
|
||||
VERIFY_CHECK(t4 >> 49 == 0);
|
||||
|
||||
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_fe_normalize_var(secp256k1_fe *r) {
|
||||
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
||||
|
||||
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
||||
uint64_t m;
|
||||
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
|
||||
|
||||
/* The first pass ensures the magnitude is 1, ... */
|
||||
t0 += x * 0x1000003D1ULL;
|
||||
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL;
|
||||
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1;
|
||||
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2;
|
||||
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3;
|
||||
|
||||
/* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
|
||||
VERIFY_CHECK(t4 >> 49 == 0);
|
||||
|
||||
/* At most a single final reduction is needed; check if the value is >= the field characteristic */
|
||||
x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL)
|
||||
& (t0 >= 0xFFFFEFFFFFC2FULL));
|
||||
|
||||
if (x) {
|
||||
t0 += 0x1000003D1ULL;
|
||||
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL;
|
||||
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL;
|
||||
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL;
|
||||
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL;
|
||||
|
||||
/* If t4 didn't carry to bit 48 already, then it should have after any final reduction */
|
||||
VERIFY_CHECK(t4 >> 48 == x);
|
||||
|
||||
/* Mask off the possible multiple of 2^256 from the final reduction */
|
||||
t4 &= 0x0FFFFFFFFFFFFULL;
|
||||
}
|
||||
|
||||
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) {
|
||||
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
||||
|
||||
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
|
||||
uint64_t z0, z1;
|
||||
|
||||
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
||||
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
|
||||
|
||||
/* The first pass ensures the magnitude is 1, ... */
|
||||
t0 += x * 0x1000003D1ULL;
|
||||
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; z0 = t0; z1 = t0 ^ 0x1000003D0ULL;
|
||||
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1;
|
||||
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2;
|
||||
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3;
|
||||
z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL;
|
||||
|
||||
/* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
|
||||
VERIFY_CHECK(t4 >> 49 == 0);
|
||||
|
||||
return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
|
||||
}
|
||||
|
||||
static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) {
|
||||
uint64_t t0, t1, t2, t3, t4;
|
||||
uint64_t z0, z1;
|
||||
uint64_t x;
|
||||
|
||||
t0 = r->n[0];
|
||||
t4 = r->n[4];
|
||||
|
||||
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
||||
x = t4 >> 48;
|
||||
|
||||
/* The first pass ensures the magnitude is 1, ... */
|
||||
t0 += x * 0x1000003D1ULL;
|
||||
|
||||
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
|
||||
z0 = t0 & 0xFFFFFFFFFFFFFULL;
|
||||
z1 = z0 ^ 0x1000003D0ULL;
|
||||
|
||||
/* Fast return path should catch the majority of cases */
|
||||
if ((z0 != 0ULL) & (z1 != 0xFFFFFFFFFFFFFULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
t1 = r->n[1];
|
||||
t2 = r->n[2];
|
||||
t3 = r->n[3];
|
||||
|
||||
t4 &= 0x0FFFFFFFFFFFFULL;
|
||||
|
||||
t1 += (t0 >> 52);
|
||||
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1;
|
||||
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2;
|
||||
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3;
|
||||
z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL;
|
||||
|
||||
/* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
|
||||
VERIFY_CHECK(t4 >> 49 == 0);
|
||||
|
||||
return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) {
|
||||
r->n[0] = a;
|
||||
r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) {
|
||||
const uint64_t *t = a->n;
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->normalized);
|
||||
secp256k1_fe_verify(a);
|
||||
#endif
|
||||
return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) {
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->normalized);
|
||||
secp256k1_fe_verify(a);
|
||||
#endif
|
||||
return a->n[0] & 1;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) {
|
||||
int i;
|
||||
#ifdef VERIFY
|
||||
a->magnitude = 0;
|
||||
a->normalized = 1;
|
||||
#endif
|
||||
for (i=0; i<5; i++) {
|
||||
a->n[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
||||
int i;
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->normalized);
|
||||
VERIFY_CHECK(b->normalized);
|
||||
secp256k1_fe_verify(a);
|
||||
secp256k1_fe_verify(b);
|
||||
#endif
|
||||
for (i = 4; i >= 0; i--) {
|
||||
if (a->n[i] > b->n[i]) {
|
||||
return 1;
|
||||
}
|
||||
if (a->n[i] < b->n[i]) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
|
||||
int i;
|
||||
r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
|
||||
for (i=0; i<32; i++) {
|
||||
int j;
|
||||
for (j=0; j<2; j++) {
|
||||
int limb = (8*i+4*j)/52;
|
||||
int shift = (8*i+4*j)%52;
|
||||
r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift;
|
||||
}
|
||||
}
|
||||
if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) {
|
||||
return 0;
|
||||
}
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
|
||||
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
|
||||
int i;
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->normalized);
|
||||
secp256k1_fe_verify(a);
|
||||
#endif
|
||||
for (i=0; i<32; i++) {
|
||||
int j;
|
||||
int c = 0;
|
||||
for (j=0; j<2; j++) {
|
||||
int limb = (8*i+4*j)/52;
|
||||
int shift = (8*i+4*j)%52;
|
||||
c |= ((a->n[limb] >> shift) & 0xF) << (4 * j);
|
||||
}
|
||||
r[31-i] = c;
|
||||
}
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->magnitude <= m);
|
||||
secp256k1_fe_verify(a);
|
||||
#endif
|
||||
r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0];
|
||||
r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1];
|
||||
r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[2];
|
||||
r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[3];
|
||||
r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4];
|
||||
#ifdef VERIFY
|
||||
r->magnitude = m + 1;
|
||||
r->normalized = 0;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
|
||||
r->n[0] *= a;
|
||||
r->n[1] *= a;
|
||||
r->n[2] *= a;
|
||||
r->n[3] *= a;
|
||||
r->n[4] *= a;
|
||||
#ifdef VERIFY
|
||||
r->magnitude *= a;
|
||||
r->normalized = 0;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||
#ifdef VERIFY
|
||||
secp256k1_fe_verify(a);
|
||||
#endif
|
||||
r->n[0] += a->n[0];
|
||||
r->n[1] += a->n[1];
|
||||
r->n[2] += a->n[2];
|
||||
r->n[3] += a->n[3];
|
||||
r->n[4] += a->n[4];
|
||||
#ifdef VERIFY
|
||||
r->magnitude += a->magnitude;
|
||||
r->normalized = 0;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->magnitude <= 8);
|
||||
VERIFY_CHECK(b->magnitude <= 8);
|
||||
secp256k1_fe_verify(a);
|
||||
secp256k1_fe_verify(b);
|
||||
VERIFY_CHECK(r != b);
|
||||
#endif
|
||||
secp256k1_fe_mul_inner(r->n, a->n, b->n);
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 0;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->magnitude <= 8);
|
||||
secp256k1_fe_verify(a);
|
||||
#endif
|
||||
secp256k1_fe_sqr_inner(r->n, a->n);
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 0;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
|
||||
uint64_t mask0, mask1;
|
||||
mask0 = flag + ~((uint64_t)0);
|
||||
mask1 = ~mask0;
|
||||
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
|
||||
r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1);
|
||||
r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1);
|
||||
r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
|
||||
r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1);
|
||||
#ifdef VERIFY
|
||||
if (a->magnitude > r->magnitude) {
|
||||
r->magnitude = a->magnitude;
|
||||
}
|
||||
r->normalized &= a->normalized;
|
||||
#endif
|
||||
}
|
||||
|
||||
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
|
||||
uint64_t mask0, mask1;
|
||||
mask0 = flag + ~((uint64_t)0);
|
||||
mask1 = ~mask0;
|
||||
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
|
||||
r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1);
|
||||
r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1);
|
||||
r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
|
||||
}
|
||||
|
||||
static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) {
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->normalized);
|
||||
#endif
|
||||
r->n[0] = a->n[0] | a->n[1] << 52;
|
||||
r->n[1] = a->n[1] >> 12 | a->n[2] << 40;
|
||||
r->n[2] = a->n[2] >> 24 | a->n[3] << 28;
|
||||
r->n[3] = a->n[3] >> 36 | a->n[4] << 16;
|
||||
}
|
||||
|
||||
static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) {
|
||||
r->n[0] = a->n[0] & 0xFFFFFFFFFFFFFULL;
|
||||
r->n[1] = a->n[0] >> 52 | ((a->n[1] << 12) & 0xFFFFFFFFFFFFFULL);
|
||||
r->n[2] = a->n[1] >> 40 | ((a->n[2] << 24) & 0xFFFFFFFFFFFFFULL);
|
||||
r->n[3] = a->n[2] >> 28 | ((a->n[3] << 36) & 0xFFFFFFFFFFFFFULL);
|
||||
r->n[4] = a->n[3] >> 16;
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
277
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h
generated
vendored
Normal file
277
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h
generated
vendored
Normal file
@@ -0,0 +1,277 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_
|
||||
#define _SECP256K1_FIELD_INNER5X52_IMPL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef VERIFY
|
||||
#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0)
|
||||
#else
|
||||
#define VERIFY_BITS(x, n) do { } while(0)
|
||||
#endif
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
|
||||
uint128_t c, d;
|
||||
uint64_t t3, t4, tx, u0;
|
||||
uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
|
||||
const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
|
||||
|
||||
VERIFY_BITS(a[0], 56);
|
||||
VERIFY_BITS(a[1], 56);
|
||||
VERIFY_BITS(a[2], 56);
|
||||
VERIFY_BITS(a[3], 56);
|
||||
VERIFY_BITS(a[4], 52);
|
||||
VERIFY_BITS(b[0], 56);
|
||||
VERIFY_BITS(b[1], 56);
|
||||
VERIFY_BITS(b[2], 56);
|
||||
VERIFY_BITS(b[3], 56);
|
||||
VERIFY_BITS(b[4], 52);
|
||||
VERIFY_CHECK(r != b);
|
||||
|
||||
/* [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n.
|
||||
* px is a shorthand for sum(a[i]*b[x-i], i=0..x).
|
||||
* Note that [x 0 0 0 0 0] = [x*R].
|
||||
*/
|
||||
|
||||
d = (uint128_t)a0 * b[3]
|
||||
+ (uint128_t)a1 * b[2]
|
||||
+ (uint128_t)a2 * b[1]
|
||||
+ (uint128_t)a3 * b[0];
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d 0 0 0] = [p3 0 0 0] */
|
||||
c = (uint128_t)a4 * b[4];
|
||||
VERIFY_BITS(c, 112);
|
||||
/* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
d += (c & M) * R; c >>= 52;
|
||||
VERIFY_BITS(d, 115);
|
||||
VERIFY_BITS(c, 60);
|
||||
/* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
t3 = d & M; d >>= 52;
|
||||
VERIFY_BITS(t3, 52);
|
||||
VERIFY_BITS(d, 63);
|
||||
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
|
||||
d += (uint128_t)a0 * b[4]
|
||||
+ (uint128_t)a1 * b[3]
|
||||
+ (uint128_t)a2 * b[2]
|
||||
+ (uint128_t)a3 * b[1]
|
||||
+ (uint128_t)a4 * b[0];
|
||||
VERIFY_BITS(d, 115);
|
||||
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
d += c * R;
|
||||
VERIFY_BITS(d, 116);
|
||||
/* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
t4 = d & M; d >>= 52;
|
||||
VERIFY_BITS(t4, 52);
|
||||
VERIFY_BITS(d, 64);
|
||||
/* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
tx = (t4 >> 48); t4 &= (M >> 4);
|
||||
VERIFY_BITS(tx, 4);
|
||||
VERIFY_BITS(t4, 48);
|
||||
/* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
|
||||
c = (uint128_t)a0 * b[0];
|
||||
VERIFY_BITS(c, 112);
|
||||
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
|
||||
d += (uint128_t)a1 * b[4]
|
||||
+ (uint128_t)a2 * b[3]
|
||||
+ (uint128_t)a3 * b[2]
|
||||
+ (uint128_t)a4 * b[1];
|
||||
VERIFY_BITS(d, 115);
|
||||
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
u0 = d & M; d >>= 52;
|
||||
VERIFY_BITS(u0, 52);
|
||||
VERIFY_BITS(d, 63);
|
||||
/* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
/* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
u0 = (u0 << 4) | tx;
|
||||
VERIFY_BITS(u0, 56);
|
||||
/* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
c += (uint128_t)u0 * (R >> 4);
|
||||
VERIFY_BITS(c, 115);
|
||||
/* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
r[0] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[0], 52);
|
||||
VERIFY_BITS(c, 61);
|
||||
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
|
||||
c += (uint128_t)a0 * b[1]
|
||||
+ (uint128_t)a1 * b[0];
|
||||
VERIFY_BITS(c, 114);
|
||||
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
|
||||
d += (uint128_t)a2 * b[4]
|
||||
+ (uint128_t)a3 * b[3]
|
||||
+ (uint128_t)a4 * b[2];
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
|
||||
c += (d & M) * R; d >>= 52;
|
||||
VERIFY_BITS(c, 115);
|
||||
VERIFY_BITS(d, 62);
|
||||
/* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
|
||||
r[1] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[1], 52);
|
||||
VERIFY_BITS(c, 63);
|
||||
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
|
||||
|
||||
c += (uint128_t)a0 * b[2]
|
||||
+ (uint128_t)a1 * b[1]
|
||||
+ (uint128_t)a2 * b[0];
|
||||
VERIFY_BITS(c, 114);
|
||||
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
|
||||
d += (uint128_t)a3 * b[4]
|
||||
+ (uint128_t)a4 * b[3];
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
c += (d & M) * R; d >>= 52;
|
||||
VERIFY_BITS(c, 115);
|
||||
VERIFY_BITS(d, 62);
|
||||
/* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
|
||||
/* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[2] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[2], 52);
|
||||
VERIFY_BITS(c, 63);
|
||||
/* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
c += d * R + t3;
|
||||
VERIFY_BITS(c, 100);
|
||||
/* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[3] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[3], 52);
|
||||
VERIFY_BITS(c, 48);
|
||||
/* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
c += t4;
|
||||
VERIFY_BITS(c, 49);
|
||||
/* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[4] = c;
|
||||
VERIFY_BITS(r[4], 49);
|
||||
/* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) {
|
||||
uint128_t c, d;
|
||||
uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
|
||||
int64_t t3, t4, tx, u0;
|
||||
const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
|
||||
|
||||
VERIFY_BITS(a[0], 56);
|
||||
VERIFY_BITS(a[1], 56);
|
||||
VERIFY_BITS(a[2], 56);
|
||||
VERIFY_BITS(a[3], 56);
|
||||
VERIFY_BITS(a[4], 52);
|
||||
|
||||
/** [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n.
|
||||
* px is a shorthand for sum(a[i]*a[x-i], i=0..x).
|
||||
* Note that [x 0 0 0 0 0] = [x*R].
|
||||
*/
|
||||
|
||||
d = (uint128_t)(a0*2) * a3
|
||||
+ (uint128_t)(a1*2) * a2;
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d 0 0 0] = [p3 0 0 0] */
|
||||
c = (uint128_t)a4 * a4;
|
||||
VERIFY_BITS(c, 112);
|
||||
/* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
d += (c & M) * R; c >>= 52;
|
||||
VERIFY_BITS(d, 115);
|
||||
VERIFY_BITS(c, 60);
|
||||
/* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
t3 = d & M; d >>= 52;
|
||||
VERIFY_BITS(t3, 52);
|
||||
VERIFY_BITS(d, 63);
|
||||
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
|
||||
a4 *= 2;
|
||||
d += (uint128_t)a0 * a4
|
||||
+ (uint128_t)(a1*2) * a3
|
||||
+ (uint128_t)a2 * a2;
|
||||
VERIFY_BITS(d, 115);
|
||||
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
d += c * R;
|
||||
VERIFY_BITS(d, 116);
|
||||
/* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
t4 = d & M; d >>= 52;
|
||||
VERIFY_BITS(t4, 52);
|
||||
VERIFY_BITS(d, 64);
|
||||
/* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
tx = (t4 >> 48); t4 &= (M >> 4);
|
||||
VERIFY_BITS(tx, 4);
|
||||
VERIFY_BITS(t4, 48);
|
||||
/* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
|
||||
c = (uint128_t)a0 * a0;
|
||||
VERIFY_BITS(c, 112);
|
||||
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
|
||||
d += (uint128_t)a1 * a4
|
||||
+ (uint128_t)(a2*2) * a3;
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
u0 = d & M; d >>= 52;
|
||||
VERIFY_BITS(u0, 52);
|
||||
VERIFY_BITS(d, 62);
|
||||
/* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
/* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
u0 = (u0 << 4) | tx;
|
||||
VERIFY_BITS(u0, 56);
|
||||
/* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
c += (uint128_t)u0 * (R >> 4);
|
||||
VERIFY_BITS(c, 113);
|
||||
/* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
r[0] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[0], 52);
|
||||
VERIFY_BITS(c, 61);
|
||||
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
|
||||
a0 *= 2;
|
||||
c += (uint128_t)a0 * a1;
|
||||
VERIFY_BITS(c, 114);
|
||||
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
|
||||
d += (uint128_t)a2 * a4
|
||||
+ (uint128_t)a3 * a3;
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
|
||||
c += (d & M) * R; d >>= 52;
|
||||
VERIFY_BITS(c, 115);
|
||||
VERIFY_BITS(d, 62);
|
||||
/* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
|
||||
r[1] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[1], 52);
|
||||
VERIFY_BITS(c, 63);
|
||||
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
|
||||
|
||||
c += (uint128_t)a0 * a2
|
||||
+ (uint128_t)a1 * a1;
|
||||
VERIFY_BITS(c, 114);
|
||||
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
|
||||
d += (uint128_t)a3 * a4;
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
c += (d & M) * R; d >>= 52;
|
||||
VERIFY_BITS(c, 115);
|
||||
VERIFY_BITS(d, 62);
|
||||
/* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[2] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[2], 52);
|
||||
VERIFY_BITS(c, 63);
|
||||
/* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
|
||||
c += d * R + t3;
|
||||
VERIFY_BITS(c, 100);
|
||||
/* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[3] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[3], 52);
|
||||
VERIFY_BITS(c, 48);
|
||||
/* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
c += t4;
|
||||
VERIFY_BITS(c, 49);
|
||||
/* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[4] = c;
|
||||
VERIFY_BITS(r[4], 49);
|
||||
/* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
}
|
||||
|
||||
#endif
|
||||
315
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_impl.h
generated
vendored
Normal file
315
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_impl.h
generated
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_FIELD_IMPL_H_
|
||||
#define _SECP256K1_FIELD_IMPL_H_
|
||||
|
||||
#if defined HAVE_CONFIG_H
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#if defined(USE_FIELD_10X26)
|
||||
#include "field_10x26_impl.h"
|
||||
#elif defined(USE_FIELD_5X52)
|
||||
#include "field_5x52_impl.h"
|
||||
#else
|
||||
#error "Please select field implementation"
|
||||
#endif
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) {
|
||||
secp256k1_fe na;
|
||||
secp256k1_fe_negate(&na, a, 1);
|
||||
secp256k1_fe_add(&na, b);
|
||||
return secp256k1_fe_normalizes_to_zero(&na);
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
||||
secp256k1_fe na;
|
||||
secp256k1_fe_negate(&na, a, 1);
|
||||
secp256k1_fe_add(&na, b);
|
||||
return secp256k1_fe_normalizes_to_zero_var(&na);
|
||||
}
|
||||
|
||||
static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||
/** Given that p is congruent to 3 mod 4, we can compute the square root of
|
||||
* a mod p as the (p+1)/4'th power of a.
|
||||
*
|
||||
* As (p+1)/4 is an even number, it will have the same result for a and for
|
||||
* (-a). Only one of these two numbers actually has a square root however,
|
||||
* so we test at the end by squaring and comparing to the input.
|
||||
* Also because (p+1)/4 is an even number, the computed square root is
|
||||
* itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)).
|
||||
*/
|
||||
secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
|
||||
int j;
|
||||
|
||||
/** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
|
||||
* { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
|
||||
* 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
|
||||
*/
|
||||
|
||||
secp256k1_fe_sqr(&x2, a);
|
||||
secp256k1_fe_mul(&x2, &x2, a);
|
||||
|
||||
secp256k1_fe_sqr(&x3, &x2);
|
||||
secp256k1_fe_mul(&x3, &x3, a);
|
||||
|
||||
x6 = x3;
|
||||
for (j=0; j<3; j++) {
|
||||
secp256k1_fe_sqr(&x6, &x6);
|
||||
}
|
||||
secp256k1_fe_mul(&x6, &x6, &x3);
|
||||
|
||||
x9 = x6;
|
||||
for (j=0; j<3; j++) {
|
||||
secp256k1_fe_sqr(&x9, &x9);
|
||||
}
|
||||
secp256k1_fe_mul(&x9, &x9, &x3);
|
||||
|
||||
x11 = x9;
|
||||
for (j=0; j<2; j++) {
|
||||
secp256k1_fe_sqr(&x11, &x11);
|
||||
}
|
||||
secp256k1_fe_mul(&x11, &x11, &x2);
|
||||
|
||||
x22 = x11;
|
||||
for (j=0; j<11; j++) {
|
||||
secp256k1_fe_sqr(&x22, &x22);
|
||||
}
|
||||
secp256k1_fe_mul(&x22, &x22, &x11);
|
||||
|
||||
x44 = x22;
|
||||
for (j=0; j<22; j++) {
|
||||
secp256k1_fe_sqr(&x44, &x44);
|
||||
}
|
||||
secp256k1_fe_mul(&x44, &x44, &x22);
|
||||
|
||||
x88 = x44;
|
||||
for (j=0; j<44; j++) {
|
||||
secp256k1_fe_sqr(&x88, &x88);
|
||||
}
|
||||
secp256k1_fe_mul(&x88, &x88, &x44);
|
||||
|
||||
x176 = x88;
|
||||
for (j=0; j<88; j++) {
|
||||
secp256k1_fe_sqr(&x176, &x176);
|
||||
}
|
||||
secp256k1_fe_mul(&x176, &x176, &x88);
|
||||
|
||||
x220 = x176;
|
||||
for (j=0; j<44; j++) {
|
||||
secp256k1_fe_sqr(&x220, &x220);
|
||||
}
|
||||
secp256k1_fe_mul(&x220, &x220, &x44);
|
||||
|
||||
x223 = x220;
|
||||
for (j=0; j<3; j++) {
|
||||
secp256k1_fe_sqr(&x223, &x223);
|
||||
}
|
||||
secp256k1_fe_mul(&x223, &x223, &x3);
|
||||
|
||||
/* The final result is then assembled using a sliding window over the blocks. */
|
||||
|
||||
t1 = x223;
|
||||
for (j=0; j<23; j++) {
|
||||
secp256k1_fe_sqr(&t1, &t1);
|
||||
}
|
||||
secp256k1_fe_mul(&t1, &t1, &x22);
|
||||
for (j=0; j<6; j++) {
|
||||
secp256k1_fe_sqr(&t1, &t1);
|
||||
}
|
||||
secp256k1_fe_mul(&t1, &t1, &x2);
|
||||
secp256k1_fe_sqr(&t1, &t1);
|
||||
secp256k1_fe_sqr(r, &t1);
|
||||
|
||||
/* Check that a square root was actually calculated */
|
||||
|
||||
secp256k1_fe_sqr(&t1, r);
|
||||
return secp256k1_fe_equal(&t1, a);
|
||||
}
|
||||
|
||||
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||
secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
|
||||
int j;
|
||||
|
||||
/** The binary representation of (p - 2) has 5 blocks of 1s, with lengths in
|
||||
* { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
|
||||
* [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
|
||||
*/
|
||||
|
||||
secp256k1_fe_sqr(&x2, a);
|
||||
secp256k1_fe_mul(&x2, &x2, a);
|
||||
|
||||
secp256k1_fe_sqr(&x3, &x2);
|
||||
secp256k1_fe_mul(&x3, &x3, a);
|
||||
|
||||
x6 = x3;
|
||||
for (j=0; j<3; j++) {
|
||||
secp256k1_fe_sqr(&x6, &x6);
|
||||
}
|
||||
secp256k1_fe_mul(&x6, &x6, &x3);
|
||||
|
||||
x9 = x6;
|
||||
for (j=0; j<3; j++) {
|
||||
secp256k1_fe_sqr(&x9, &x9);
|
||||
}
|
||||
secp256k1_fe_mul(&x9, &x9, &x3);
|
||||
|
||||
x11 = x9;
|
||||
for (j=0; j<2; j++) {
|
||||
secp256k1_fe_sqr(&x11, &x11);
|
||||
}
|
||||
secp256k1_fe_mul(&x11, &x11, &x2);
|
||||
|
||||
x22 = x11;
|
||||
for (j=0; j<11; j++) {
|
||||
secp256k1_fe_sqr(&x22, &x22);
|
||||
}
|
||||
secp256k1_fe_mul(&x22, &x22, &x11);
|
||||
|
||||
x44 = x22;
|
||||
for (j=0; j<22; j++) {
|
||||
secp256k1_fe_sqr(&x44, &x44);
|
||||
}
|
||||
secp256k1_fe_mul(&x44, &x44, &x22);
|
||||
|
||||
x88 = x44;
|
||||
for (j=0; j<44; j++) {
|
||||
secp256k1_fe_sqr(&x88, &x88);
|
||||
}
|
||||
secp256k1_fe_mul(&x88, &x88, &x44);
|
||||
|
||||
x176 = x88;
|
||||
for (j=0; j<88; j++) {
|
||||
secp256k1_fe_sqr(&x176, &x176);
|
||||
}
|
||||
secp256k1_fe_mul(&x176, &x176, &x88);
|
||||
|
||||
x220 = x176;
|
||||
for (j=0; j<44; j++) {
|
||||
secp256k1_fe_sqr(&x220, &x220);
|
||||
}
|
||||
secp256k1_fe_mul(&x220, &x220, &x44);
|
||||
|
||||
x223 = x220;
|
||||
for (j=0; j<3; j++) {
|
||||
secp256k1_fe_sqr(&x223, &x223);
|
||||
}
|
||||
secp256k1_fe_mul(&x223, &x223, &x3);
|
||||
|
||||
/* The final result is then assembled using a sliding window over the blocks. */
|
||||
|
||||
t1 = x223;
|
||||
for (j=0; j<23; j++) {
|
||||
secp256k1_fe_sqr(&t1, &t1);
|
||||
}
|
||||
secp256k1_fe_mul(&t1, &t1, &x22);
|
||||
for (j=0; j<5; j++) {
|
||||
secp256k1_fe_sqr(&t1, &t1);
|
||||
}
|
||||
secp256k1_fe_mul(&t1, &t1, a);
|
||||
for (j=0; j<3; j++) {
|
||||
secp256k1_fe_sqr(&t1, &t1);
|
||||
}
|
||||
secp256k1_fe_mul(&t1, &t1, &x2);
|
||||
for (j=0; j<2; j++) {
|
||||
secp256k1_fe_sqr(&t1, &t1);
|
||||
}
|
||||
secp256k1_fe_mul(r, a, &t1);
|
||||
}
|
||||
|
||||
static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||
#if defined(USE_FIELD_INV_BUILTIN)
|
||||
secp256k1_fe_inv(r, a);
|
||||
#elif defined(USE_FIELD_INV_NUM)
|
||||
secp256k1_num n, m;
|
||||
static const secp256k1_fe negone = SECP256K1_FE_CONST(
|
||||
0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL,
|
||||
0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, 0xFFFFFC2EUL
|
||||
);
|
||||
/* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */
|
||||
static const unsigned char prime[32] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F
|
||||
};
|
||||
unsigned char b[32];
|
||||
int res;
|
||||
secp256k1_fe c = *a;
|
||||
secp256k1_fe_normalize_var(&c);
|
||||
secp256k1_fe_get_b32(b, &c);
|
||||
secp256k1_num_set_bin(&n, b, 32);
|
||||
secp256k1_num_set_bin(&m, prime, 32);
|
||||
secp256k1_num_mod_inverse(&n, &n, &m);
|
||||
secp256k1_num_get_bin(b, 32, &n);
|
||||
res = secp256k1_fe_set_b32(r, b);
|
||||
(void)res;
|
||||
VERIFY_CHECK(res);
|
||||
/* Verify the result is the (unique) valid inverse using non-GMP code. */
|
||||
secp256k1_fe_mul(&c, &c, r);
|
||||
secp256k1_fe_add(&c, &negone);
|
||||
CHECK(secp256k1_fe_normalizes_to_zero_var(&c));
|
||||
#else
|
||||
#error "Please select field inverse implementation"
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len) {
|
||||
secp256k1_fe u;
|
||||
size_t i;
|
||||
if (len < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
VERIFY_CHECK((r + len <= a) || (a + len <= r));
|
||||
|
||||
r[0] = a[0];
|
||||
|
||||
i = 0;
|
||||
while (++i < len) {
|
||||
secp256k1_fe_mul(&r[i], &r[i - 1], &a[i]);
|
||||
}
|
||||
|
||||
secp256k1_fe_inv_var(&u, &r[--i]);
|
||||
|
||||
while (i > 0) {
|
||||
size_t j = i--;
|
||||
secp256k1_fe_mul(&r[j], &r[i], &u);
|
||||
secp256k1_fe_mul(&u, &u, &a[j]);
|
||||
}
|
||||
|
||||
r[0] = u;
|
||||
}
|
||||
|
||||
static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) {
|
||||
#ifndef USE_NUM_NONE
|
||||
unsigned char b[32];
|
||||
secp256k1_num n;
|
||||
secp256k1_num m;
|
||||
/* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */
|
||||
static const unsigned char prime[32] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F
|
||||
};
|
||||
|
||||
secp256k1_fe c = *a;
|
||||
secp256k1_fe_normalize_var(&c);
|
||||
secp256k1_fe_get_b32(b, &c);
|
||||
secp256k1_num_set_bin(&n, b, 32);
|
||||
secp256k1_num_set_bin(&m, prime, 32);
|
||||
return secp256k1_num_jacobi(&n, &m) >= 0;
|
||||
#else
|
||||
secp256k1_fe r;
|
||||
return secp256k1_fe_sqrt(&r, a);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user