Initial commit of CLI client

This commit is contained in:
Cassandra Heart 2023-04-15 00:05:26 -04:00
commit e6ef405c62
No known key found for this signature in database
GPG Key ID: 6352152859385958
38 changed files with 83496 additions and 0 deletions

65808
basis.json Normal file

File diff suppressed because it is too large Load Diff

251
bootstrap.go Normal file
View File

@ -0,0 +1,251 @@
package main
import (
"bytes"
"crypto"
"crypto/rand"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"
"github.com/cloudflare/circl/sign/ed448"
bls48581 "source.quilibrium.com/quilibrium/ceremonyclient/ec/bls48581"
)
const SEQUENCER_ACCEPTING = "\"ACCEPTING\""
type PowersOfTauJson struct {
G1Affines []string `json:"G1Powers"`
G2Affines []string `json:"G2Powers"`
}
type ContributionJson struct {
PowersOfTau PowersOfTauJson `json:"powersOfTau"`
PotPubKey string `json:"potPubKey"`
VoucherPubKey string `json:"voucherPubKey"`
}
type BatchContribution struct {
Contribution Contribution
}
type PowersOfTau struct {
G1Affines []*bls48581.ECP
G2Affines []*bls48581.ECP8
}
type Contribution struct {
NumG1Powers int
NumG2Powers int
PowersOfTau PowersOfTau
PotPubKey *bls48581.ECP8
}
var voucherPubKey ed448.PublicKey
var voucher ed448.PrivateKey
var secret *bls48581.BIG
var bcj *ContributionJson = &ContributionJson{}
func JoinLobby() {
var err error
if voucherPubKey == nil {
voucherPubKey, voucher, err = ed448.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
}
sig, err := voucher.Sign(rand.Reader, []byte("JOIN"), ed448.SignerOptions{Hash: crypto.Hash(0), Scheme: ed448.ED448})
if err != nil {
panic(err)
}
reqHex := hex.EncodeToString(voucherPubKey)
sigHex := hex.EncodeToString(sig)
req, err := http.NewRequest("POST", HOST+"join", bytes.NewBuffer([]byte(reqHex)))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "text/plain")
req.Header.Set("Authorization", sigHex)
client := http.DefaultClient
resp, err := client.Do(req)
fmt.Println("connected")
if err != nil {
panic(err)
} else {
_, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
} else {
return
}
}
}
func GetSequencerState() string {
req, err := http.NewRequest("POST", HOST+"sequencer_state", bytes.NewBuffer([]byte("{}")))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
client := http.DefaultClient
resp, err := client.Do(req)
if err != nil {
panic(err)
}
sequencerState, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
return string(sequencerState)
}
func Bootstrap(batch uint, batchSize uint) {
if batch == 65536/batchSize {
return
}
if batch == 0 {
secretBytes := make([]byte, (8 * int(bls48581.MODBYTES)))
rand.Read(secretBytes)
secret = bls48581.FromBytes(secretBytes)
bcjRes, err := http.DefaultClient.Post(HOST+"current_state", "application/json", bytes.NewBufferString("{}"))
if err != nil {
panic(err)
}
defer bcjRes.Body.Close()
bcjBytes, err := io.ReadAll(bcjRes.Body)
if err != nil {
panic(err)
}
if err := json.Unmarshal(bcjBytes, bcj); err != nil {
// message is not conformant, we are in validating phase
panic(err)
}
}
contributeWithSecrets(batch, batchSize, secret)
fmt.Printf("Participating... %f%% Complete\n", float32(batch*batchSize)/655.36)
}
func contributeWithSecrets(batch uint, batchSize uint, secret *bls48581.BIG) error {
updatePowersOfTau(batch, batchSize, secret)
if batch == 0 {
updateWitness(secret)
}
return nil
}
var xi *bls48581.BIG
var xi2 *bls48581.BIG
func updatePowersOfTau(batch uint, batchSize uint, secret *bls48581.BIG) {
if batch == 0 {
xi = bls48581.NewBIGint(1)
xi2 = bls48581.NewBIGint(1)
}
for i := batchSize * batch; i < batchSize*(batch+1); i++ {
g1PowersString := strings.TrimPrefix(bcj.PowersOfTau.G1Affines[i], "0x")
g1PowersHex, _ := hex.DecodeString(g1PowersString)
g1Power := bls48581.ECP_fromBytes(g1PowersHex)
if g1Power.Equals(bls48581.NewECP()) {
panic("invalid g1Power")
}
g1Power = g1Power.Mul(xi)
g1Power.ToBytes(g1PowersHex, true)
bcj.PowersOfTau.G1Affines[i] = "0x" + hex.EncodeToString(g1PowersHex)
if (i%batchSize == 0) && i < uint(257*batchSize) {
g2PowersString := strings.TrimPrefix(bcj.PowersOfTau.G2Affines[i/batchSize], "0x")
g2PowersHex, _ := hex.DecodeString(g2PowersString)
g2Power := bls48581.ECP8_fromBytes(g2PowersHex)
if g2Power.Equals(bls48581.NewECP8()) {
panic("invalid g1Power")
}
g2Power = g2Power.Mul(xi2)
g2Power.ToBytes(g2PowersHex, true)
bcj.PowersOfTau.G2Affines[i/batchSize] = "0x" + hex.EncodeToString(g2PowersHex)
xi2 = bls48581.Modmul(xi2, secret, bls48581.NewBIGints(bls48581.Modulus))
}
xi = bls48581.Modmul(xi, secret, bls48581.NewBIGints(bls48581.Modulus))
}
}
func updateWitness(secret *bls48581.BIG) {
g2PowersString := strings.TrimPrefix(bcj.PotPubKey, "0x")
g2PowersHex, _ := hex.DecodeString(g2PowersString)
g2Power := bls48581.ECP8_fromBytes(g2PowersHex)
if g2Power.Equals(bls48581.NewECP8()) {
panic("invalid g2Power")
}
newPotPubKey := g2Power.Mul(secret)
newPotPubKey.ToBytes(g2PowersHex, true)
bcj.PotPubKey = "0x" + hex.EncodeToString(g2PowersHex)
bcj.VoucherPubKey = "0x" + hex.EncodeToString(voucherPubKey)
}
func ContributeAndGetVoucher() {
sendBytes, err := json.Marshal(bcj)
if err != nil {
panic(err)
}
req, err := http.NewRequest("POST", HOST+"contribute", bytes.NewBuffer(sendBytes))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
sig, err := voucher.Sign(rand.Reader, []byte(bcj.PotPubKey), ed448.SignerOptions{Hash: crypto.Hash(0), Scheme: ed448.ED448})
if err != nil {
panic(err)
}
sigHex := hex.EncodeToString(sig)
req.Header.Set("Authorization", sigHex)
client := http.DefaultClient
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
filename := "quil_voucher.hex"
if len(os.Args) > 1 {
filename = os.Args[1]
} else {
fmt.Println("Voucher file name not provided, writing to quil_voucher.hex")
}
if err := os.WriteFile(filename, []byte(hex.EncodeToString(voucher)), 0644); err != nil {
fmt.Println("Could not write voucher to file, voucher hex string below:")
fmt.Println(hex.EncodeToString(voucher))
}
}

27
ec/bls48581/ARCH.go Normal file
View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* core BIG number class */
package bls48581
type Chunk int32
type DChunk int64
const CHUNK int = 32 /* Set word size */

1023
ec/bls48581/BIG.go Normal file

File diff suppressed because it is too large Load Diff

155
ec/bls48581/BLS256.go Normal file
View File

@ -0,0 +1,155 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* Boneh-Lynn-Shacham signature 256-bit API Functions */
/* Loosely (for now) following https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-02 */
// Minimal-signature-size variant
package bls48581
import "source.quilibrium.com/quilibrium/ceremonyclient/ec/bls48581/core"
//import "fmt"
const BFS int = int(MODBYTES)
const BGS int = int(MODBYTES)
const BLS_OK int = 0
const BLS_FAIL int = -1
var G2_TAB []*FP16
func ceil(a int, b int) int {
return (((a)-1)/(b) + 1)
}
/* output u \in F_p */
func hash_to_field(hash int, hlen int, DST []byte, M []byte, ctr int) []*FP {
q := NewBIGints(Modulus)
nbq := q.nbits()
L := ceil(nbq+AESKEY*8, 8)
var u []*FP
var fd = make([]byte, L)
OKM := core.XMD_Expand(hash, hlen, L*ctr, DST, M)
for i := 0; i < ctr; i++ {
for j := 0; j < L; j++ {
fd[j] = OKM[i*L+j]
}
u = append(u, NewFPbig(DBIG_fromBytes(fd).ctmod(q, uint(8*L-nbq))))
}
return u
}
/* hash a message to an ECP point, using SHA2, random oracle method */
func bls256_hash_to_point(M []byte) *ECP {
DST := []byte("BLS_SIG_BLS48581G1_XMD:SHA-512_SVDW_RO_NUL_")
u := hash_to_field(core.MC_SHA2, HASH_TYPE, DST, M, 2)
P := ECP_map2point(u[0])
P1 := ECP_map2point(u[1])
P.Add(P1)
P.Cfp()
P.Affine()
return P
}
func Init() int {
G := ECP8_generator()
if G.Is_infinity() {
return BLS_FAIL
}
G2_TAB = precomp(G)
return BLS_OK
}
/* generate key pair, private key S, public key W */
func KeyPairGenerate(IKM []byte, S []byte, W []byte) int {
r := NewBIGints(CURVE_Order)
nbr := r.nbits()
L := ceil(3*ceil(nbr, 8), 2)
LEN := core.InttoBytes(L, 2)
AIKM := make([]byte, len(IKM)+1)
for i := 0; i < len(IKM); i++ {
AIKM[i] = IKM[i]
}
AIKM[len(IKM)] = 0
G := ECP8_generator()
if G.Is_infinity() {
return BLS_FAIL
}
SALT := []byte("BLS-SIG-KEYGEN-SALT-")
PRK := core.HKDF_Extract(core.MC_SHA2, HASH_TYPE, SALT, AIKM)
OKM := core.HKDF_Expand(core.MC_SHA2, HASH_TYPE, L, PRK, LEN)
dx := DBIG_fromBytes(OKM[:])
s := dx.ctmod(r, uint(8*L-nbr))
s.ToBytes(S)
// SkToPk
G = G2mul(G, s)
G.ToBytes(W, true)
return BLS_OK
}
/* Sign message m using private key S to produce signature SIG */
func Core_Sign(SIG []byte, M []byte, S []byte) int {
D := bls256_hash_to_point(M)
s := FromBytes(S)
D = G1mul(D, s)
D.ToBytes(SIG, true)
return BLS_OK
}
/* Verify signature given message M, the signature SIG, and the public key W */
func Core_Verify(SIG []byte, M []byte, W []byte) int {
HM := bls256_hash_to_point(M)
D := ECP_fromBytes(SIG)
if !G1member(D) {
return BLS_FAIL
}
D.Neg()
PK := ECP8_fromBytes(W)
if !G2member(PK) {
return BLS_FAIL
}
// Use new multi-pairing mechanism
r := Initmp()
Another_pc(r, G2_TAB, D)
Another(r, PK, HM)
v := Miller(r)
//.. or alternatively
// G := ECP8_generator()
// if G.Is_infinity() {return BLS_FAIL}
// v := Ate2(G, D, PK, HM)
v = Fexp(v)
if v.Isunity() {
return BLS_OK
} else {
return BLS_FAIL
}
}

34
ec/bls48581/CONFIG_BIG.go Normal file
View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
package bls48581
// BIG length in bytes and number base
const MODBYTES uint = 73
const BASEBITS uint = 29
// BIG lengths and Masks
const NLEN int = int((1 + ((8*MODBYTES - 1) / BASEBITS)))
const DNLEN int = 2 * NLEN
const BMASK Chunk = ((Chunk(1) << BASEBITS) - 1)
const HBITS uint = (BASEBITS / 2)
const HMASK Chunk = ((Chunk(1) << HBITS) - 1)
const NEXCESS int = (1 << (uint(CHUNK) - BASEBITS - 1))
const BIGBITS int = int(MODBYTES * 8)

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
package bls48581
// Curve types
const WEIERSTRASS int = 0
const EDWARDS int = 1
const MONTGOMERY int = 2
// Pairing Friendly?
const NOT int = 0
const BN int = 1
const BLS12 int = 2
const BLS24 int = 3
const BLS48 int = 4
// Pairing Twist type
const D_TYPE int = 0
const M_TYPE int = 1
// Sparsity
const FP_ZERO int = 0
const FP_ONE int = 1
const FP_SPARSEST int = 2
const FP_SPARSER int = 3
const FP_SPARSE int = 4
const FP_DENSE int = 5
// Pairing x parameter sign
const POSITIVEX int = 0
const NEGATIVEX int = 1
// Curve type
const CURVETYPE int = WEIERSTRASS
const CURVE_A int = 0
const CURVE_PAIRING_TYPE int = BLS48
// Pairings only
const SEXTIC_TWIST int = D_TYPE
const SIGN_OF_X int = NEGATIVEX
const ATE_BITS int = 33
const G2_TABLE int = 36
const HTC_ISO int = 0
const HTC_ISO_G2 int = 0
// associated hash function and AES key size
const HASH_TYPE int = 64
const AESKEY int = 32
const ALLOW_ALT_COMPRESS bool = false
// These are manually decided policy decisions. To block any potential patent issues set to false.
const USE_GLV bool = true
const USE_GS_G2 bool = true
const USE_GS_GT bool = true

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
package bls48581
// Modulus types
const NOT_SPECIAL int = 0
const PSEUDO_MERSENNE int = 1
const MONTGOMERY_FRIENDLY int = 2
const GENERALISED_MERSENNE int = 3
const NEGATOWER int = 0
const POSITOWER int = 1
// Modulus details
const MODBITS uint = 581 /* Number of bits in Modulus */
const PM1D2 uint = 1 /* Modulus mod 8 */
const RIADZ int = 2 /* hash-to-point Z */
const RIADZG2A int = 2 /* G2 hash-to-point Z */
const RIADZG2B int = 0 /* G2 hash-to-point Z */
const MODTYPE int = NOT_SPECIAL //NOT_SPECIAL
const QNRI int = 0 // Fp2 QNR
const TOWER int = POSITOWER // Tower type
const FEXCESS int32 = ((int32(1) << 14) - 1)
// Modulus Masks
const OMASK Chunk = ((Chunk(-1)) << (MODBITS % BASEBITS))
const TBITS uint = MODBITS % BASEBITS // Number of active bits in top word
const TMASK Chunk = (Chunk(1) << TBITS) - 1
const BIG_ENDIAN_SIGN bool = false

298
ec/bls48581/DBIG.go Normal file
View File

@ -0,0 +1,298 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* MiotCL double length DBIG number class */
package bls48581
import "strconv"
//import "fmt"
func NewDBIG() *DBIG {
b := new(DBIG)
for i := 0; i < DNLEN; i++ {
b.w[i] = 0
}
return b
}
func NewDBIGcopy(x *DBIG) *DBIG {
b := new(DBIG)
for i := 0; i < DNLEN; i++ {
b.w[i] = x.w[i]
}
return b
}
func NewDBIGscopy(x *BIG) *DBIG {
b := new(DBIG)
for i := 0; i < NLEN-1; i++ {
b.w[i] = x.w[i]
}
b.w[NLEN-1] = x.get(NLEN-1) & BMASK /* top word normalized */
b.w[NLEN] = x.get(NLEN-1) >> BASEBITS
for i := NLEN + 1; i < DNLEN; i++ {
b.w[i] = 0
}
return b
}
/* normalise this */
func (r *DBIG) norm() {
carry := Chunk(0)
for i := 0; i < DNLEN-1; i++ {
d := r.w[i] + carry
r.w[i] = d & BMASK
carry = d >> BASEBITS
}
r.w[DNLEN-1] = (r.w[DNLEN-1] + carry)
}
/* split DBIG at position n, return higher half, keep lower half */
func (r *DBIG) split(n uint) *BIG {
t := NewBIG()
m := n % BASEBITS
carry := r.w[DNLEN-1] << (BASEBITS - m)
for i := DNLEN - 2; i >= NLEN-1; i-- {
nw := (r.w[i] >> m) | carry
carry = (r.w[i] << (BASEBITS - m)) & BMASK
t.set(i-NLEN+1, nw)
}
r.w[NLEN-1] &= ((Chunk(1) << m) - 1)
return t
}
func (r *DBIG) cmove(g *DBIG, d int) Chunk {
var b = Chunk(-d)
s := Chunk(0)
v := r.w[0] ^ g.w[1]
va := v + v
va >>= 1
for i := 0; i < DNLEN; i++ {
t := (r.w[i] ^ g.w[i]) & b
t ^= v
e := r.w[i] ^ t
s ^= e
r.w[i] = e ^ va
}
return s
}
/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
func dcomp(a *DBIG, b *DBIG) int {
gt := Chunk(0)
eq := Chunk(1)
for i := DNLEN - 1; i >= 0; i-- {
gt |= ((b.w[i] - a.w[i]) >> BASEBITS) & eq
eq &= ((b.w[i] ^ a.w[i]) - 1) >> BASEBITS
}
return int(gt + gt + eq - 1)
}
/* Copy from another DBIG */
func (r *DBIG) copy(x *DBIG) {
for i := 0; i < DNLEN; i++ {
r.w[i] = x.w[i]
}
}
/* Copy from another BIG to upper half */
func (r *DBIG) ucopy(x *BIG) {
for i := 0; i < NLEN; i++ {
r.w[i] = 0
}
for i := NLEN; i < DNLEN; i++ {
r.w[i] = x.w[i-NLEN]
}
}
func (r *DBIG) add(x *DBIG) {
for i := 0; i < DNLEN; i++ {
r.w[i] = r.w[i] + x.w[i]
}
}
/* this-=x */
func (r *DBIG) sub(x *DBIG) {
for i := 0; i < DNLEN; i++ {
r.w[i] = r.w[i] - x.w[i]
}
}
/* this-=x */
func (r *DBIG) rsub(x *DBIG) {
for i := 0; i < DNLEN; i++ {
r.w[i] = x.w[i] - r.w[i]
}
}
/* general shift left */
func (r *DBIG) shl(k uint) {
n := k % BASEBITS
m := int(k / BASEBITS)
r.w[DNLEN-1] = (r.w[DNLEN-1-m] << n) | (r.w[DNLEN-m-2] >> (BASEBITS - n))
for i := DNLEN - 2; i > m; i-- {
r.w[i] = ((r.w[i-m] << n) & BMASK) | (r.w[i-m-1] >> (BASEBITS - n))
}
r.w[m] = (r.w[0] << n) & BMASK
for i := 0; i < m; i++ {
r.w[i] = 0
}
}
/* general shift right */
func (r *DBIG) shr(k uint) {
n := (k % BASEBITS)
m := int(k / BASEBITS)
for i := 0; i < DNLEN-m-1; i++ {
r.w[i] = (r.w[m+i] >> n) | ((r.w[m+i+1] << (BASEBITS - n)) & BMASK)
}
r.w[DNLEN-m-1] = r.w[DNLEN-1] >> n
for i := DNLEN - m; i < DNLEN; i++ {
r.w[i] = 0
}
}
func (r *DBIG) ctmod(m *BIG, bd uint) *BIG {
k := bd
r.norm()
c := NewDBIGscopy(m)
dr := NewDBIG()
c.shl(k)
for {
dr.copy(r)
dr.sub(c)
dr.norm()
r.cmove(dr, int(1-((dr.w[DNLEN-1]>>uint(CHUNK-1))&1)))
if k == 0 {
break
}
k -= 1
c.shr(1)
}
return NewBIGdcopy(r)
}
/* reduces this DBIG mod a BIG, and returns the BIG */
func (r *DBIG) Mod(m *BIG) *BIG {
k := r.nbits() - m.nbits()
if k < 0 {
k = 0
}
return r.ctmod(m, uint(k))
}
func (r *DBIG) ctdiv(m *BIG, bd uint) *BIG {
k := bd
c := NewDBIGscopy(m)
a := NewBIGint(0)
e := NewBIGint(1)
sr := NewBIG()
dr := NewDBIG()
r.norm()
c.shl(k)
e.shl(k)
for {
dr.copy(r)
dr.sub(c)
dr.norm()
d := int(1 - ((dr.w[DNLEN-1] >> uint(CHUNK-1)) & 1))
r.cmove(dr, d)
sr.copy(a)
sr.add(e)
sr.norm()
a.cmove(sr, d)
if k == 0 {
break
}
k -= 1
c.shr(1)
e.shr(1)
}
return a
}
/* return this/c */
func (r *DBIG) div(m *BIG) *BIG {
k := r.nbits() - m.nbits()
if k < 0 {
k = 0
}
return r.ctdiv(m, uint(k))
}
/* Convert to Hex String */
func (r *DBIG) toString() string {
s := ""
len := r.nbits()
if len%4 == 0 {
len /= 4
} else {
len /= 4
len++
}
for i := len - 1; i >= 0; i-- {
b := NewDBIGcopy(r)
b.shr(uint(i * 4))
s += strconv.FormatInt(int64(b.w[0]&15), 16)
}
return s
}
/* return number of bits */
func (r *DBIG) nbits() int {
k := DNLEN - 1
t := NewDBIGcopy(r)
t.norm()
for k >= 0 && t.w[k] == 0 {
k--
}
if k < 0 {
return 0
}
bts := int(BASEBITS) * k
c := t.w[k]
for c != 0 {
c /= 2
bts++
}
return bts
}
/* convert from byte array to BIG */
func DBIG_fromBytes(b []byte) *DBIG {
m := NewDBIG()
for i := 0; i < len(b); i++ {
m.shl(8)
m.w[0] += Chunk(int(b[i] & 0xff))
}
return m
}

381
ec/bls48581/ECDH.go Normal file
View File

@ -0,0 +1,381 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* ECDH/ECIES/ECDSA API Functions */
package bls48581
//import "fmt"
import "source.quilibrium.com/quilibrium/ceremonyclient/ec/bls48581/core"
const INVALID_PUBLIC_KEY int = -2
const ERROR int = -3
//const INVALID int = -4
const EFS int = int(MODBYTES)
const EGS int = int(MODBYTES)
// Transform a point multiplier to RFC7748 form
func RFC7748(r *BIG) {
lg := 0
t := NewBIGint(1)
c := CURVE_Cof_I
for c != 1 {
lg++
c /= 2
}
n := uint(8*EGS - lg + 1)
r.mod2m(n)
t.shl(n)
r.add(t)
c = r.lastbits(lg)
r.dec(c)
}
/* return true if S is in ranger 0 < S < order , else return false */
func ECDH_IN_RANGE(S []byte) bool {
r := NewBIGints(CURVE_Order)
s := FromBytes(S)
if s.iszilch() {
return false
}
if Comp(s, r) >= 0 {
return false
}
return true
}
/* Calculate a public/private EC GF(p) key pair W,S where W=S.G mod EC(p),
* where S is the secret key and W is the public key
* and G is fixed generator.
* If RNG is NULL then the private key is provided externally in S
* otherwise it is generated randomly internally */
func ECDH_KEY_PAIR_GENERATE(RNG *core.RAND, S []byte, W []byte) int {
res := 0
var s *BIG
var G *ECP
G = ECP_generator()
r := NewBIGints(CURVE_Order)
if RNG == nil {
s = FromBytes(S)
} else {
if CURVETYPE != WEIERSTRASS {
s = Random(RNG) // from random bytes
} else {
s = Randomnum(r, RNG) // Removes biases
}
}
if CURVETYPE != WEIERSTRASS {
RFC7748(s) // For Montgomery or Edwards, apply RFC7748 transformation
}
s.ToBytes(S)
WP := G.clmul(s, r)
WP.ToBytes(W, false) // To use point compression on public keys, change to true
return res
}
/* validate public key */
func ECDH_PUBLIC_KEY_VALIDATE(W []byte) int {
WP := ECP_fromBytes(W)
res := 0
r := NewBIGints(CURVE_Order)
if WP.Is_infinity() {
res = INVALID_PUBLIC_KEY
}
if res == 0 {
q := NewBIGints(Modulus)
nb := q.nbits()
k := NewBIGint(1)
k.shl(uint((nb + 4) / 2))
k.add(q)
k.div(r)
for k.parity() == 0 {
k.shr(1)
WP.dbl()
}
if !k.isunity() {
WP = WP.mul(k)
}
if WP.Is_infinity() {
res = INVALID_PUBLIC_KEY
}
}
return res
}
/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
// type = 0 is just x coordinate output
// type = 1 for standard compressed output
// type = 2 for standard uncompress output 04|x|y
func ECDH_ECPSVDP_DH(S []byte, WD []byte, Z []byte, typ int) int {
res := 0
s := FromBytes(S)
W := ECP_fromBytes(WD)
if W.Is_infinity() {
res = ERROR
}
if res == 0 {
r := NewBIGints(CURVE_Order)
W = W.clmul(s, r)
if W.Is_infinity() {
res = ERROR
} else {
if CURVETYPE != MONTGOMERY {
if typ > 0 {
if typ == 1 {
W.ToBytes(Z, true)
} else {
W.ToBytes(Z, false)
}
} else {
W.GetX().ToBytes(Z)
}
return res
} else {
W.GetX().ToBytes(Z)
}
}
}
return res
}
/* IEEE ECDSA Signature, C and D are signature on F using private key S */
func ECDH_ECPSP_DSA(sha int, RNG *core.RAND, S []byte, F []byte, C []byte, D []byte) int {
var T [EGS]byte
B := core.GPhashit(core.MC_SHA2, sha, EGS, 0, F, -1, nil)
G := ECP_generator()
r := NewBIGints(CURVE_Order)
s := FromBytes(S)
f := FromBytes(B[:])
c := NewBIGint(0)
d := NewBIGint(0)
V := NewECP()
for d.iszilch() {
u := Randomnum(r, RNG)
w := Randomnum(r, RNG) /* IMPORTANT - side channel masking to protect invmodp() */
V.Copy(G)
V = V.clmul(u, r)
vx := V.GetX()
c.copy(vx)
c.Mod(r)
if c.iszilch() {
continue
}
u.copy(Modmul(u, w, r))
u.Invmodp(r)
d.copy(Modmul(s, c, r))
d.copy(Modadd(d, f, r))
d.copy(Modmul(d, w, r))
d.copy(Modmul(u, d, r))
}
c.ToBytes(T[:])
for i := 0; i < EGS; i++ {
C[i] = T[i]
}
d.ToBytes(T[:])
for i := 0; i < EGS; i++ {
D[i] = T[i]
}
return 0
}
/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
func ECDH_ECPVP_DSA(sha int, W []byte, F []byte, C []byte, D []byte) int {
res := 0
B := core.GPhashit(core.MC_SHA2, sha, EGS, 0, F, -1, nil)
G := ECP_generator()
r := NewBIGints(CURVE_Order)
c := FromBytes(C)
d := FromBytes(D)
f := FromBytes(B[:])
if c.iszilch() || Comp(c, r) >= 0 || d.iszilch() || Comp(d, r) >= 0 {
res = ERROR
}
if res == 0 {
d.Invmodp(r)
f.copy(Modmul(f, d, r))
h2 := Modmul(c, d, r)
WP := ECP_fromBytes(W)
if WP.Is_infinity() {
res = ERROR
} else {
P := NewECP()
P.Copy(WP)
P = P.Mul2(h2, G, f)
if P.Is_infinity() {
res = ERROR
} else {
d = P.GetX()
d.Mod(r)
if Comp(d, c) != 0 {
res = ERROR
}
}
}
}
return res
}
/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
func ECDH_ECIES_ENCRYPT(sha int, P1 []byte, P2 []byte, RNG *core.RAND, W []byte, M []byte, V []byte, T []byte) []byte {
var Z [EFS]byte
var VZ [3*EFS + 1]byte
var K1 [AESKEY]byte
var K2 [AESKEY]byte
var U [EGS]byte
if ECDH_KEY_PAIR_GENERATE(RNG, U[:], V) != 0 {
return nil
}
if ECDH_ECPSVDP_DH(U[:], W, Z[:], 0) != 0 {
return nil
}
for i := 0; i < 2*EFS+1; i++ {
VZ[i] = V[i]
}
for i := 0; i < EFS; i++ {
VZ[2*EFS+1+i] = Z[i]
}
K := core.KDF2(core.MC_SHA2, sha, VZ[:], P1, 2*AESKEY)
for i := 0; i < AESKEY; i++ {
K1[i] = K[i]
K2[i] = K[AESKEY+i]
}
C := core.AES_CBC_IV0_ENCRYPT(K1[:], M)
L2 := core.InttoBytes(len(P2), 8)
var AC []byte
for i := 0; i < len(C); i++ {
AC = append(AC, C[i])
}
for i := 0; i < len(P2); i++ {
AC = append(AC, P2[i])
}
for i := 0; i < 8; i++ {
AC = append(AC, L2[i])
}
core.HMAC(core.MC_SHA2, sha, T, len(T), K2[:], AC)
return C
}
/* constant time n-byte compare */
func ncomp(T1 []byte, T2 []byte, n int) bool {
res := 0
for i := 0; i < n; i++ {
res |= int(T1[i] ^ T2[i])
}
if res == 0 {
return true
}
return false
}
/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
func ECDH_ECIES_DECRYPT(sha int, P1 []byte, P2 []byte, V []byte, C []byte, T []byte, U []byte) []byte {
var Z [EFS]byte
var VZ [3*EFS + 1]byte
var K1 [AESKEY]byte
var K2 [AESKEY]byte
var TAG []byte = T[:]
if ECDH_ECPSVDP_DH(U, V, Z[:], 0) != 0 {
return nil
}
for i := 0; i < 2*EFS+1; i++ {
VZ[i] = V[i]
}
for i := 0; i < EFS; i++ {
VZ[2*EFS+1+i] = Z[i]
}
K := core.KDF2(core.MC_SHA2, sha, VZ[:], P1, 2*AESKEY)
for i := 0; i < AESKEY; i++ {
K1[i] = K[i]
K2[i] = K[AESKEY+i]
}
M := core.AES_CBC_IV0_DECRYPT(K1[:], C)
if M == nil {
return nil
}
L2 := core.InttoBytes(len(P2), 8)
var AC []byte
for i := 0; i < len(C); i++ {
AC = append(AC, C[i])
}
for i := 0; i < len(P2); i++ {
AC = append(AC, P2[i])
}
for i := 0; i < 8; i++ {
AC = append(AC, L2[i])
}
core.HMAC(core.MC_SHA2, sha, TAG, len(TAG), K2[:], AC)
if !ncomp(T, TAG, len(T)) {
return nil
}
return M
}

1850
ec/bls48581/ECP.go Normal file

File diff suppressed because it is too large Load Diff

1074
ec/bls48581/ECP8.go Normal file

File diff suppressed because it is too large Load Diff

760
ec/bls48581/FP.go Normal file
View File

@ -0,0 +1,760 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* Finite Field arithmetic */
/* CLINT mod p functions */
package bls48581
import "source.quilibrium.com/quilibrium/ceremonyclient/ec/bls48581/core"
type FP struct {
x *BIG
XES int32
}
/* Constructors */
func NewFP() *FP {
F := new(FP)
F.x = NewBIG()
F.XES = 1
return F
}
func NewFPint(a int) *FP {
F := new(FP)
if a < 0 {
m := NewBIGints(Modulus)
m.inc(a)
m.norm()
F.x = NewBIGcopy(m)
} else {
F.x = NewBIGint(a)
}
F.nres()
return F
}
func NewFPbig(a *BIG) *FP {
F := new(FP)
F.x = NewBIGcopy(a)
F.nres()
return F
}
func NewFPcopy(a *FP) *FP {
F := new(FP)
F.x = NewBIGcopy(a.x)
F.XES = a.XES
return F
}
func NewFPrand(rng *core.RAND) *FP {
m := NewBIGints(Modulus)
w := Randomnum(m, rng)
F := NewFPbig(w)
return F
}
func (F *FP) ToString() string {
F.reduce()
return F.redc().ToString()
}
/* convert to Montgomery n-residue form */
func (F *FP) nres() {
if MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE {
r := NewBIGints(R2modp)
d := mul(F.x, r)
F.x.copy(mod(d))
F.XES = 2
} else {
md := NewBIGints(Modulus)
F.x.Mod(md)
F.XES = 1
}
}
/* convert back to regular form */
func (F *FP) redc() *BIG {
if MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE {
d := NewDBIGscopy(F.x)
return mod(d)
} else {
r := NewBIGcopy(F.x)
return r
}
}
/* reduce a DBIG to a BIG using the appropriate form of the modulus */
func mod(d *DBIG) *BIG {
if MODTYPE == PSEUDO_MERSENNE {
t := d.split(MODBITS)
b := NewBIGdcopy(d)
v := t.pmul(int(MConst))
t.add(b)
t.norm()
tw := t.w[NLEN-1]
t.w[NLEN-1] &= TMASK
t.w[0] += (MConst * ((tw >> TBITS) + (v << (BASEBITS - TBITS))))
t.norm()
return t
}
if MODTYPE == MONTGOMERY_FRIENDLY {
for i := 0; i < NLEN; i++ {
top, bot := muladd(d.w[i], MConst-1, d.w[i], d.w[NLEN+i-1])
d.w[NLEN+i-1] = bot
d.w[NLEN+i] += top
}
b := NewBIG()
for i := 0; i < NLEN; i++ {
b.w[i] = d.w[NLEN+i]
}
b.norm()
return b
}
if MODTYPE == GENERALISED_MERSENNE { // GoldiLocks only
t := d.split(MODBITS)
b := NewBIGdcopy(d)
b.add(t)
dd := NewDBIGscopy(t)
dd.shl(MODBITS / 2)
tt := dd.split(MODBITS)
lo := NewBIGdcopy(dd)
b.add(tt)
b.add(lo)
b.norm()
tt.shl(MODBITS / 2)
b.add(tt)
carry := b.w[NLEN-1] >> TBITS
b.w[NLEN-1] &= TMASK
b.w[0] += carry
ix := 224 / int(BASEBITS)
b.w[ix] += carry << (224 % BASEBITS)
b.norm()
return b
}
if MODTYPE == NOT_SPECIAL {
md := NewBIGints(Modulus)
return monty(md, MConst, d)
}
return NewBIG()
}
// find appoximation to quotient of a/m
// Out by at most 2.
// Note that MAXXES is bounded to be 2-bits less than half a word
func quo(n *BIG, m *BIG) int {
var num Chunk
var den Chunk
hb := uint(CHUNK) / 2
if TBITS < hb {
sh := hb - TBITS
num = (n.w[NLEN-1] << sh) | (n.w[NLEN-2] >> (BASEBITS - sh))
den = (m.w[NLEN-1] << sh) | (m.w[NLEN-2] >> (BASEBITS - sh))
} else {
num = n.w[NLEN-1]
den = m.w[NLEN-1]
}
return int(num / (den + 1))
}
/* reduce this mod Modulus */
func (F *FP) reduce() {
m := NewBIGints(Modulus)
r := NewBIGints(Modulus)
var sb uint
F.x.norm()
if F.XES > 16 {
q := quo(F.x, m)
carry := r.pmul(q)
r.w[NLEN-1] += carry << BASEBITS
F.x.sub(r)
F.x.norm()
sb = 2
} else {
sb = logb2(uint32(F.XES - 1))
}
m.fshl(sb)
for sb > 0 {
sr := ssn(r, F.x, m)
F.x.cmove(r, 1-sr)
sb -= 1
}
F.XES = 1
}
/* test this=0? */
func (F *FP) iszilch() bool {
W := NewFPcopy(F)
W.reduce()
return W.x.iszilch()
}
func (F *FP) islarger() int {
if F.iszilch() {
return 0
}
sx := NewBIGints(Modulus)
fx := F.redc()
sx.sub(fx)
sx.norm()
return Comp(fx, sx)
}
func (F *FP) ToBytes(b []byte) {
F.redc().ToBytes(b)
}
func FP_fromBytes(b []byte) *FP {
t := FromBytes(b)
return NewFPbig(t)
}
func (F *FP) isunity() bool {
W := NewFPcopy(F)
W.reduce()
return W.redc().isunity()
}
/* copy from FP b */
func (F *FP) copy(b *FP) {
F.x.copy(b.x)
F.XES = b.XES
}
/* set this=0 */
func (F *FP) zero() {
F.x.zero()
F.XES = 1
}
/* set this=1 */
func (F *FP) one() {
F.x.one()
F.nres()
}
/* return sign */
func (F *FP) sign() int {
if BIG_ENDIAN_SIGN {
m := NewBIGints(Modulus)
m.dec(1)
m.fshr(1)
n := NewFPcopy(F)
n.reduce()
w := n.redc()
cp := Comp(w, m)
return ((cp + 1) & 2) >> 1
} else {
W := NewFPcopy(F)
W.reduce()
return W.redc().parity()
}
}
/* normalise this */
func (F *FP) norm() {
F.x.norm()
}
/* swap FPs depending on d */
func (F *FP) cswap(b *FP, d int) {
c := int32(d)
c = ^(c - 1)
t := c & (F.XES ^ b.XES)
F.XES ^= t
b.XES ^= t
F.x.cswap(b.x, d)
}
/* copy FPs depending on d */
func (F *FP) cmove(b *FP, d int) {
F.x.cmove(b.x, d)
c := int32(-d)
F.XES ^= (F.XES ^ b.XES) & c
}
/* this*=b mod Modulus */
func (F *FP) mul(b *FP) {
if int64(F.XES)*int64(b.XES) > int64(FEXCESS) {
F.reduce()
}
d := mul(F.x, b.x)
F.x.copy(mod(d))
F.XES = 2
}
/* this = -this mod Modulus */
func (F *FP) neg() {
m := NewBIGints(Modulus)
sb := logb2(uint32(F.XES - 1))
m.fshl(sb)
F.x.rsub(m)
F.XES = (1 << sb) + 1
if F.XES > FEXCESS {
F.reduce()
}
}
/* this*=c mod Modulus, where c is a small int */
func (F *FP) imul(c int) {
// F.norm()
s := false
if c < 0 {
c = -c
s = true
}
if MODTYPE == PSEUDO_MERSENNE || MODTYPE == GENERALISED_MERSENNE {
d := F.x.pxmul(c)
F.x.copy(mod(d))
F.XES = 2
} else {
if F.XES*int32(c) <= FEXCESS {
F.x.pmul(c)
F.XES *= int32(c)
} else {
n := NewFPint(c)
F.mul(n)
}
}
if s {
F.neg()
F.norm()
}
}
/* this*=this mod Modulus */
func (F *FP) sqr() {
if int64(F.XES)*int64(F.XES) > int64(FEXCESS) {
F.reduce()
}
d := sqr(F.x)
F.x.copy(mod(d))
F.XES = 2
}
/* this+=b */
func (F *FP) add(b *FP) {
F.x.add(b.x)
F.XES += b.XES
if F.XES > FEXCESS {
F.reduce()
}
}
/* this-=b */
func (F *FP) sub(b *FP) {
n := NewFPcopy(b)
n.neg()
F.add(n)
}
func (F *FP) rsub(b *FP) {
F.neg()
F.add(b)
}
/* this/=2 mod Modulus */
func (F *FP) div2() {
p := NewBIGints(Modulus)
pr := F.x.parity()
w := NewBIGcopy(F.x)
F.x.fshr(1)
w.add(p)
w.norm()
w.fshr(1)
F.x.cmove(w, pr)
}
/* return jacobi symbol (this/Modulus) */
func (F *FP) jacobi() int {
w := F.redc()
p := NewBIGints(Modulus)
return w.Jacobi(p)
}
/* return TRUE if this==a */
func (F *FP) Equals(a *FP) bool {
f := NewFPcopy(F)
s := NewFPcopy(a)
s.reduce()
f.reduce()
if Comp(s.x, f.x) == 0 {
return true
}
return false
}
func (F *FP) pow(e *BIG) *FP {
var tb []*FP
var w [1 + (NLEN*int(BASEBITS)+3)/4]int8
F.norm()
t := NewBIGcopy(e)
t.norm()
nb := 1 + (t.nbits()+3)/4
for i := 0; i < nb; i++ {
lsbs := t.lastbits(4)
t.dec(lsbs)
t.norm()
w[i] = int8(lsbs)
t.fshr(4)
}
tb = append(tb, NewFPint(1))
tb = append(tb, NewFPcopy(F))
for i := 2; i < 16; i++ {
tb = append(tb, NewFPcopy(tb[i-1]))
tb[i].mul(F)
}
r := NewFPcopy(tb[w[nb-1]])
for i := nb - 2; i >= 0; i-- {
r.sqr()
r.sqr()
r.sqr()
r.sqr()
r.mul(tb[w[i]])
}
r.reduce()
return r
}
// See https://eprint.iacr.org/2018/1038
// return this^(p-3)/4 or this^(p-5)/8
func (F *FP) fpow() *FP {
ac := [11]int{1, 2, 3, 6, 12, 15, 30, 60, 120, 240, 255}
var xp []*FP
// phase 1
xp = append(xp, NewFPcopy(F))
xp = append(xp, NewFPcopy(F))
xp[1].sqr()
xp = append(xp, NewFPcopy(xp[1]))
xp[2].mul(F)
xp = append(xp, NewFPcopy(xp[2]))
xp[3].sqr()
xp = append(xp, NewFPcopy(xp[3]))
xp[4].sqr()
xp = append(xp, NewFPcopy(xp[4]))
xp[5].mul(xp[2])
xp = append(xp, NewFPcopy(xp[5]))
xp[6].sqr()
xp = append(xp, NewFPcopy(xp[6]))
xp[7].sqr()
xp = append(xp, NewFPcopy(xp[7]))
xp[8].sqr()
xp = append(xp, NewFPcopy(xp[8]))
xp[9].sqr()
xp = append(xp, NewFPcopy(xp[9]))
xp[10].mul(xp[5])
var n, c int
e := int(PM1D2)
n = int(MODBITS)
if MODTYPE == GENERALISED_MERSENNE { // Goldilocks ONLY
n /= 2
}
n -= (e + 1)
c = (int(MConst) + (1 << e) + 1) / (1 << (e + 1))
nd := 0
for c%2 == 0 {
c /= 2
n -= 1
nd++
}
bw := 0
w := 1
for w < c {
w *= 2
bw += 1
}
k := w - c
i := 10
key := NewFP()
if k != 0 {
for ac[i] > k {
i--
}
key.copy(xp[i])
k -= ac[i]
}
for k != 0 {
i--
if ac[i] > k {
continue
}
key.mul(xp[i])
k -= ac[i]
}
// phase 2
xp[1].copy(xp[2])
xp[2].copy(xp[5])
xp[3].copy(xp[10])
j := 3
m := 8
nw := n - bw
t := NewFP()
for 2*m < nw {
t.copy(xp[j])
j++
for i = 0; i < m; i++ {
t.sqr()
}
xp[j].copy(xp[j-1])
xp[j].mul(t)
m *= 2
}
lo := nw - m
r := NewFPcopy(xp[j])
for lo != 0 {
m /= 2
j--
if lo < m {
continue
}
lo -= m
t.copy(r)
for i = 0; i < m; i++ {
t.sqr()
}
r.copy(t)
r.mul(xp[j])
}
// phase 3
if bw != 0 {
for i = 0; i < bw; i++ {
r.sqr()
}
r.mul(key)
}
if MODTYPE == GENERALISED_MERSENNE { // Goldilocks ONLY
key.copy(r)
r.sqr()
r.mul(F)
for i = 0; i < n+1; i++ {
r.sqr()
}
r.mul(key)
}
for nd > 0 {
r.sqr()
nd--
}
return r
}
// calculates r=x^(p-1-2^e)/2^{e+1) where 2^e|p-1
func (F *FP) progen() {
if MODTYPE == PSEUDO_MERSENNE || MODTYPE == GENERALISED_MERSENNE {
F.copy(F.fpow())
return
}
e := uint(PM1D2)
m := NewBIGints(Modulus)
m.dec(1)
m.shr(e)
m.dec(1)
m.fshr(1)
F.copy(F.pow(m))
}
/* this=1/this mod Modulus */
func (F *FP) inverse(h *FP) {
e := int(PM1D2)
F.norm()
s := NewFPcopy(F)
for i := 0; i < e-1; i++ {
s.sqr()
s.mul(F)
}
if h == nil {
F.progen()
} else {
F.copy(h)
}
for i := 0; i <= e; i++ {
F.sqr()
}
F.mul(s)
F.reduce()
}
/* test for Quadratic residue */
func (F *FP) qr(h *FP) int {
r := NewFPcopy(F)
e := int(PM1D2)
r.progen()
if h != nil {
h.copy(r)
}
r.sqr()
r.mul(F)
for i := 0; i < e-1; i++ {
r.sqr()
}
if r.isunity() {
return 1
} else {
return 0
}
}
/* return sqrt(this) mod Modulus */
func (F *FP) sqrt(h *FP) *FP {
e := int(PM1D2)
g := NewFPcopy(F)
if h == nil {
g.progen()
} else {
g.copy(h)
}
m := NewBIGints(ROI)
v := NewFPbig(m)
t := NewFPcopy(g)
t.sqr()
t.mul(F)
r := NewFPcopy(F)
r.mul(g)
b := NewFPcopy(t)
for k := e; k > 1; k-- {
for j := 1; j < k-1; j++ {
b.sqr()
}
var u int
if b.isunity() {
u = 0
} else {
u = 1
}
g.copy(r)
g.mul(v)
r.cmove(g, u)
v.sqr()
g.copy(t)
g.mul(v)
t.cmove(g, u)
b.copy(t)
}
sgn := r.sign()
nr := NewFPcopy(r)
nr.neg()
nr.norm()
r.cmove(nr, sgn)
return r
}
func (F *FP) invsqrt(i *FP, s *FP) int {
h := NewFP()
qr := F.qr(h)
s.copy(F.sqrt(h))
i.copy(F)
i.inverse(h)
return qr
}
// Two for the price of one - See Hamburg https://eprint.iacr.org/2012/309.pdf
// Calculate inverse of i and square root of s, return QR
func FP_tpo(i *FP, s *FP) int {
w := NewFPcopy(s)
t := NewFPcopy(i)
w.mul(i)
t.mul(w)
qr := t.invsqrt(i, s)
i.mul(w)
s.mul(i)
return qr
}
/* return sqrt(this) mod Modulus
func (F *FP) sqrt() *FP {
F.reduce()
if PM1D2 == 2 {
var v *FP
i := NewFPcopy(F)
i.x.shl(1)
if MODTYPE == PSEUDO_MERSENNE || MODTYPE == GENERALISED_MERSENNE {
v = i.fpow()
} else {
b := NewBIGints(Modulus)
b.dec(5)
b.norm()
b.shr(3)
v = i.pow(b)
}
i.mul(v)
i.mul(v)
i.x.dec(1)
r := NewFPcopy(F)
r.mul(v)
r.mul(i)
r.reduce()
return r
} else {
var r *FP
if MODTYPE == PSEUDO_MERSENNE || MODTYPE == GENERALISED_MERSENNE {
r = F.fpow()
r.mul(F)
} else {
b := NewBIGints(Modulus)
b.inc(1)
b.norm()
b.shr(2)
r = F.pow(b)
}
return r
}
} */

616
ec/bls48581/FP16.go Normal file
View File

@ -0,0 +1,616 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* Finite Field arithmetic Fp^16 functions */
/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1)) */
package bls48581
//import "fmt"
type FP16 struct {
a *FP8
b *FP8
}
func NewFP16() *FP16 {
F := new(FP16)
F.a = NewFP8()
F.b = NewFP8()
return F
}
/* Constructors */
func NewFP16int(a int) *FP16 {
F := new(FP16)
F.a = NewFP8int(a)
F.b = NewFP8()
return F
}
func NewFP16copy(x *FP16) *FP16 {
F := new(FP16)
F.a = NewFP8copy(x.a)
F.b = NewFP8copy(x.b)
return F
}
func NewFP16fp8s(c *FP8, d *FP8) *FP16 {
F := new(FP16)
F.a = NewFP8copy(c)
F.b = NewFP8copy(d)
return F
}
func NewFP16fp8(c *FP8) *FP16 {
F := new(FP16)
F.a = NewFP8copy(c)
F.b = NewFP8()
return F
}
/* reduce all components of this mod Modulus */
func (F *FP16) reduce() {
F.a.reduce()
F.b.reduce()
}
/* normalise all components of this mod Modulus */
func (F *FP16) norm() {
F.a.norm()
F.b.norm()
}
/* test this==0 ? */
func (F *FP16) iszilch() bool {
return F.a.iszilch() && F.b.iszilch()
}
func (F *FP16) ToBytes(bf []byte) {
var t [8 * int(MODBYTES)]byte
MB := 8 * int(MODBYTES)
F.b.ToBytes(t[:])
for i := 0; i < MB; i++ {
bf[i] = t[i]
}
F.a.ToBytes(t[:])
for i := 0; i < MB; i++ {
bf[i+MB] = t[i]
}
}
func FP16_fromBytes(bf []byte) *FP16 {
var t [8 * int(MODBYTES)]byte
MB := 8 * int(MODBYTES)
for i := 0; i < MB; i++ {
t[i] = bf[i]
}
tb := FP8_fromBytes(t[:])
for i := 0; i < MB; i++ {
t[i] = bf[i+MB]
}
ta := FP8_fromBytes(t[:])
return NewFP16fp8s(ta, tb)
}
/* Conditional move */
func (F *FP16) cmove(g *FP16, d int) {
F.a.cmove(g.a, d)
F.b.cmove(g.b, d)
}
/* test this==1 ? */
func (F *FP16) isunity() bool {
one := NewFP8int(1)
return F.a.Equals(one) && F.b.iszilch()
}
/* test is w real? That is in a+ib test b is zero */
func (F *FP16) isreal() bool {
return F.b.iszilch()
}
/* extract real part a */
func (F *FP16) real() *FP8 {
return F.a
}
func (F *FP16) geta() *FP8 {
return F.a
}
/* extract imaginary part b */
func (F *FP16) getb() *FP8 {
return F.b
}
/* test this=x? */
func (F *FP16) Equals(x *FP16) bool {
return (F.a.Equals(x.a) && F.b.Equals(x.b))
}
/* copy this=x */
func (F *FP16) copy(x *FP16) {
F.a.copy(x.a)
F.b.copy(x.b)
}
/* set this=0 */
func (F *FP16) zero() {
F.a.zero()
F.b.zero()
}
/* set this=1 */
func (F *FP16) one() {
F.a.one()
F.b.zero()
}
/* set this=-this */
func (F *FP16) neg() {
F.norm()
m := NewFP8copy(F.a)
t := NewFP8()
m.add(F.b)
m.neg()
t.copy(m)
t.add(F.b)
F.b.copy(m)
F.b.add(F.a)
F.a.copy(t)
F.norm()
}
/* this=conjugate(this) */
func (F *FP16) conj() {
F.b.neg()
F.norm()
}
/* this=-conjugate(this) */
func (F *FP16) nconj() {
F.a.neg()
F.norm()
}
/* this+=x */
func (F *FP16) add(x *FP16) {
F.a.add(x.a)
F.b.add(x.b)
}
/* this-=x */
func (F *FP16) sub(x *FP16) {
m := NewFP16copy(x)
m.neg()
F.add(m)
}
/* this-=x */
func (F *FP16) rsub(x *FP16) {
F.neg()
F.add(x)
}
/* this*=s where s is FP8 */
func (F *FP16) pmul(s *FP8) {
F.a.mul(s)
F.b.mul(s)
}
/* this*=s where s is FP2 */
func (F *FP16) qmul(s *FP2) {
F.a.qmul(s)
F.b.qmul(s)
}
/* this*=s where s is FP */
func (F *FP16) tmul(s *FP) {
F.a.tmul(s)
F.b.tmul(s)
}
/* this*=c where c is int */
func (F *FP16) imul(c int) {
F.a.imul(c)
F.b.imul(c)
}
/* this*=this */
func (F *FP16) sqr() {
t1 := NewFP8copy(F.a)
t2 := NewFP8copy(F.b)
t3 := NewFP8copy(F.a)
t3.mul(F.b)
t1.add(F.b)
t2.times_i()
t2.add(F.a)
t1.norm()
t2.norm()
F.a.copy(t1)
F.a.mul(t2)
t2.copy(t3)
t2.times_i()
t2.add(t3)
t2.norm()
t2.neg()
F.a.add(t2)
F.b.copy(t3)
F.b.add(t3)
F.norm()
}
/* this*=y */
func (F *FP16) mul(y *FP16) {
t1 := NewFP8copy(F.a)
t2 := NewFP8copy(F.b)
t3 := NewFP8()
t4 := NewFP8copy(F.b)
t1.mul(y.a)
t2.mul(y.b)
t3.copy(y.b)
t3.add(y.a)
t4.add(F.a)
t3.norm()
t4.norm()
t4.mul(t3)
t3.copy(t1)
t3.neg()
t4.add(t3)
t4.norm()
t3.copy(t2)
t3.neg()
F.b.copy(t4)
F.b.add(t3)
t2.times_i()
F.a.copy(t2)
F.a.add(t1)
F.norm()
}
/* convert this to hex string */
func (F *FP16) toString() string {
return ("[" + F.a.toString() + "," + F.b.toString() + "]")
}
/* this=1/this */
func (F *FP16) inverse() {
t1 := NewFP8copy(F.a)
t2 := NewFP8copy(F.b)
t1.sqr()
t2.sqr()
t2.times_i()
t2.norm()
t1.sub(t2)
t1.norm()
t1.inverse(nil)
F.a.mul(t1)
t1.neg()
t1.norm()
F.b.mul(t1)
}
/* this*=i where i = sqrt(sqrt(-1+sqrt(-1))) */
func (F *FP16) times_i() {
s := NewFP8copy(F.b)
t := NewFP8copy(F.a)
s.times_i()
F.a.copy(s)
F.b.copy(t)
F.norm()
}
func (F *FP16) times_i2() {
F.a.times_i()
F.b.times_i()
}
func (F *FP16) times_i4() {
F.a.times_i2()
F.b.times_i2()
}
/* this=this^p using Frobenius */
func (F *FP16) frob(f *FP2) {
ff := NewFP2copy(f)
ff.sqr()
ff.norm()
F.a.frob(ff)
F.b.frob(ff)
F.b.qmul(f)
F.b.times_i()
}
/* this=this^e */
func (F *FP16) pow(e *BIG) *FP16 {
w := NewFP16copy(F)
w.norm()
z := NewBIGcopy(e)
r := NewFP16int(1)
z.norm()
for true {
bt := z.parity()
z.fshr(1)
if bt == 1 {
r.mul(w)
}
if z.iszilch() {
break
}
w.sqr()
}
r.reduce()
return r
}
/* XTR xtr_a function */
/*
func (F *FP16) xtr_A(w *FP16, y *FP16, z *FP16) {
r := NewFP16copy(w)
t := NewFP16copy(w)
r.sub(y)
r.norm()
r.pmul(F.a)
t.add(y)
t.norm()
t.pmul(F.b)
t.times_i()
F.copy(r)
F.add(t)
F.add(z)
F.norm()
}
*/
/* XTR xtr_d function */
/*
func (F *FP16) xtr_D() {
w := NewFP16copy(F)
F.sqr()
w.conj()
w.add(w)
w.norm()
F.sub(w)
F.reduce()
}
*/
/* r=x^n using XTR method on traces of FP48s */
/*
func (F *FP16) xtr_pow(n *BIG) *FP16 {
sf := NewFP16copy(F)
sf.norm()
a := NewFP16int(3)
b := NewFP16copy(sf)
c := NewFP16copy(b)
c.xtr_D()
t := NewFP16()
r := NewFP16()
par := n.parity()
v := NewBIGcopy(n)
v.norm()
v.fshr(1)
if par == 0 {
v.dec(1)
v.norm()
}
nb := v.nbits()
for i := nb - 1; i >= 0; i-- {
if v.bit(i) != 1 {
t.copy(b)
sf.conj()
c.conj()
b.xtr_A(a, sf, c)
sf.conj()
c.copy(t)
c.xtr_D()
a.xtr_D()
} else {
t.copy(a)
t.conj()
a.copy(b)
a.xtr_D()
b.xtr_A(c, sf, t)
c.xtr_D()
}
}
if par == 0 {
r.copy(c)
} else {
r.copy(b)
}
r.reduce()
return r
}
*/
/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP48s. See Stam thesis. */
/*
func (F *FP16) xtr_pow2(ck *FP16, ckml *FP16, ckm2l *FP16, a *BIG, b *BIG) *FP16 {
e := NewBIGcopy(a)
d := NewBIGcopy(b)
w := NewBIGint(0)
e.norm()
d.norm()
cu := NewFP16copy(ck) // can probably be passed in w/o copying
cv := NewFP16copy(F)
cumv := NewFP16copy(ckml)
cum2v := NewFP16copy(ckm2l)
r := NewFP16()
t := NewFP16()
f2 := 0
for d.parity() == 0 && e.parity() == 0 {
d.fshr(1)
e.fshr(1)
f2++
}
for Comp(d, e) != 0 {
if Comp(d, e) > 0 {
w.copy(e)
w.imul(4)
w.norm()
if Comp(d, w) <= 0 {
w.copy(d)
d.copy(e)
e.rsub(w)
e.norm()
t.copy(cv)
t.xtr_A(cu, cumv, cum2v)
cum2v.copy(cumv)
cum2v.conj()
cumv.copy(cv)
cv.copy(cu)
cu.copy(t)
} else {
if d.parity() == 0 {
d.fshr(1)
r.copy(cum2v)
r.conj()
t.copy(cumv)
t.xtr_A(cu, cv, r)
cum2v.copy(cumv)
cum2v.xtr_D()
cumv.copy(t)
cu.xtr_D()
} else {
if e.parity() == 1 {
d.sub(e)
d.norm()
d.fshr(1)
t.copy(cv)
t.xtr_A(cu, cumv, cum2v)
cu.xtr_D()
cum2v.copy(cv)
cum2v.xtr_D()
cum2v.conj()
cv.copy(t)
} else {
w.copy(d)
d.copy(e)
d.fshr(1)
e.copy(w)
t.copy(cumv)
t.xtr_D()
cumv.copy(cum2v)
cumv.conj()
cum2v.copy(t)
cum2v.conj()
t.copy(cv)
t.xtr_D()
cv.copy(cu)
cu.copy(t)
}
}
}
}
if Comp(d, e) < 0 {
w.copy(d)
w.imul(4)
w.norm()
if Comp(e, w) <= 0 {
e.sub(d)
e.norm()
t.copy(cv)
t.xtr_A(cu, cumv, cum2v)
cum2v.copy(cumv)
cumv.copy(cu)
cu.copy(t)
} else {
if e.parity() == 0 {
w.copy(d)
d.copy(e)
d.fshr(1)
e.copy(w)
t.copy(cumv)
t.xtr_D()
cumv.copy(cum2v)
cumv.conj()
cum2v.copy(t)
cum2v.conj()
t.copy(cv)
t.xtr_D()
cv.copy(cu)
cu.copy(t)
} else {
if d.parity() == 1 {
w.copy(e)
e.copy(d)
w.sub(d)
w.norm()
d.copy(w)
d.fshr(1)
t.copy(cv)
t.xtr_A(cu, cumv, cum2v)
cumv.conj()
cum2v.copy(cu)
cum2v.xtr_D()
cum2v.conj()
cu.copy(cv)
cu.xtr_D()
cv.copy(t)
} else {
d.fshr(1)
r.copy(cum2v)
r.conj()
t.copy(cumv)
t.xtr_A(cu, cv, r)
cum2v.copy(cumv)
cum2v.xtr_D()
cumv.copy(t)
cu.xtr_D()
}
}
}
}
}
r.copy(cv)
r.xtr_A(cu, cumv, cum2v)
for i := 0; i < f2; i++ {
r.xtr_D()
}
r = r.xtr_pow(d)
return r
}
*/

505
ec/bls48581/FP2.go Normal file
View File

@ -0,0 +1,505 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* Finite Field arithmetic Fp^2 functions */
/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
package bls48581
import "source.quilibrium.com/quilibrium/ceremonyclient/ec/bls48581/core"
//import "fmt"
type FP2 struct {
a *FP
b *FP
}
func NewFP2() *FP2 {
F := new(FP2)
F.a = NewFP()
F.b = NewFP()
return F
}
/* Constructors */
func NewFP2int(a int) *FP2 {
F := new(FP2)
F.a = NewFPint(a)
F.b = NewFP()
return F
}
func NewFP2ints(a int, b int) *FP2 {
F := new(FP2)
F.a = NewFPint(a)
F.b = NewFPint(b)
return F
}
func NewFP2copy(x *FP2) *FP2 {
F := new(FP2)
F.a = NewFPcopy(x.a)
F.b = NewFPcopy(x.b)
return F
}
func NewFP2fps(c *FP, d *FP) *FP2 {
F := new(FP2)
F.a = NewFPcopy(c)
F.b = NewFPcopy(d)
return F
}
func NewFP2bigs(c *BIG, d *BIG) *FP2 {
F := new(FP2)
F.a = NewFPbig(c)
F.b = NewFPbig(d)
return F
}
func NewFP2fp(c *FP) *FP2 {
F := new(FP2)
F.a = NewFPcopy(c)
F.b = NewFP()
return F
}
func NewFP2big(c *BIG) *FP2 {
F := new(FP2)
F.a = NewFPbig(c)
F.b = NewFP()
return F
}
func NewFP2rand(rng *core.RAND) *FP2 {
F := NewFP2fps(NewFPrand(rng), NewFPrand(rng))
return F
}
/* reduce components mod Modulus */
func (F *FP2) reduce() {
F.a.reduce()
F.b.reduce()
}
/* normalise components of w */
func (F *FP2) norm() {
F.a.norm()
F.b.norm()
}
/* test this=0 ? */
func (F *FP2) iszilch() bool {
return (F.a.iszilch() && F.b.iszilch())
}
func (F *FP2) islarger() int {
if F.iszilch() {
return 0
}
cmp := F.b.islarger()
if cmp != 0 {
return cmp
}
return F.a.islarger()
}
func (F *FP2) ToBytes(bf []byte) {
var t [int(MODBYTES)]byte
MB := int(MODBYTES)
F.b.ToBytes(t[:])
for i := 0; i < MB; i++ {
bf[i] = t[i]
}
F.a.ToBytes(t[:])
for i := 0; i < MB; i++ {
bf[i+MB] = t[i]
}
}
func FP2_fromBytes(bf []byte) *FP2 {
var t [int(MODBYTES)]byte
MB := int(MODBYTES)
for i := 0; i < MB; i++ {
t[i] = bf[i]
}
tb := FP_fromBytes(t[:])
for i := 0; i < MB; i++ {
t[i] = bf[i+MB]
}
ta := FP_fromBytes(t[:])
return NewFP2fps(ta, tb)
}
func (F *FP2) cmove(g *FP2, d int) {
F.a.cmove(g.a, d)
F.b.cmove(g.b, d)
}
/* test this=1 ? */
func (F *FP2) isunity() bool {
one := NewFPint(1)
return (F.a.Equals(one) && F.b.iszilch())
}
/* test this=x */
func (F *FP2) Equals(x *FP2) bool {
return (F.a.Equals(x.a) && F.b.Equals(x.b))
}
/* extract a */
func (F *FP2) GetA() *BIG {
return F.a.redc()
}
/* extract b */
func (F *FP2) GetB() *BIG {
return F.b.redc()
}
/* copy this=x */
func (F *FP2) copy(x *FP2) {
F.a.copy(x.a)
F.b.copy(x.b)
}
/* set this=0 */
func (F *FP2) zero() {
F.a.zero()
F.b.zero()
}
/* set this=1 */
func (F *FP2) one() {
F.a.one()
F.b.zero()
}
/* Return sign */
func (F *FP2) sign() int {
p1 := F.a.sign()
p2 := F.b.sign()
var u int
if BIG_ENDIAN_SIGN {
if F.b.iszilch() {
u = 1
} else {
u = 0
}
p2 ^= (p1 ^ p2) & u
return p2
} else {
if F.a.iszilch() {
u = 1
} else {
u = 0
}
p1 ^= (p1 ^ p2) & u
return p1
}
}
/* negate this mod Modulus */
func (F *FP2) neg() {
m := NewFPcopy(F.a)
t := NewFP()
m.add(F.b)
m.neg()
t.copy(m)
t.add(F.b)
F.b.copy(m)
F.b.add(F.a)
F.a.copy(t)
}
/* set to a-ib */
func (F *FP2) conj() {
F.b.neg()
F.b.norm()
}
/* this+=a */
func (F *FP2) add(x *FP2) {
F.a.add(x.a)
F.b.add(x.b)
}
/* this-=a */
func (F *FP2) sub(x *FP2) {
m := NewFP2copy(x)
m.neg()
F.add(m)
}
/* this-=a */
func (F *FP2) rsub(x *FP2) {
F.neg()
F.add(x)
}
/* this*=s, where s is an FP */
func (F *FP2) pmul(s *FP) {
F.a.mul(s)
F.b.mul(s)
}
/* this*=i, where i is an int */
func (F *FP2) imul(c int) {
F.a.imul(c)
F.b.imul(c)
}
/* this*=this */
func (F *FP2) sqr() {
w1 := NewFPcopy(F.a)
w3 := NewFPcopy(F.a)
mb := NewFPcopy(F.b)
w1.add(F.b)
w3.add(F.a)
w3.norm()
F.b.mul(w3)
mb.neg()
F.a.add(mb)
w1.norm()
F.a.norm()
F.a.mul(w1)
}
/* this*=y */
/* Now using Lazy reduction */
func (F *FP2) mul(y *FP2) {
if int64(F.a.XES+F.b.XES)*int64(y.a.XES+y.b.XES) > int64(FEXCESS) {
if F.a.XES > 1 {
F.a.reduce()
}
if F.b.XES > 1 {
F.b.reduce()
}
}
pR := NewDBIG()
C := NewBIGcopy(F.a.x)
D := NewBIGcopy(y.a.x)
p := NewBIGints(Modulus)
pR.ucopy(p)
A := mul(F.a.x, y.a.x)
B := mul(F.b.x, y.b.x)
C.add(F.b.x)
C.norm()
D.add(y.b.x)
D.norm()
E := mul(C, D)
FF := NewDBIGcopy(A)
FF.add(B)
B.rsub(pR)
A.add(B)
A.norm()
E.sub(FF)
E.norm()
F.a.x.copy(mod(A))
F.a.XES = 3
F.b.x.copy(mod(E))
F.b.XES = 2
}
/*
func (F *FP2) pow(b *BIG) {
w := NewFP2copy(F);
r := NewFP2int(1)
z := NewBIGcopy(b)
for true {
bt := z.parity()
z.shr(1)
if bt==1 {
r.mul(w)
}
if z.iszilch() {break}
w.sqr()
}
r.reduce()
F.copy(r)
}
*/
func (F *FP2) qr(h *FP) int {
c := NewFP2copy(F)
c.conj()
c.mul(F)
return c.a.qr(h)
}
/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
func (F *FP2) sqrt(h *FP) {
if F.iszilch() {
return
}
w1 := NewFPcopy(F.b)
w2 := NewFPcopy(F.a)
w3 := NewFP()
w4 := NewFP()
hint := NewFP()
w1.sqr()
w2.sqr()
w1.add(w2)
w1.norm()
w1 = w1.sqrt(h)
w2.copy(F.a)
w3.copy(F.a)
w2.add(w1)
w2.norm()
w2.div2()
w1.copy(F.b)
w1.div2()
qr := w2.qr(hint)
// tweak hint
w3.copy(hint)
w3.neg()
w3.norm()
w4.copy(w2)
w4.neg()
w4.norm()
w2.cmove(w4, 1-qr)
hint.cmove(w3, 1-qr)
F.a.copy(w2.sqrt(hint))
w3.copy(w2)
w3.inverse(hint)
w3.mul(F.a)
F.b.copy(w3)
F.b.mul(w1)
w4.copy(F.a)
F.a.cmove(F.b, 1-qr)
F.b.cmove(w4, 1-qr)
/*
F.a.copy(w2.sqrt(hint))
w3.copy(w2); w3.inverse(hint)
w3.mul(F.a)
F.b.copy(w3); F.b.mul(w1)
hint.neg(); hint.norm()
w2.neg(); w2.norm()
w4.copy(w2.sqrt(hint))
w3.copy(w2); w3.inverse(hint)
w3.mul(w4)
w3.mul(w1)
F.a.cmove(w3,1-qr)
F.b.cmove(w4,1-qr)
*/
sgn := F.sign()
nr := NewFP2copy(F)
nr.neg()
nr.norm()
F.cmove(nr, sgn)
}
/* output to hex string */
func (F *FP2) ToString() string {
return ("[" + F.a.ToString() + "," + F.b.ToString() + "]")
}
/* output to hex string */
func (F *FP2) toString() string {
return ("[" + F.a.ToString() + "," + F.b.ToString() + "]")
}
/* this=1/this */
func (F *FP2) inverse(h *FP) {
F.norm()
w1 := NewFPcopy(F.a)
w2 := NewFPcopy(F.b)
w1.sqr()
w2.sqr()
w1.add(w2)
w1.inverse(h)
F.a.mul(w1)
w1.neg()
w1.norm()
F.b.mul(w1)
}
/* this/=2 */
func (F *FP2) div2() {
F.a.div2()
F.b.div2()
}
/* this*=sqrt(-1) */
func (F *FP2) times_i() {
z := NewFPcopy(F.a)
F.a.copy(F.b)
F.a.neg()
F.b.copy(z)
}
/* w*=(1+sqrt(-1)) */
/* where X*2-(2^i+sqrt(-1)) is irreducible for FP4 */
func (F *FP2) mul_ip() {
t := NewFP2copy(F)
i := QNRI
F.times_i()
for i > 0 {
t.add(t)
t.norm()
i--
}
F.add(t)
if TOWER == POSITOWER {
F.norm()
F.neg()
}
}
/* w/=(2^i+sqrt(-1)) */
func (F *FP2) div_ip() {
z := NewFP2ints(1<<uint(QNRI), 1)
z.inverse(nil)
F.norm()
F.mul(z)
if TOWER == POSITOWER {
F.neg()
F.norm()
}
}

759
ec/bls48581/FP4.go Normal file
View File

@ -0,0 +1,759 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* Finite Field arithmetic Fp^4 functions */
/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1)) */
package bls48581
import "source.quilibrium.com/quilibrium/ceremonyclient/ec/bls48581/core"
//import "fmt"
type FP4 struct {
a *FP2
b *FP2
}
func NewFP4() *FP4 {
F := new(FP4)
F.a = NewFP2()
F.b = NewFP2()
return F
}
/* Constructors */
func NewFP4int(a int) *FP4 {
F := new(FP4)
F.a = NewFP2int(a)
F.b = NewFP2()
return F
}
/* Constructors */
func NewFP4ints(a int, b int) *FP4 {
F := new(FP4)
F.a = NewFP2int(a)
F.b = NewFP2int(b)
return F
}
func NewFP4copy(x *FP4) *FP4 {
F := new(FP4)
F.a = NewFP2copy(x.a)
F.b = NewFP2copy(x.b)
return F
}
func NewFP4fp2s(c *FP2, d *FP2) *FP4 {
F := new(FP4)
F.a = NewFP2copy(c)
F.b = NewFP2copy(d)
return F
}
func NewFP4fp2(c *FP2) *FP4 {
F := new(FP4)
F.a = NewFP2copy(c)
F.b = NewFP2()
return F
}
func NewFP4fp(c *FP) *FP4 {
F := new(FP4)
F.a = NewFP2fp(c)
F.b = NewFP2()
return F
}
func NewFP4rand(rng *core.RAND) *FP4 {
F := NewFP4fp2s(NewFP2rand(rng), NewFP2rand(rng))
return F
}
/* reduce all components of this mod Modulus */
func (F *FP4) reduce() {
F.a.reduce()
F.b.reduce()
}
/* normalise all components of this mod Modulus */
func (F *FP4) norm() {
F.a.norm()
F.b.norm()
}
/* test this==0 ? */
func (F *FP4) iszilch() bool {
return F.a.iszilch() && F.b.iszilch()
}
func (F *FP4) islarger() int {
if F.iszilch() {
return 0
}
cmp := F.b.islarger()
if cmp != 0 {
return cmp
}
return F.a.islarger()
}
func (F *FP4) ToBytes(bf []byte) {
var t [2 * int(MODBYTES)]byte
MB := 2 * int(MODBYTES)
F.b.ToBytes(t[:])
for i := 0; i < MB; i++ {
bf[i] = t[i]
}
F.a.ToBytes(t[:])
for i := 0; i < MB; i++ {
bf[i+MB] = t[i]
}
}
func FP4_fromBytes(bf []byte) *FP4 {
var t [2 * int(MODBYTES)]byte
MB := 2 * int(MODBYTES)
for i := 0; i < MB; i++ {
t[i] = bf[i]
}
tb := FP2_fromBytes(t[:])
for i := 0; i < MB; i++ {
t[i] = bf[i+MB]
}
ta := FP2_fromBytes(t[:])
return NewFP4fp2s(ta, tb)
}
/* Conditional move */
func (F *FP4) cmove(g *FP4, d int) {
F.a.cmove(g.a, d)
F.b.cmove(g.b, d)
}
/* test this==1 ? */
func (F *FP4) isunity() bool {
one := NewFP2int(1)
return F.a.Equals(one) && F.b.iszilch()
}
/* test is w real? That is in a+ib test b is zero */
func (F *FP4) isreal() bool {
return F.b.iszilch()
}
/* extract real part a */
func (F *FP4) real() *FP2 {
return F.a
}
func (F *FP4) geta() *FP2 {
return F.a
}
/* extract imaginary part b */
func (F *FP4) getb() *FP2 {
return F.b
}
/* test this=x? */
func (F *FP4) Equals(x *FP4) bool {
return (F.a.Equals(x.a) && F.b.Equals(x.b))
}
/* copy this=x */
func (F *FP4) copy(x *FP4) {
F.a.copy(x.a)
F.b.copy(x.b)
}
/* set this=0 */
func (F *FP4) zero() {
F.a.zero()
F.b.zero()
}
/* set this=1 */
func (F *FP4) one() {
F.a.one()
F.b.zero()
}
/* Return sign */
func (F *FP4) sign() int {
p1 := F.a.sign()
p2 := F.b.sign()
var u int
if BIG_ENDIAN_SIGN {
if F.b.iszilch() {
u = 1
} else {
u = 0
}
p2 ^= (p1 ^ p2) & u
return p2
} else {
if F.a.iszilch() {
u = 1
} else {
u = 0
}
p1 ^= (p1 ^ p2) & u
return p1
}
}
/* set this=-this */
func (F *FP4) neg() {
F.norm()
m := NewFP2copy(F.a)
t := NewFP2()
m.add(F.b)
m.neg()
t.copy(m)
t.add(F.b)
F.b.copy(m)
F.b.add(F.a)
F.a.copy(t)
F.norm()
}
/* this=conjugate(this) */
func (F *FP4) conj() {
F.b.neg()
F.norm()
}
/* this=-conjugate(this) */
func (F *FP4) nconj() {
F.a.neg()
F.norm()
}
/* this+=x */
func (F *FP4) add(x *FP4) {
F.a.add(x.a)
F.b.add(x.b)
}
/* this-=x */
func (F *FP4) sub(x *FP4) {
m := NewFP4copy(x)
m.neg()
F.add(m)
}
/* this-=x */
func (F *FP4) rsub(x *FP4) {
F.neg()
F.add(x)
}
/* this*=s where s is FP2 */
func (F *FP4) pmul(s *FP2) {
F.a.mul(s)
F.b.mul(s)
}
/* this*=s where s is FP2 */
func (F *FP4) qmul(s *FP) {
F.a.pmul(s)
F.b.pmul(s)
}
/* this*=c where c is int */
func (F *FP4) imul(c int) {
F.a.imul(c)
F.b.imul(c)
}
/* this*=this */
func (F *FP4) sqr() {
t1 := NewFP2copy(F.a)
t2 := NewFP2copy(F.b)
t3 := NewFP2copy(F.a)
t3.mul(F.b)
t1.add(F.b)
t2.mul_ip()
t2.add(F.a)
t1.norm()
t2.norm()
F.a.copy(t1)
F.a.mul(t2)
t2.copy(t3)
t2.mul_ip()
t2.add(t3)
t2.norm()
t2.neg()
F.a.add(t2)
F.b.copy(t3)
F.b.add(t3)
F.norm()
}
/* this*=y */
func (F *FP4) mul(y *FP4) {
t1 := NewFP2copy(F.a)
t2 := NewFP2copy(F.b)
t3 := NewFP2()
t4 := NewFP2copy(F.b)
t1.mul(y.a)
t2.mul(y.b)
t3.copy(y.b)
t3.add(y.a)
t4.add(F.a)
t3.norm()
t4.norm()
t4.mul(t3)
t3.copy(t1)
t3.neg()
t4.add(t3)
t4.norm()
t3.copy(t2)
t3.neg()
F.b.copy(t4)
F.b.add(t3)
t2.mul_ip()
F.a.copy(t2)
F.a.add(t1)
F.norm()
}
/* convert this to hex string */
func (F *FP4) toString() string {
return ("[" + F.a.toString() + "," + F.b.toString() + "]")
}
/* this=1/this */
func (F *FP4) inverse(h *FP) {
t1 := NewFP2copy(F.a)
t2 := NewFP2copy(F.b)
t1.sqr()
t2.sqr()
t2.mul_ip()
t2.norm()
t1.sub(t2)
t1.inverse(h)
F.a.mul(t1)
t1.neg()
t1.norm()
F.b.mul(t1)
}
/* this*=i where i = sqrt(2^i+sqrt(-1)) */
func (F *FP4) times_i() {
t := NewFP2copy(F.b)
F.b.copy(F.a)
t.mul_ip()
F.a.copy(t)
F.norm()
if TOWER == POSITOWER {
F.neg()
F.norm()
}
}
/* this=this^p using Frobenius */
func (F *FP4) frob(f *FP2) {
F.a.conj()
F.b.conj()
F.b.mul(f)
}
/* this=this^e
func (F *FP4) pow(e *BIG) *FP4 {
w := NewFP4copy(F)
w.norm()
z := NewBIGcopy(e)
r := NewFP4int(1)
z.norm()
for true {
bt := z.parity()
z.fshr(1)
if bt == 1 {
r.mul(w)
}
if z.iszilch() {
break
}
w.sqr()
}
r.reduce()
return r
}
*/
/* XTR xtr_a function */
func (F *FP4) xtr_A(w *FP4, y *FP4, z *FP4) {
r := NewFP4copy(w)
t := NewFP4copy(w)
r.sub(y)
r.norm()
r.pmul(F.a)
t.add(y)
t.norm()
t.pmul(F.b)
t.times_i()
F.copy(r)
F.add(t)
F.add(z)
F.norm()
}
/* XTR xtr_d function */
func (F *FP4) xtr_D() {
w := NewFP4copy(F)
F.sqr()
w.conj()
w.add(w)
w.norm()
F.sub(w)
F.reduce()
}
/* r=x^n using XTR method on traces of FP12s */
func (F *FP4) xtr_pow(n *BIG) *FP4 {
a := NewFP4int(3)
b := NewFP4copy(F)
c := NewFP4copy(b)
c.xtr_D()
t := NewFP4()
r := NewFP4()
sf := NewFP4copy(F)
sf.norm()
par := n.parity()
v := NewBIGcopy(n)
v.norm()
v.fshr(1)
if par == 0 {
v.dec(1)
v.norm()
}
nb := v.nbits()
for i := nb - 1; i >= 0; i-- {
if v.bit(i) != 1 {
t.copy(b)
sf.conj()
c.conj()
b.xtr_A(a, sf, c)
sf.conj()
c.copy(t)
c.xtr_D()
a.xtr_D()
} else {
t.copy(a)
t.conj()
a.copy(b)
a.xtr_D()
b.xtr_A(c, sf, t)
c.xtr_D()
}
}
if par == 0 {
r.copy(c)
} else {
r.copy(b)
}
r.reduce()
return r
}
/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
func (F *FP4) xtr_pow2(ck *FP4, ckml *FP4, ckm2l *FP4, a *BIG, b *BIG) *FP4 {
e := NewBIGcopy(a)
d := NewBIGcopy(b)
w := NewBIGint(0)
e.norm()
d.norm()
cu := NewFP4copy(ck) // can probably be passed in w/o copying
cv := NewFP4copy(F)
cumv := NewFP4copy(ckml)
cum2v := NewFP4copy(ckm2l)
r := NewFP4()
t := NewFP4()
f2 := 0
for d.parity() == 0 && e.parity() == 0 {
d.fshr(1)
e.fshr(1)
f2++
}
for Comp(d, e) != 0 {
if Comp(d, e) > 0 {
w.copy(e)
w.imul(4)
w.norm()
if Comp(d, w) <= 0 {
w.copy(d)
d.copy(e)
e.rsub(w)
e.norm()
t.copy(cv)
t.xtr_A(cu, cumv, cum2v)
cum2v.copy(cumv)
cum2v.conj()
cumv.copy(cv)
cv.copy(cu)
cu.copy(t)
} else {
if d.parity() == 0 {
d.fshr(1)
r.copy(cum2v)
r.conj()
t.copy(cumv)
t.xtr_A(cu, cv, r)
cum2v.copy(cumv)
cum2v.xtr_D()
cumv.copy(t)
cu.xtr_D()
} else {
if e.parity() == 1 {
d.sub(e)
d.norm()
d.fshr(1)
t.copy(cv)
t.xtr_A(cu, cumv, cum2v)
cu.xtr_D()
cum2v.copy(cv)
cum2v.xtr_D()
cum2v.conj()
cv.copy(t)
} else {
w.copy(d)
d.copy(e)
d.fshr(1)
e.copy(w)
t.copy(cumv)
t.xtr_D()
cumv.copy(cum2v)
cumv.conj()
cum2v.copy(t)
cum2v.conj()
t.copy(cv)
t.xtr_D()
cv.copy(cu)
cu.copy(t)
}
}
}
}
if Comp(d, e) < 0 {
w.copy(d)
w.imul(4)
w.norm()
if Comp(e, w) <= 0 {
e.sub(d)
e.norm()
t.copy(cv)
t.xtr_A(cu, cumv, cum2v)
cum2v.copy(cumv)
cumv.copy(cu)
cu.copy(t)
} else {
if e.parity() == 0 {
w.copy(d)
d.copy(e)
d.fshr(1)
e.copy(w)
t.copy(cumv)
t.xtr_D()
cumv.copy(cum2v)
cumv.conj()
cum2v.copy(t)
cum2v.conj()
t.copy(cv)
t.xtr_D()
cv.copy(cu)
cu.copy(t)
} else {
if d.parity() == 1 {
w.copy(e)
e.copy(d)
w.sub(d)
w.norm()
d.copy(w)
d.fshr(1)
t.copy(cv)
t.xtr_A(cu, cumv, cum2v)
cumv.conj()
cum2v.copy(cu)
cum2v.xtr_D()
cum2v.conj()
cu.copy(cv)
cu.xtr_D()
cv.copy(t)
} else {
d.fshr(1)
r.copy(cum2v)
r.conj()
t.copy(cumv)
t.xtr_A(cu, cv, r)
cum2v.copy(cumv)
cum2v.xtr_D()
cumv.copy(t)
cu.xtr_D()
}
}
}
}
}
r.copy(cv)
r.xtr_A(cu, cumv, cum2v)
for i := 0; i < f2; i++ {
r.xtr_D()
}
r = r.xtr_pow(d)
return r
}
/* this/=2 */
func (F *FP4) div2() {
F.a.div2()
F.b.div2()
}
func (F *FP4) div_i() {
u := NewFP2copy(F.a)
v := NewFP2copy(F.b)
u.div_ip()
F.a.copy(v)
F.b.copy(u)
if TOWER == POSITOWER {
F.neg()
F.norm()
}
}
/*
func (F *FP4) pow(b *BIG) {
w := NewFP4copy(F);
r := NewFP4int(1)
z := NewBIGcopy(b)
for true {
bt := z.parity()
z.shr(1)
if bt==1 {
r.mul(w)
}
if z.iszilch() {break}
w.sqr()
}
r.reduce();
F.copy(r);
}
*/
/* */
// Test for Quadratic Residue
func (F *FP4) qr(h *FP) int {
c := NewFP4copy(F)
c.conj()
c.mul(F)
return c.a.qr(h)
}
// sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2))
func (F *FP4) sqrt(h *FP) {
if F.iszilch() {
return
}
a := NewFP2copy(F.a)
b := NewFP2()
s := NewFP2copy(F.b)
t := NewFP2copy(F.a)
hint := NewFP()
s.sqr()
a.sqr()
s.mul_ip()
s.norm()
a.sub(s)
s.copy(a)
s.norm()
s.sqrt(h)
a.copy(t)
b.copy(t)
a.add(s)
a.norm()
a.div2()
b.copy(F.b)
b.div2()
qr := a.qr(hint)
// tweak hint - multiply old hint by Norm(1/Beta)^e where Beta is irreducible polynomial
s.copy(a)
twk := NewFPbig(NewBIGints(TWK))
twk.mul(hint)
s.div_ip()
s.norm()
a.cmove(s, 1-qr)
hint.cmove(twk, 1-qr)
F.a.copy(a)
F.a.sqrt(hint)
s.copy(a)
s.inverse(hint)
s.mul(F.a)
F.b.copy(s)
F.b.mul(b)
t.copy(F.a)
F.a.cmove(F.b, 1-qr)
F.b.cmove(t, 1-qr)
sgn := F.sign()
nr := NewFP4copy(F)
nr.neg()
nr.norm()
F.cmove(nr, sgn)
}
/* */

1189
ec/bls48581/FP48.go Normal file

File diff suppressed because it is too large Load Diff

781
ec/bls48581/FP8.go Normal file
View File

@ -0,0 +1,781 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* Finite Field arithmetic Fp^8 functions */
/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1)) */
package bls48581
import "source.quilibrium.com/quilibrium/ceremonyclient/ec/bls48581/core"
//import "fmt"
type FP8 struct {
a *FP4
b *FP4
}
func NewFP8() *FP8 {
F := new(FP8)
F.a = NewFP4()
F.b = NewFP4()
return F
}
/* Constructors */
func NewFP8int(a int) *FP8 {
F := new(FP8)
F.a = NewFP4int(a)
F.b = NewFP4()
return F
}
/* Constructors */
func NewFP8ints(a int, b int) *FP8 {
F := new(FP8)
F.a = NewFP4int(a)
F.b = NewFP4int(b)
return F
}
func NewFP8copy(x *FP8) *FP8 {
F := new(FP8)
F.a = NewFP4copy(x.a)
F.b = NewFP4copy(x.b)
return F
}
func NewFP8fp4s(c *FP4, d *FP4) *FP8 {
F := new(FP8)
F.a = NewFP4copy(c)
F.b = NewFP4copy(d)
return F
}
func NewFP8fp4(c *FP4) *FP8 {
F := new(FP8)
F.a = NewFP4copy(c)
F.b = NewFP4()
return F
}
func NewFP8fp(c *FP) *FP8 {
F := new(FP8)
F.a = NewFP4fp(c)
F.b = NewFP4()
return F
}
func NewFP8rand(rng *core.RAND) *FP8 {
F := NewFP8fp4s(NewFP4rand(rng), NewFP4rand(rng))
return F
}
/* reduce all components of this mod Modulus */
func (F *FP8) reduce() {
F.a.reduce()
F.b.reduce()
}
/* normalise all components of this mod Modulus */
func (F *FP8) norm() {
F.a.norm()
F.b.norm()
}
/* test this==0 ? */
func (F *FP8) iszilch() bool {
return F.a.iszilch() && F.b.iszilch()
}
func (F *FP8) islarger() int {
if F.iszilch() {
return 0
}
cmp := F.b.islarger()
if cmp != 0 {
return cmp
}
return F.a.islarger()
}
func (F *FP8) ToBytes(bf []byte) {
var t [4 * int(MODBYTES)]byte
MB := 4 * int(MODBYTES)
F.b.ToBytes(t[:])
for i := 0; i < MB; i++ {
bf[i] = t[i]
}
F.a.ToBytes(t[:])
for i := 0; i < MB; i++ {
bf[i+MB] = t[i]
}
}
func FP8_fromBytes(bf []byte) *FP8 {
var t [4 * int(MODBYTES)]byte
MB := 4 * int(MODBYTES)
for i := 0; i < MB; i++ {
t[i] = bf[i]
}
tb := FP4_fromBytes(t[:])
for i := 0; i < MB; i++ {
t[i] = bf[i+MB]
}
ta := FP4_fromBytes(t[:])
return NewFP8fp4s(ta, tb)
}
/* Conditional move */
func (F *FP8) cmove(g *FP8, d int) {
F.a.cmove(g.a, d)
F.b.cmove(g.b, d)
}
/* test this==1 ? */
func (F *FP8) isunity() bool {
one := NewFP4int(1)
return F.a.Equals(one) && F.b.iszilch()
}
/* test is w real? That is in a+ib test b is zero */
func (F *FP8) isreal() bool {
return F.b.iszilch()
}
/* extract real part a */
func (F *FP8) real() *FP4 {
return F.a
}
func (F *FP8) geta() *FP4 {
return F.a
}
/* extract imaginary part b */
func (F *FP8) getb() *FP4 {
return F.b
}
/* test this=x? */
func (F *FP8) Equals(x *FP8) bool {
return (F.a.Equals(x.a) && F.b.Equals(x.b))
}
/* copy this=x */
func (F *FP8) copy(x *FP8) {
F.a.copy(x.a)
F.b.copy(x.b)
}
/* set this=0 */
func (F *FP8) zero() {
F.a.zero()
F.b.zero()
}
/* set this=1 */
func (F *FP8) one() {
F.a.one()
F.b.zero()
}
/* Return sign */
func (F *FP8) sign() int {
p1 := F.a.sign()
p2 := F.b.sign()
var u int
if BIG_ENDIAN_SIGN {
if F.b.iszilch() {
u = 1
} else {
u = 0
}
p2 ^= (p1 ^ p2) & u
return p2
} else {
if F.a.iszilch() {
u = 1
} else {
u = 0
}
p1 ^= (p1 ^ p2) & u
return p1
}
}
/* set this=-this */
func (F *FP8) neg() {
F.norm()
m := NewFP4copy(F.a)
t := NewFP4()
m.add(F.b)
m.neg()
t.copy(m)
t.add(F.b)
F.b.copy(m)
F.b.add(F.a)
F.a.copy(t)
F.norm()
}
/* this=conjugate(this) */
func (F *FP8) conj() {
F.b.neg()
F.norm()
}
/* this=-conjugate(this) */
func (F *FP8) nconj() {
F.a.neg()
F.norm()
}
/* this+=x */
func (F *FP8) add(x *FP8) {
F.a.add(x.a)
F.b.add(x.b)
}
/* this-=x */
func (F *FP8) sub(x *FP8) {
m := NewFP8copy(x)
m.neg()
F.add(m)
}
/* this-=x */
func (F *FP8) rsub(x *FP8) {
F.neg()
F.add(x)
}
/* this*=s where s is FP4 */
func (F *FP8) pmul(s *FP4) {
F.a.mul(s)
F.b.mul(s)
}
/* this*=s where s is FP2 */
func (F *FP8) qmul(s *FP2) {
F.a.pmul(s)
F.b.pmul(s)
}
/* this*=s where s is FP */
func (F *FP8) tmul(s *FP) {
F.a.qmul(s)
F.b.qmul(s)
}
/* this*=c where c is int */
func (F *FP8) imul(c int) {
F.a.imul(c)
F.b.imul(c)
}
/* this*=this */
func (F *FP8) sqr() {
t1 := NewFP4copy(F.a)
t2 := NewFP4copy(F.b)
t3 := NewFP4copy(F.a)
t3.mul(F.b)
t1.add(F.b)
t2.times_i()
t2.add(F.a)
t1.norm()
t2.norm()
F.a.copy(t1)
F.a.mul(t2)
t2.copy(t3)
t2.times_i()
t2.add(t3)
t2.norm()
t2.neg()
F.a.add(t2)
F.b.copy(t3)
F.b.add(t3)
F.norm()
}
/* this*=y */
func (F *FP8) mul(y *FP8) {
t1 := NewFP4copy(F.a)
t2 := NewFP4copy(F.b)
t3 := NewFP4()
t4 := NewFP4copy(F.b)
t1.mul(y.a)
t2.mul(y.b)
t3.copy(y.b)
t3.add(y.a)
t4.add(F.a)
t3.norm()
t4.norm()
t4.mul(t3)
t3.copy(t1)
t3.neg()
t4.add(t3)
t4.norm()
t3.copy(t2)
t3.neg()
F.b.copy(t4)
F.b.add(t3)
t2.times_i()
F.a.copy(t2)
F.a.add(t1)
F.norm()
}
/* convert this to hex string */
func (F *FP8) toString() string {
return ("[" + F.a.toString() + "," + F.b.toString() + "]")
}
/* this=1/this */
func (F *FP8) inverse(h *FP) {
t1 := NewFP4copy(F.a)
t2 := NewFP4copy(F.b)
t1.sqr()
t2.sqr()
t2.times_i()
t2.norm()
t1.sub(t2)
t1.norm()
t1.inverse(h)
F.a.mul(t1)
t1.neg()
t1.norm()
F.b.mul(t1)
}
/* this*=i where i = sqrt(sqrt(-1+sqrt(-1))) */
func (F *FP8) times_i() {
s := NewFP4copy(F.b)
t := NewFP4copy(F.a)
s.times_i()
F.a.copy(s)
F.b.copy(t)
F.norm()
if TOWER == POSITOWER {
F.neg()
F.norm()
}
}
func (F *FP8) times_i2() {
F.a.times_i()
F.b.times_i()
}
/* this=this^p using Frobenius */
func (F *FP8) frob(f *FP2) {
ff := NewFP2copy(f)
ff.sqr()
ff.mul_ip()
ff.norm()
F.a.frob(ff)
F.b.frob(ff)
F.b.pmul(f)
F.b.times_i()
}
/* this=this^e
func (F *FP8) pow(e *BIG) *FP8 {
w := NewFP8copy(F)
w.norm()
z := NewBIGcopy(e)
r := NewFP8int(1)
z.norm()
for true {
bt := z.parity()
z.fshr(1)
if bt == 1 {
r.mul(w)
}
if z.iszilch() {
break
}
w.sqr()
}
r.reduce()
return r
} */
/* XTR xtr_a function */
/*
func (F *FP8) xtr_A(w *FP8, y *FP8, z *FP8) {
r := NewFP8copy(w)
t := NewFP8copy(w)
r.sub(y)
r.norm()
r.pmul(F.a)
t.add(y)
t.norm()
t.pmul(F.b)
t.times_i()
F.copy(r)
F.add(t)
F.add(z)
F.norm()
}
*/
/* XTR xtr_d function */
/*
func (F *FP8) xtr_D() {
w := NewFP8copy(F)
F.sqr()
w.conj()
w.add(w)
w.norm()
F.sub(w)
F.reduce()
}
*/
/* r=x^n using XTR method on traces of FP24s */
/*
func (F *FP8) xtr_pow(n *BIG) *FP8 {
a := NewFP8int(3)
b := NewFP8copy(F)
c := NewFP8copy(b)
c.xtr_D()
t := NewFP8()
r := NewFP8()
sf := NewFP8copy(F)
sf.norm()
par := n.parity()
v := NewBIGcopy(n)
v.norm()
v.fshr(1)
if par == 0 {
v.dec(1)
v.norm()
}
nb := v.nbits()
for i := nb - 1; i >= 0; i-- {
if v.bit(i) != 1 {
t.copy(b)
sf.conj()
c.conj()
b.xtr_A(a, sf, c)
sf.conj()
c.copy(t)
c.xtr_D()
a.xtr_D()
} else {
t.copy(a)
t.conj()
a.copy(b)
a.xtr_D()
b.xtr_A(c, sf, t)
c.xtr_D()
}
}
if par == 0 {
r.copy(c)
} else {
r.copy(b)
}
r.reduce()
return r
}
*/
/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP24s. See Stam thesis. */
/*
func (F *FP8) xtr_pow2(ck *FP8, ckml *FP8, ckm2l *FP8, a *BIG, b *BIG) *FP8 {
e := NewBIGcopy(a)
d := NewBIGcopy(b)
w := NewBIGint(0)
e.norm()
d.norm()
cu := NewFP8copy(ck) // can probably be passed in w/o copying
cv := NewFP8copy(F)
cumv := NewFP8copy(ckml)
cum2v := NewFP8copy(ckm2l)
r := NewFP8()
t := NewFP8()
f2 := 0
for d.parity() == 0 && e.parity() == 0 {
d.fshr(1)
e.fshr(1)
f2++
}
for Comp(d, e) != 0 {
if Comp(d, e) > 0 {
w.copy(e)
w.imul(4)
w.norm()
if Comp(d, w) <= 0 {
w.copy(d)
d.copy(e)
e.rsub(w)
e.norm()
t.copy(cv)
t.xtr_A(cu, cumv, cum2v)
cum2v.copy(cumv)
cum2v.conj()
cumv.copy(cv)
cv.copy(cu)
cu.copy(t)
} else {
if d.parity() == 0 {
d.fshr(1)
r.copy(cum2v)
r.conj()
t.copy(cumv)
t.xtr_A(cu, cv, r)
cum2v.copy(cumv)
cum2v.xtr_D()
cumv.copy(t)
cu.xtr_D()
} else {
if e.parity() == 1 {
d.sub(e)
d.norm()
d.fshr(1)
t.copy(cv)
t.xtr_A(cu, cumv, cum2v)
cu.xtr_D()
cum2v.copy(cv)
cum2v.xtr_D()
cum2v.conj()
cv.copy(t)
} else {
w.copy(d)
d.copy(e)
d.fshr(1)
e.copy(w)
t.copy(cumv)
t.xtr_D()
cumv.copy(cum2v)
cumv.conj()
cum2v.copy(t)
cum2v.conj()
t.copy(cv)
t.xtr_D()
cv.copy(cu)
cu.copy(t)
}
}
}
}
if Comp(d, e) < 0 {
w.copy(d)
w.imul(4)
w.norm()
if Comp(e, w) <= 0 {
e.sub(d)
e.norm()
t.copy(cv)
t.xtr_A(cu, cumv, cum2v)
cum2v.copy(cumv)
cumv.copy(cu)
cu.copy(t)
} else {
if e.parity() == 0 {
w.copy(d)
d.copy(e)
d.fshr(1)
e.copy(w)
t.copy(cumv)
t.xtr_D()
cumv.copy(cum2v)
cumv.conj()
cum2v.copy(t)
cum2v.conj()
t.copy(cv)
t.xtr_D()
cv.copy(cu)
cu.copy(t)
} else {
if d.parity() == 1 {
w.copy(e)
e.copy(d)
w.sub(d)
w.norm()
d.copy(w)
d.fshr(1)
t.copy(cv)
t.xtr_A(cu, cumv, cum2v)
cumv.conj()
cum2v.copy(cu)
cum2v.xtr_D()
cum2v.conj()
cu.copy(cv)
cu.xtr_D()
cv.copy(t)
} else {
d.fshr(1)
r.copy(cum2v)
r.conj()
t.copy(cumv)
t.xtr_A(cu, cv, r)
cum2v.copy(cumv)
cum2v.xtr_D()
cumv.copy(t)
cu.xtr_D()
}
}
}
}
}
r.copy(cv)
r.xtr_A(cu, cumv, cum2v)
for i := 0; i < f2; i++ {
r.xtr_D()
}
r = r.xtr_pow(d)
return r
}
*/
/* this/=2 */
func (F *FP8) div2() {
F.a.div2()
F.b.div2()
}
func (F *FP8) div_i() {
u := NewFP4copy(F.a)
v := NewFP4copy(F.b)
u.div_i()
F.a.copy(v)
F.b.copy(u)
if TOWER == POSITOWER {
F.neg()
F.norm()
}
}
/*
func (F *FP8) pow(b *BIG) {
w := NewFP8copy(F);
r := NewFP8int(1)
z := NewBIGcopy(b)
for true {
bt := z.parity()
z.shr(1)
if bt==1 {
r.mul(w)
}
if z.iszilch() {break}
w.sqr()
}
r.reduce();
F.copy(r);
}
*/
/* */
// Test for Quadratic Residue
func (F *FP8) qr(h *FP) int {
c := NewFP8copy(F)
c.conj()
c.mul(F)
return c.a.qr(h)
}
// sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2))
func (F *FP8) sqrt(h *FP) {
if F.iszilch() {
return
}
a := NewFP4copy(F.a)
b := NewFP4()
s := NewFP4copy(F.b)
t := NewFP4copy(F.a)
hint := NewFP()
s.sqr()
a.sqr()
s.times_i()
s.norm()
a.sub(s)
s.copy(a)
s.norm()
s.sqrt(h)
a.copy(t)
b.copy(t)
a.add(s)
a.norm()
a.div2()
b.copy(F.b)
b.div2()
qr := a.qr(hint)
// tweak hint - multiply old hint by Norm(1/Beta)^e where Beta is irreducible polynomial
s.copy(a)
twk := NewFPbig(NewBIGints(TWK))
twk.mul(hint)
s.div_i()
s.norm()
a.cmove(s, 1-qr)
hint.cmove(twk, 1-qr)
F.a.copy(a)
F.a.sqrt(hint)
s.copy(a)
s.inverse(hint)
s.mul(F.a)
F.b.copy(s)
F.b.mul(b)
t.copy(F.a)
F.a.cmove(F.b, 1-qr)
F.b.cmove(t, 1-qr)
sgn := F.sign()
nr := NewFP8copy(F)
nr.neg()
nr.norm()
F.cmove(nr, sgn)
}
/* */

327
ec/bls48581/HPKE.go Normal file
View File

@ -0,0 +1,327 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* Hybrid Public Key Encryption */
/* Following https://datatracker.ietf.org/doc/draft-irtf-cfrg-hpke/?include_text=1 */
package bls48581
//import "fmt"
import "source.quilibrium.com/quilibrium/ceremonyclient/ec/bls48581/core"
func reverse(X []byte) {
lx := len(X)
for i := 0; i < lx/2; i++ {
ch := X[i]
X[i] = X[lx-i-1]
X[lx-i-1] = ch
}
}
func labeledExtract(SALT []byte, SUITE_ID []byte, label string, IKM []byte) []byte {
rfc := "HPKE-v1"
RFC := []byte(rfc)
LABEL := []byte(label)
var LIKM []byte
for i := 0; i < len(RFC); i++ {
LIKM = append(LIKM, RFC[i])
}
for i := 0; i < len(SUITE_ID); i++ {
LIKM = append(LIKM, SUITE_ID[i])
}
for i := 0; i < len(LABEL); i++ {
LIKM = append(LIKM, LABEL[i])
}
if IKM != nil {
for i := 0; i < len(IKM); i++ {
LIKM = append(LIKM, IKM[i])
}
}
return core.HKDF_Extract(core.MC_SHA2, HASH_TYPE, SALT, LIKM)
}
func labeledExpand(PRK []byte, SUITE_ID []byte, label string, INFO []byte, L int) []byte {
rfc := "HPKE-v1"
RFC := []byte(rfc)
LABEL := []byte(label)
AR := core.InttoBytes(L, 2)
var LINFO []byte
for i := 0; i < len(AR); i++ {
LINFO = append(LINFO, AR[i])
}
for i := 0; i < len(RFC); i++ {
LINFO = append(LINFO, RFC[i])
}
for i := 0; i < len(SUITE_ID); i++ {
LINFO = append(LINFO, SUITE_ID[i])
}
for i := 0; i < len(LABEL); i++ {
LINFO = append(LINFO, LABEL[i])
}
if INFO != nil {
for i := 0; i < len(INFO); i++ {
LINFO = append(LINFO, INFO[i])
}
}
return core.HKDF_Expand(core.MC_SHA2, HASH_TYPE, L, PRK, LINFO)
}
func extractAndExpand(config_id int, DH []byte, context []byte) []byte {
kem := config_id & 255
txt := "KEM"
KEM_ID := core.InttoBytes(kem, 2)
KEM := []byte(txt)
var SUITE_ID []byte
for i := 0; i < len(KEM); i++ {
SUITE_ID = append(SUITE_ID, KEM[i])
}
SUITE_ID = append(SUITE_ID, KEM_ID[0])
SUITE_ID = append(SUITE_ID, KEM_ID[1])
PRK := labeledExtract(nil, SUITE_ID, "eae_prk", DH)
return labeledExpand(PRK, SUITE_ID, "shared_secret", context, HASH_TYPE)
}
func DeriveKeyPair(config_id int, SK []byte, PK []byte, SEED []byte) bool {
counter := 0
kem := config_id & 255
txt := "KEM"
KEM_ID := core.InttoBytes(kem, 2)
KEM := []byte(txt)
var SUITE_ID []byte
for i := 0; i < len(KEM); i++ {
SUITE_ID = append(SUITE_ID, KEM[i])
}
SUITE_ID = append(SUITE_ID, KEM_ID[0])
SUITE_ID = append(SUITE_ID, KEM_ID[1])
PRK := labeledExtract(nil, SUITE_ID, "dkp_prk", SEED)
var S []byte
if kem == 32 || kem == 33 { // RFC7748
S = labeledExpand(PRK, SUITE_ID, "sk", nil, EGS)
reverse(S)
if kem == 32 {
S[EGS-1] &= 248
S[0] &= 127
S[0] |= 64
} else {
S[EGS-1] &= 252
S[0] |= 128
}
} else {
bit_mask := 0xff
if kem == 18 {
bit_mask = 1
}
for i := 0; i < EGS; i++ {
S = append(S, 0)
}
for !ECDH_IN_RANGE(S) && counter < 256 {
var INFO [1]byte
INFO[0] = byte(counter)
S = labeledExpand(PRK, SUITE_ID, "candidate", INFO[:], EGS)
S[0] &= byte(bit_mask)
counter++
}
}
for i := 0; i < EGS; i++ {
SK[i] = S[i]
}
ECDH_KEY_PAIR_GENERATE(nil, SK, PK)
if kem == 32 || kem == 33 {
reverse(PK)
}
if counter < 256 {
return true
}
return false
}
func Encap(config_id int, skE []byte, pkE []byte, pkR []byte) []byte {
DH := make([]byte, EFS)
var kemcontext []byte
kem := config_id & 255
if kem == 32 || kem == 33 {
reverse(pkR)
ECDH_ECPSVDP_DH(skE, pkR, DH[:], 0)
reverse(pkR)
reverse(DH[:])
} else {
ECDH_ECPSVDP_DH(skE, pkR, DH[:], 0)
}
for i := 0; i < len(pkE); i++ {
kemcontext = append(kemcontext, pkE[i])
}
for i := 0; i < len(pkR); i++ {
kemcontext = append(kemcontext, pkR[i])
}
return extractAndExpand(config_id, DH[:], kemcontext)
}
func Decap(config_id int, skR []byte, pkE []byte, pkR []byte) []byte {
DH := make([]byte, EFS)
var kemcontext []byte
kem := config_id & 255
if kem == 32 || kem == 33 {
reverse(pkE)
ECDH_ECPSVDP_DH(skR, pkE, DH[:], 0)
reverse(pkE)
reverse(DH[:])
} else {
ECDH_ECPSVDP_DH(skR, pkE, DH[:], 0)
}
for i := 0; i < len(pkE); i++ {
kemcontext = append(kemcontext, pkE[i])
}
for i := 0; i < len(pkR); i++ {
kemcontext = append(kemcontext, pkR[i])
}
return extractAndExpand(config_id, DH[:], kemcontext)
}
func AuthEncap(config_id int, skE []byte, skS []byte, pkE []byte, pkR []byte, pkS []byte) []byte {
pklen := len(pkE)
DH := make([]byte, EFS)
DH1 := make([]byte, EFS)
kemcontext := make([]byte, 3*pklen)
kem := config_id & 255
if kem == 32 || kem == 33 {
reverse(pkR)
ECDH_ECPSVDP_DH(skE, pkR, DH[:], 0)
ECDH_ECPSVDP_DH(skS, pkR, DH1[:], 0)
reverse(pkR)
reverse(DH[:])
reverse(DH1[:])
} else {
ECDH_ECPSVDP_DH(skE, pkR, DH[:], 0)
ECDH_ECPSVDP_DH(skS, pkR, DH1[:], 0)
}
ZZ := make([]byte, 2*EFS)
for i := 0; i < EFS; i++ {
ZZ[i] = DH[i]
ZZ[EFS+i] = DH1[i]
}
for i := 0; i < pklen; i++ {
kemcontext[i] = pkE[i]
kemcontext[pklen+i] = pkR[i]
kemcontext[2*pklen+i] = pkS[i]
}
return extractAndExpand(config_id, ZZ[:], kemcontext)
}
func AuthDecap(config_id int, skR []byte, pkE []byte, pkR []byte, pkS []byte) []byte {
pklen := len(pkE)
DH := make([]byte, EFS)
DH1 := make([]byte, EFS)
kemcontext := make([]byte, 3*pklen)
kem := config_id & 255
if kem == 32 || kem == 33 {
reverse(pkE)
reverse(pkS)
ECDH_ECPSVDP_DH(skR[:], pkE, DH[:], 0)
ECDH_ECPSVDP_DH(skR[:], pkS, DH1[:], 0)
reverse(pkE)
reverse(pkS)
reverse(DH[:])
reverse(DH1[:])
} else {
ECDH_ECPSVDP_DH(skR[:], pkE, DH[:], 0)
ECDH_ECPSVDP_DH(skR[:], pkS, DH1[:], 0)
}
ZZ := make([]byte, 2*EFS)
for i := 0; i < EFS; i++ {
ZZ[i] = DH[i]
ZZ[EFS+i] = DH1[i]
}
for i := 0; i < pklen; i++ {
kemcontext[i] = pkE[i]
kemcontext[pklen+i] = pkR[i]
kemcontext[2*pklen+i] = pkS[i]
}
return extractAndExpand(config_id, ZZ[:], kemcontext)
}
/*
func printBinary(array []byte) {
for i := 0; i < len(array); i++ {
fmt.Printf("%02x", array[i])
}
fmt.Printf("\n")
}
*/
func KeySchedule(config_id int, mode int, Z []byte, info []byte, psk []byte, pskID []byte) ([]byte, []byte, []byte) {
var context []byte
kem := config_id & 255
kdf := (config_id >> 8) & 3
aead := (config_id >> 10) & 3
txt := "HPKE"
KEM := []byte(txt)
var SUITE_ID []byte
for i := 0; i < len(KEM); i++ {
SUITE_ID = append(SUITE_ID, KEM[i])
}
num := core.InttoBytes(kem, 2)
SUITE_ID = append(SUITE_ID, num[0])
SUITE_ID = append(SUITE_ID, num[1])
num = core.InttoBytes(kdf, 2)
SUITE_ID = append(SUITE_ID, num[0])
SUITE_ID = append(SUITE_ID, num[1])
num = core.InttoBytes(aead, 2)
SUITE_ID = append(SUITE_ID, num[0])
SUITE_ID = append(SUITE_ID, num[1])
ar := core.InttoBytes(mode, 1)
for i := 0; i < len(ar); i++ {
context = append(context, ar[i])
}
H := labeledExtract(nil, SUITE_ID, "psk_id_hash", pskID)
for i := 0; i < HASH_TYPE; i++ {
context = append(context, H[i])
}
H = labeledExtract(nil, SUITE_ID, "info_hash", info)
for i := 0; i < HASH_TYPE; i++ {
context = append(context, H[i])
}
//H=labeledExtract(nil,SUITE_ID,"psk_hash",psk)
//secret:=labeledExtract(H,SUITE_ID,"secret",Z)
secret := labeledExtract(Z, SUITE_ID, "secret", psk)
key := labeledExpand(secret, SUITE_ID, "key", context, AESKEY)
nonce := labeledExpand(secret, SUITE_ID, "base_nonce", context, 12)
exp_secret := labeledExpand(secret, SUITE_ID, "exp", context, HASH_TYPE)
return key, nonce, exp_secret
}

202
ec/bls48581/MPIN256.go Normal file
View File

@ -0,0 +1,202 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* MPIN 256-bit API Functions */
package bls48581
import "source.quilibrium.com/quilibrium/ceremonyclient/ec/bls48581/core"
//import "fmt"
const MFS int = int(MODBYTES)
const MGS int = int(MODBYTES)
const BAD_PARAMS int = -11
const INVALID_POINT int = -14
const WRONG_ORDER int = -18
const BAD_PIN int = -19
/* Configure your PIN here */
const MAXPIN int32 = 10000 /* PIN less than this */
const PBLEN int32 = 14 /* Number of bits in PIN */
func MPIN_HASH_ID(sha int, ID []byte) []byte {
return core.GPhashit(core.MC_SHA2, sha, int(MODBYTES), 0, nil, -1, ID)
//return mhashit(sha, 0, ID)
}
func roundup(a int, b int) int {
return (((a)-1)/(b) + 1)
}
func MPIN_ENCODE_TO_CURVE(DST []byte, ID []byte, HCID []byte) {
q := NewBIGints(Modulus)
k := q.Nbits()
r := NewBIGints(CURVE_Order)
m := r.Nbits()
L := roundup(k+roundup(m, 2), 8)
var fd = make([]byte, L)
OKM := core.XMD_Expand(core.MC_SHA2, HASH_TYPE, L, DST, ID)
for j := 0; j < L; j++ {
fd[j] = OKM[j]
}
dx := DBIG_fromBytes(fd)
u := NewFPbig(dx.Mod(q))
P := ECP_map2point(u)
P.Cfp()
P.Affine()
P.ToBytes(HCID, false)
}
/* create random secret S */
func MPIN_RANDOM_GENERATE(rng *core.RAND, S []byte) int {
r := NewBIGints(CURVE_Order)
s := Randtrunc(r, 16*AESKEY, rng)
s.ToBytes(S)
return 0
}
func MPIN_EXTRACT_PIN(CID []byte, pin int, TOKEN []byte) int {
P := ECP_fromBytes(TOKEN)
if P.Is_infinity() {
return INVALID_POINT
}
R := ECP_fromBytes(CID)
if R.Is_infinity() {
return INVALID_POINT
}
R = R.pinmul(int32(pin)%MAXPIN, PBLEN)
P.Sub(R)
P.ToBytes(TOKEN, false)
return 0
}
/* Implement step 2 on client side of MPin protocol */
func MPIN_CLIENT_2(X []byte, Y []byte, SEC []byte) int {
r := NewBIGints(CURVE_Order)
P := ECP_fromBytes(SEC)
if P.Is_infinity() {
return INVALID_POINT
}
px := FromBytes(X)
py := FromBytes(Y)
px.add(py)
px.Mod(r)
P = G1mul(P, px)
P.Neg()
P.ToBytes(SEC, false)
return 0
}
func MPIN_GET_CLIENT_SECRET(S []byte, IDHTC []byte, CST []byte) int {
s := FromBytes(S)
P := ECP_fromBytes(IDHTC)
if P.Is_infinity() {
return INVALID_POINT
}
G1mul(P, s).ToBytes(CST, false)
return 0
}
/* Implement step 1 on client side of MPin protocol */
func MPIN_CLIENT_1(CID []byte, rng *core.RAND, X []byte, pin int, TOKEN []byte, SEC []byte, xID []byte) int {
r := NewBIGints(CURVE_Order)
var x *BIG
if rng != nil {
x = Randtrunc(r, 16*AESKEY, rng)
x.ToBytes(X)
} else {
x = FromBytes(X)
}
P := ECP_fromBytes(CID)
if P.Is_infinity() {
return INVALID_POINT
}
T := ECP_fromBytes(TOKEN)
if T.Is_infinity() {
return INVALID_POINT
}
W := P.pinmul(int32(pin)%MAXPIN, PBLEN)
T.Add(W)
P = G1mul(P, x)
P.ToBytes(xID, false)
T.ToBytes(SEC, false)
return 0
}
/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
func MPIN_GET_SERVER_SECRET(S []byte, SST []byte) int {
Q := ECP8_generator()
s := FromBytes(S)
Q = G2mul(Q, s)
Q.ToBytes(SST, false)
return 0
}
/* Implement step 2 of MPin protocol on server side */
func MPIN_SERVER(HID []byte, Y []byte, SST []byte, xID []byte, mSEC []byte) int {
Q := ECP8_generator()
sQ := ECP8_fromBytes(SST)
if sQ.Is_infinity() {
return INVALID_POINT
}
if xID == nil {
return BAD_PARAMS
}
R := ECP_fromBytes(xID)
if R.Is_infinity() {
return INVALID_POINT
}
y := FromBytes(Y)
if HID == nil {
return BAD_PARAMS
}
P := ECP_fromBytes(HID)
if P.Is_infinity() {
return INVALID_POINT
}
P = G1mul(P, y)
P.Add(R)
R = ECP_fromBytes(mSEC)
if R.Is_infinity() {
return INVALID_POINT
}
var g *FP48
g = Ate2(Q, R, sQ, P)
g = Fexp(g)
if !g.Isunity() {
return BAD_PIN
}
return 0
}

978
ec/bls48581/PAIR8.go Normal file
View File

@ -0,0 +1,978 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* BLS Curve Pairing functions */
package bls48581
//import "fmt"
// Point doubling for pairings
func dbl(A *ECP8, AA *FP8, BB *FP8, CC *FP8) {
CC.copy(A.getx()) //X
YY := NewFP8copy(A.gety()) //Y
BB.copy(A.getz()) //Z
AA.copy(YY) //Y
AA.mul(BB) //YZ
CC.sqr() //X^2
YY.sqr() //Y^2
BB.sqr() //Z^2
AA.add(AA)
AA.neg()
AA.norm() //-2AA
AA.times_i()
sb := 3 * CURVE_B_I
BB.imul(sb)
CC.imul(3)
if SEXTIC_TWIST == D_TYPE {
YY.times_i()
CC.times_i()
}
if SEXTIC_TWIST == M_TYPE {
BB.times_i()
}
BB.sub(YY)
BB.norm()
A.dbl()
}
// Point addition for pairings
func add(A *ECP8, B *ECP8, AA *FP8, BB *FP8, CC *FP8) {
AA.copy(A.getx()) // X1
CC.copy(A.gety()) // Y1
T1 := NewFP8copy(A.getz()) // Z1
BB.copy(A.getz()) // Z1
T1.mul(B.gety()) // T1=Z1.Y2
BB.mul(B.getx()) // T2=Z1.X2
AA.sub(BB)
AA.norm() // X1=X1-Z1.X2
CC.sub(T1)
CC.norm() // Y1=Y1-Z1.Y2
T1.copy(AA) // T1=X1-Z1.X2
if SEXTIC_TWIST == M_TYPE {
AA.times_i()
AA.norm()
}
T1.mul(B.gety()) // T1=(X1-Z1.X2).Y2
BB.copy(CC) // T2=Y1-Z1.Y2
BB.mul(B.getx()) // T2=(Y1-Z1.Y2).X2
BB.sub(T1)
BB.norm() // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
CC.neg()
CC.norm() // Y1=-(Y1-Z1.Y2).Xs
A.Add(B)
}
func line(A *ECP8, B *ECP8, Qx *FP, Qy *FP) *FP48 {
AA := NewFP8()
BB := NewFP8()
CC := NewFP8()
var a *FP16
var b *FP16
var c *FP16
if A == B {
dbl(A, AA, BB, CC)
} else {
add(A, B, AA, BB, CC)
}
CC.tmul(Qx)
AA.tmul(Qy)
a = NewFP16fp8s(AA, BB)
if SEXTIC_TWIST == D_TYPE {
b = NewFP16fp8(CC) // L(0,1) | L(0,0) | L(1,0)
c = NewFP16()
}
if SEXTIC_TWIST == M_TYPE {
b = NewFP16()
c = NewFP16fp8(CC)
c.times_i()
}
r := NewFP48fp16s(a, b, c)
r.stype = FP_SPARSER
return r
}
/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
func lbits(n3 *BIG, n *BIG) int {
n.copy(NewBIGints(CURVE_Bnx))
n3.copy(n)
n3.pmul(3)
n3.norm()
return n3.nbits()
}
/* prepare for multi-pairing */
func Initmp() []*FP48 {
var r []*FP48
for i := ATE_BITS - 1; i >= 0; i-- {
r = append(r, NewFP48int(1))
}
return r
}
/* basic Miller loop */
func Miller(r []*FP48) *FP48 {
res := NewFP48int(1)
for i := ATE_BITS - 1; i >= 1; i-- {
res.sqr()
res.ssmul(r[i])
r[i].zero()
}
if SIGN_OF_X == NEGATIVEX {
res.conj()
}
res.ssmul(r[0])
r[0].zero()
return res
}
// Store precomputed line details in an FP8
func pack(AA *FP8, BB *FP8, CC *FP8) *FP16 {
i := NewFP8copy(CC)
i.inverse(nil)
a := NewFP8copy(AA)
a.mul(i)
b := NewFP8copy(BB)
b.mul(i)
return NewFP16fp8s(a, b)
}
// Unpack G2 line function details and include G1
func unpack(T *FP16, Qx *FP, Qy *FP) *FP48 {
var a *FP16
var b *FP16
var c *FP16
a = NewFP16copy(T)
a.geta().tmul(Qy)
t := NewFP8fp(Qx)
if SEXTIC_TWIST == D_TYPE {
b = NewFP16fp8(t)
c = NewFP16()
}
if SEXTIC_TWIST == M_TYPE {
b = NewFP16()
c = NewFP16fp8(t)
c.times_i()
}
v := NewFP48fp16s(a, b, c)
v.stype = FP_SPARSEST
return v
}
func precomp(GV *ECP8) []*FP16 {
n := NewBIG()
n3 := NewBIG()
AA := NewFP8()
BB := NewFP8()
CC := NewFP8()
var bt int
P := NewECP8()
P.Copy(GV)
A := NewECP8()
A.Copy(P)
MP := NewECP8()
MP.Copy(P)
MP.neg()
nb := lbits(n3, n)
var T []*FP16
for i := nb - 2; i >= 1; i-- {
dbl(A, AA, BB, CC)
T = append(T, pack(AA, BB, CC))
bt = n3.bit(i) - n.bit(i)
if bt == 1 {
add(A, P, AA, BB, CC)
T = append(T, pack(AA, BB, CC))
}
if bt == -1 {
add(A, MP, AA, BB, CC)
T = append(T, pack(AA, BB, CC))
}
}
return T
}
func Another_pc(r []*FP48, T []*FP16, QV *ECP) {
n := NewBIG()
n3 := NewBIG()
var lv, lv2 *FP48
var bt, j int
if QV.Is_infinity() {
return
}
Q := NewECP()
Q.Copy(QV)
Q.Affine()
Qx := NewFPcopy(Q.getx())
Qy := NewFPcopy(Q.gety())
nb := lbits(n3, n)
j = 0
for i := nb - 2; i >= 1; i-- {
lv = unpack(T[j], Qx, Qy)
j += 1
bt = n3.bit(i) - n.bit(i)
if bt == 1 {
lv2 = unpack(T[j], Qx, Qy)
j += 1
lv.smul(lv2)
}
if bt == -1 {
lv2 = unpack(T[j], Qx, Qy)
j += 1
lv.smul(lv2)
}
r[i].ssmul(lv)
}
}
/* Accumulate another set of line functions for n-pairing */
func Another(r []*FP48, P1 *ECP8, Q1 *ECP) {
n := NewBIG()
n3 := NewBIG()
var lv, lv2 *FP48
if Q1.Is_infinity() {
return
}
// P is needed in affine form for line function, Q for (Qx,Qy) extraction
P := NewECP8()
P.Copy(P1)
Q := NewECP()
Q.Copy(Q1)
P.Affine()
Q.Affine()
Qx := NewFPcopy(Q.getx())
Qy := NewFPcopy(Q.gety())
A := NewECP8()
A.Copy(P)
MP := NewECP8()
MP.Copy(P)
MP.neg()
nb := lbits(n3, n)
for i := nb - 2; i >= 1; i-- {
lv = line(A, A, Qx, Qy)
bt := n3.bit(i) - n.bit(i)
if bt == 1 {
lv2 = line(A, P, Qx, Qy)
lv.smul(lv2)
}
if bt == -1 {
lv2 = line(A, MP, Qx, Qy)
lv.smul(lv2)
}
r[i].ssmul(lv)
}
}
/* Optimal R-ate pairing */
func Ate(P1 *ECP8, Q1 *ECP) *FP48 {
n := NewBIG()
n3 := NewBIG()
var lv, lv2 *FP48
if Q1.Is_infinity() {
return NewFP48int(1)
}
P := NewECP8()
P.Copy(P1)
P.Affine()
Q := NewECP()
Q.Copy(Q1)
Q.Affine()
Qx := NewFPcopy(Q.getx())
Qy := NewFPcopy(Q.gety())
A := NewECP8()
r := NewFP48int(1)
A.Copy(P)
NP := NewECP8()
NP.Copy(P)
NP.neg()
nb := lbits(n3, n)
for i := nb - 2; i >= 1; i-- {
r.sqr()
lv = line(A, A, Qx, Qy)
bt := n3.bit(i) - n.bit(i)
if bt == 1 {
lv2 = line(A, P, Qx, Qy)
lv.smul(lv2)
}
if bt == -1 {
lv2 = line(A, NP, Qx, Qy)
lv.smul(lv2)
}
r.ssmul(lv)
}
if SIGN_OF_X == NEGATIVEX {
r.conj()
}
return r
}
/* Optimal R-ate double pairing e(P,Q).e(R,S) */
func Ate2(P1 *ECP8, Q1 *ECP, R1 *ECP8, S1 *ECP) *FP48 {
n := NewBIG()
n3 := NewBIG()
var lv, lv2 *FP48
if Q1.Is_infinity() {
return Ate(R1, S1)
}
if S1.Is_infinity() {
return Ate(P1, Q1)
}
P := NewECP8()
P.Copy(P1)
P.Affine()
Q := NewECP()
Q.Copy(Q1)
Q.Affine()
R := NewECP8()
R.Copy(R1)
R.Affine()
S := NewECP()
S.Copy(S1)
S.Affine()
Qx := NewFPcopy(Q.getx())
Qy := NewFPcopy(Q.gety())
Sx := NewFPcopy(S.getx())
Sy := NewFPcopy(S.gety())
A := NewECP8()
B := NewECP8()
r := NewFP48int(1)
A.Copy(P)
B.Copy(R)
NP := NewECP8()
NP.Copy(P)
NP.neg()
NR := NewECP8()
NR.Copy(R)
NR.neg()
nb := lbits(n3, n)
for i := nb - 2; i >= 1; i-- {
r.sqr()
lv = line(A, A, Qx, Qy)
lv2 = line(B, B, Sx, Sy)
lv.smul(lv2)
r.ssmul(lv)
bt := n3.bit(i) - n.bit(i)
if bt == 1 {
lv = line(A, P, Qx, Qy)
lv2 = line(B, R, Sx, Sy)
lv.smul(lv2)
r.ssmul(lv)
}
if bt == -1 {
lv = line(A, NP, Qx, Qy)
lv2 = line(B, NR, Sx, Sy)
lv.smul(lv2)
r.ssmul(lv)
}
}
if SIGN_OF_X == NEGATIVEX {
r.conj()
}
return r
}
/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
func Fexp(m *FP48) *FP48 {
f := NewFP2bigs(NewBIGints(Fra), NewBIGints(Frb))
x := NewBIGints(CURVE_Bnx)
r := NewFP48copy(m)
// var t1, t2 *FP48
/* Easy part of final exp */
lv := NewFP48copy(r)
lv.Inverse()
r.conj()
r.Mul(lv)
lv.Copy(r)
r.frob(f, 8)
r.Mul(lv)
/* Hard part of final exp */
// See https://eprint.iacr.org/2020/875.pdf
y1 := NewFP48copy(r)
y1.usqr()
y1.Mul(r) // y1=r^3
y0 := NewFP48copy(r.Pow(x))
if SIGN_OF_X == NEGATIVEX {
y0.conj()
}
t0 := NewFP48copy(r)
t0.conj()
r.Copy(y0)
r.Mul(t0)
y0.Copy(r.Pow(x))
if SIGN_OF_X == NEGATIVEX {
y0.conj()
}
t0.Copy(r)
t0.conj()
r.Copy(y0)
r.Mul(t0)
// ^(x+p)
y0.Copy(r.Pow(x))
if SIGN_OF_X == NEGATIVEX {
y0.conj()
}
t0.Copy(r)
t0.frob(f, 1)
r.Copy(y0)
r.Mul(t0)
// ^(x^2+p^2)
y0.Copy(r.Pow(x))
y0.Copy(y0.Pow(x))
t0.Copy(r)
t0.frob(f, 2)
r.Copy(y0)
r.Mul(t0)
// ^(x^4+p^4)
y0.Copy(r.Pow(x))
y0.Copy(y0.Pow(x))
y0.Copy(y0.Pow(x))
y0.Copy(y0.Pow(x))
t0.Copy(r)
t0.frob(f, 4)
r.Copy(y0)
r.Mul(t0)
// ^(x^8+p^8-1)
y0.Copy(r.Pow(x))
y0.Copy(y0.Pow(x))
y0.Copy(y0.Pow(x))
y0.Copy(y0.Pow(x))
y0.Copy(y0.Pow(x))
y0.Copy(y0.Pow(x))
y0.Copy(y0.Pow(x))
y0.Copy(y0.Pow(x))
t0.Copy(r)
t0.frob(f, 8)
y0.Mul(t0)
t0.Copy(r)
t0.conj()
r.Copy(y0)
r.Mul(t0)
r.Mul(y1)
r.reduce()
/*
// Ghamman & Fouotsa Method
t7 := NewFP48copy(r)
t7.usqr()
if x.parity() == 1 {
t2 = r.Pow(x)
t1 = NewFP48copy(t2)
t1.usqr()
t2 = t2.Pow(x)
} else {
t1 = t7.Pow(x)
x.fshr(1)
t2 = t1.Pow(x)
x.fshl(1)
}
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3 := NewFP48copy(t1)
t3.conj()
t2.Mul(t3)
t2.Mul(r)
r.Mul(t7)
t1 = t2.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3.Copy(t1)
t3.frob(f, 14)
r.Mul(t3)
t1 = t1.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3.Copy(t1)
t3.frob(f, 13)
r.Mul(t3)
t1 = t1.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3.Copy(t1)
t3.frob(f, 12)
r.Mul(t3)
t1 = t1.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3.Copy(t1)
t3.frob(f, 11)
r.Mul(t3)
t1 = t1.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3.Copy(t1)
t3.frob(f, 10)
r.Mul(t3)
t1 = t1.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3.Copy(t1)
t3.frob(f, 9)
r.Mul(t3)
t1 = t1.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3.Copy(t1)
t3.frob(f, 8)
r.Mul(t3)
t1 = t1.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3.Copy(t2)
t3.conj()
t1.Mul(t3)
t3.Copy(t1)
t3.frob(f, 7)
r.Mul(t3)
t1 = t1.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3.Copy(t1)
t3.frob(f, 6)
r.Mul(t3)
t1 = t1.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3.Copy(t1)
t3.frob(f, 5)
r.Mul(t3)
t1 = t1.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3.Copy(t1)
t3.frob(f, 4)
r.Mul(t3)
t1 = t1.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3.Copy(t1)
t3.frob(f, 3)
r.Mul(t3)
t1 = t1.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3.Copy(t1)
t3.frob(f, 2)
r.Mul(t3)
t1 = t1.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
t3.Copy(t1)
t3.frob(f, 1)
r.Mul(t3)
t1 = t1.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t1.conj()
}
r.Mul(t1)
t2.frob(f, 15)
r.Mul(t2)
r.reduce()
*/
return r
}
/* GLV method */
func glv(ee *BIG) []*BIG {
var u []*BIG
q := NewBIGints(CURVE_Order)
x := NewBIGints(CURVE_Bnx)
x2 := smul(x, x)
x = smul(x2, x2)
x2 = smul(x, x)
bd := uint(q.nbits() - x2.nbits())
u = append(u, NewBIGcopy(ee))
u[0].ctmod(x2, bd)
u = append(u, NewBIGcopy(ee))
u[1].ctdiv(x2, bd)
u[1].rsub(q)
return u
}
/* Galbraith & Scott Method */
func gs(ee *BIG) []*BIG {
var u []*BIG
q := NewBIGints(CURVE_Order)
x := NewBIGints(CURVE_Bnx)
bd := uint(q.nbits() - x.nbits())
w := NewBIGcopy(ee)
for i := 0; i < 15; i++ {
u = append(u, NewBIGcopy(w))
u[i].ctmod(x, bd)
w.ctdiv(x, bd)
}
u = append(u, NewBIGcopy(w))
if SIGN_OF_X == NEGATIVEX {
u[1].copy(Modneg(u[1], q))
u[3].copy(Modneg(u[3], q))
u[5].copy(Modneg(u[5], q))
u[7].copy(Modneg(u[7], q))
u[9].copy(Modneg(u[9], q))
u[11].copy(Modneg(u[11], q))
u[13].copy(Modneg(u[13], q))
u[15].copy(Modneg(u[15], q))
}
return u
}
/* Multiply P by e in group G1 */
func G1mul(P *ECP, e *BIG) *ECP {
var R *ECP
q := NewBIGints(CURVE_Order)
ee := NewBIGcopy(e)
ee.Mod(q)
if USE_GLV {
R = NewECP()
R.Copy(P)
Q := NewECP()
Q.Copy(P)
Q.Affine()
cru := NewFPbig(NewBIGints(CRu))
t := NewBIGint(0)
u := glv(ee)
Q.getx().mul(cru)
np := u[0].nbits()
t.copy(Modneg(u[0], q))
nn := t.nbits()
if nn < np {
u[0].copy(t)
R.Neg()
}
np = u[1].nbits()
t.copy(Modneg(u[1], q))
nn = t.nbits()
if nn < np {
u[1].copy(t)
Q.Neg()
}
u[0].norm()
u[1].norm()
R = R.Mul2(u[0], Q, u[1])
} else {
R = P.clmul(e, q)
}
return R
}
/* Multiply P by e in group G2 */
func G2mul(P *ECP8, e *BIG) *ECP8 {
var R *ECP8
q := NewBIGints(CURVE_Order)
ee := NewBIGcopy(e)
ee.Mod(q)
if USE_GS_G2 {
var Q []*ECP8
F := ECP8_frob_constants()
u := gs(ee)
t := NewBIGint(0)
Q = append(Q, NewECP8())
Q[0].Copy(P)
for i := 1; i < 16; i++ {
Q = append(Q, NewECP8())
Q[i].Copy(Q[i-1])
Q[i].frob(F, 1)
}
for i := 0; i < 16; i++ {
np := u[i].nbits()
t.copy(Modneg(u[i], q))
nn := t.nbits()
if nn < np {
u[i].copy(t)
Q[i].neg()
}
u[i].norm()
}
R = mul16(Q, u)
} else {
R = P.mul(e)
}
return R
}
/* f=f^e */
/* Note that this method requires a lot of RAM! */
func GTpow(d *FP48, e *BIG) *FP48 {
var r *FP48
q := NewBIGints(CURVE_Order)
ee := NewBIGcopy(e)
ee.Mod(q)
if USE_GS_GT {
var g []*FP48
f := NewFP2bigs(NewBIGints(Fra), NewBIGints(Frb))
t := NewBIGint(0)
u := gs(ee)
g = append(g, NewFP48copy(d))
for i := 1; i < 16; i++ {
g = append(g, NewFP48())
g[i].Copy(g[i-1])
g[i].frob(f, 1)
}
for i := 0; i < 16; i++ {
np := u[i].nbits()
t.copy(Modneg(u[i], q))
nn := t.nbits()
if nn < np {
u[i].copy(t)
g[i].conj()
}
u[i].norm()
}
r = pow16(g, u)
} else {
r = d.Pow(ee)
}
return r
}
/* test G1 group membership */
func G1member(P *ECP) bool {
if P.Is_infinity() {
return false
}
x := NewBIGints(CURVE_Bnx)
cru := NewFPbig(NewBIGints(CRu))
W := NewECP()
W.Copy(P)
W.getx().mul(cru)
T := P.mul(x)
if P.Equals(T) {
return false
} // P is of low order
T = T.mul(x)
T = T.mul(x)
T = T.mul(x)
T = T.mul(x)
T = T.mul(x)
T = T.mul(x)
T = T.mul(x)
T.Neg()
if !W.Equals(T) {
return false
}
// Not needed
// W.Add(P);
// T.getx().mul(cru)
// W.Add(T)
// if !W.Is_infinity() {return false}
/*
q := NewBIGints(CURVE_Order)
if P.Is_infinity() {return false}
W:=P.mul(q)
if !W.Is_infinity() {return false} */
return true
}
/* test G2 group membership */
func G2member(P *ECP8) bool {
if P.Is_infinity() {
return false
}
F := ECP8_frob_constants()
x := NewBIGints(CURVE_Bnx)
W := NewECP8()
W.Copy(P)
W.frob(F, 1)
T := P.mul(x)
if SIGN_OF_X == NEGATIVEX {
T.neg()
}
/*
R:=NewECP8(); R.Copy(W)
R.frob(F,1)
W.Sub(R)
R.Copy(T)
R.frob(F,1)
W.Add(R)
*/
if !W.Equals(T) {
return false
}
return true
/*
q := NewBIGints(CURVE_Order)
if P.Is_infinity() {return false}
W:=P.mul(q)
if !W.Is_infinity() {return false}
return true */
}
/* Check that m is in cyclotomic sub-group */
/* Check that m!=1, conj(m)*m==1, and m.m^{p^16}=m^{p^8} */
func GTcyclotomic(m *FP48) bool {
if m.Isunity() {
return false
}
r := NewFP48copy(m)
r.conj()
r.Mul(m)
if !r.Isunity() {
return false
}
f := NewFP2bigs(NewBIGints(Fra), NewBIGints(Frb))
r.Copy(m)
r.frob(f, 8)
w := NewFP48copy(r)
w.frob(f, 8)
w.Mul(m)
if !w.Equals(r) {
return false
}
return true
}
/* test for full GT membership */
func GTmember(m *FP48) bool {
if !GTcyclotomic(m) {
return false
}
f := NewFP2bigs(NewBIGints(Fra), NewBIGints(Frb))
x := NewBIGints(CURVE_Bnx)
r := NewFP48copy(m)
r.frob(f, 1)
t := m.Pow(x)
if SIGN_OF_X == NEGATIVEX {
t.conj()
}
if !r.Equals(t) {
return false
}
return true
/*
q := NewBIGints(CURVE_Order)
r := m.Pow(q)
if !r.Isunity() {
return false
}
return true */
}

74
ec/bls48581/ROM.go Normal file
View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* Fixed Data in ROM - Field and Curve parameters */
package bls48581
// Base Bits= 29
var Modulus = [...]Chunk{0x565912B, 0x16E0AA73, 0x12922B0F, 0x1FBEE434, 0xEE0A578, 0x12A898B8, 0xBDA0D9E, 0x9E8E6DB, 0x19CD3039, 0x17041566, 0x2B90EBD, 0xEA88949, 0xC0F1F39, 0x18DD9DF3, 0x1E344884, 0xADD09, 0x1D47012A, 0x9C12718, 0x1CD1DBCC, 0x501EE7F, 0x1}
var ROI = [...]Chunk{0x565912A, 0x16E0AA73, 0x12922B0F, 0x1FBEE434, 0xEE0A578, 0x12A898B8, 0xBDA0D9E, 0x9E8E6DB, 0x19CD3039, 0x17041566, 0x2B90EBD, 0xEA88949, 0xC0F1F39, 0x18DD9DF3, 0x1E344884, 0xADD09, 0x1D47012A, 0x9C12718, 0x1CD1DBCC, 0x501EE7F, 0x1}
var R2modp = [...]Chunk{0x19BCC5B0, 0x126A343E, 0xA46F6C0, 0x29B7799, 0xB758510, 0x1357043D, 0x1DC2D482, 0x115A8C75, 0x1F6CA5F6, 0x9B40365, 0x16E1C7DB, 0x1A304684, 0xA85F60F, 0x16E21141, 0x1D5AE21, 0xD9EA745, 0x1641FB69, 0x249C4AC, 0xA2B23E1, 0x14FCE472, 0x0}
var SQRTm3 = [...]Chunk{0x1D65A0A, 0x8F6FE15, 0xB6336FD, 0xC5B5452, 0x69D616D, 0x8923C1, 0x1E2B5C49, 0x4BA7957, 0x13E4CD6C, 0x14D8B5AE, 0x583BB23, 0x14076E71, 0x14343F50, 0x121BB7F6, 0xB818699, 0x11F7124B, 0x1EAABFFD, 0x4635146, 0x69D8024, 0x501EE7F, 0x1}
const MConst Chunk = 0x39D5A7D
var Fra = [...]Chunk{0x42AEB25, 0x1175B67F, 0x182B4FE5, 0x1683284E, 0x115ECE4D, 0x1EF92B83, 0x22B03E9, 0x6EF6A24, 0x8C41890, 0x4249F0E, 0x61F9A1, 0xC60FC53, 0x16B62F49, 0x71E57E, 0xF9E161D, 0xFA08F30, 0x1E55F606, 0x1AE6BF39, 0x140527E9, 0x1FA61B6, 0x0}
var Frb = [...]Chunk{0x42AEB25, 0x1175B67F, 0x182B4FE5, 0x1683284E, 0x115ECE4D, 0x1EF92B83, 0x22B03E9, 0x6EF6A24, 0x8C41890, 0x4249F0E, 0x61F9A1, 0xC60FC53, 0x16B62F49, 0x71E57E, 0xF9E161D, 0xFA08F30, 0x1E55F606, 0x1AE6BF39, 0x140527E9, 0x1FA61B6, 0x0}
var TWK = [...]Chunk{0x1F426953, 0x1DA19E92, 0xEE618F5, 0x159C8B24, 0xD37E160, 0x145DEFD1, 0xD2F0630, 0x1FF9915F, 0x2C4F62, 0xDA1C978, 0x51E0598, 0x4FD2A34, 0x132462ED, 0x13341DC2, 0x81D59C2, 0x19374271, 0x1D9EAEB8, 0x1ABB4E6E, 0xDEF0401, 0x74CB4A, 0x0}
//*** rom curve parameters *****
// Base Bits= 29
// Ate Bits= 33
// G2 Table size= 36
const CURVE_Cof_I int = 0
var CURVE_Cof = [...]Chunk{0x382, 0xA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
const CURVE_B_I int = 1
var CURVE_B = [...]Chunk{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
var CURVE_Order = [...]Chunk{0xD671C01, 0x52FF37E, 0x10936846, 0x1CB328CF, 0x103C4CCB, 0x1E682B11, 0x5AA171, 0x6989924, 0x741969D, 0xB961737, 0xFEB5AF2, 0x16797C00, 0x1387A3F0, 0x6B631A, 0x13305857, 0xBC46753, 0x925E288, 0x11C37C5, 0x0, 0x0, 0x0}
var CURVE_Gx = [...]Chunk{0x115AF640, 0x1E743991, 0x79B630E, 0x9B4BA74, 0x11786CB7, 0x1ED9B458, 0x1BAF6F15, 0xBB0B246, 0x4584766, 0x14EFB7CB, 0x1154151A, 0x1F73EEA8, 0xBDBAEDF, 0x3467B0D, 0x15F83A1A, 0xC1BC7E4, 0x1F1E93F8, 0x1D795B9E, 0xB0D03CA, 0x55EB36F, 0x0}
var CURVE_Gy = [...]Chunk{0x2587A70, 0xDDAEF1F, 0x49AD5DB, 0x6F5DEF7, 0x11B2E35F, 0x1BE143B6, 0x8BD21FD, 0xB0987DE, 0x1E80F678, 0x1CC57729, 0xEDEFBFE, 0x16E41DEF, 0x1279DD41, 0x52974C8, 0xF27BFAE, 0x149114AA, 0xD1FB398, 0xFC359D1, 0x1D94C7E4, 0x19DFB489, 0x0}
var CURVE_HTPC = [...]Chunk{0x31193EC, 0x1C9F85F0, 0x1D6090C, 0x5112C88, 0x10D4620C, 0x1F255473, 0x1F5583B6, 0x4F7AABD, 0xCD0706B, 0x14B125F7, 0xECD8492, 0x4D5AF8A, 0xC755E26, 0x2D4C018, 0xB0B7761, 0x1369CD4C, 0x1FD42938, 0x782EC54, 0x17716BE5, 0x1246919A, 0x0}
var CURVE_Bnx = [...]Chunk{0x381, 0xA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
var CRu = [...]Chunk{0x1C79B90, 0x6F4D62F, 0x3977A09, 0x19B1C7F1, 0x1421A205, 0x190FBA7B, 0x16D758AA, 0x129736C1, 0x2F43166, 0x115AFDC, 0x1E9AA9CD, 0xD508D6B, 0xBED6FF4, 0x1360F2FE, 0x95960F5, 0x709E55F, 0x1F4E2096, 0x2AEEAE8, 0xB1A2DD4, 0x0, 0x0}
var CURVE_Pxaaa = [...]Chunk{0xCE8BFAB, 0x1A7E85A5, 0x85537B0, 0xF2ECC64, 0x1510317B, 0x6C0248F, 0x140C01, 0x140C25E8, 0x281A63C, 0x168D4621, 0x1BFDE6EA, 0x1DE2AD88, 0x64DB3A2, 0xDE65BEF, 0x1F1C0D13, 0x1BD7577D, 0x45A2775, 0x11C11BFD, 0x9E1C792, 0xBAC2BB3, 0x0}
var CURVE_Pxaab = [...]Chunk{0x16B47C57, 0x134D9B33, 0x1E850FC5, 0xAAD4035, 0x30FFD75, 0x1186CBCB, 0x13C30F1D, 0x1FF4C4A0, 0x214A76A, 0x15FF6F8B, 0xE50E802, 0xFE9C38, 0xF6DA123, 0x111F4A93, 0x1B660385, 0x1D164576, 0x86ABC07, 0x9034D87, 0x13889614, 0xF892E7D, 0x0}
var CURVE_Pxaba = [...]Chunk{0x55A3E6A, 0x440AB65, 0xCFC2D19, 0x1E99BDAD, 0x1D5FEA8E, 0x1EFDDC3C, 0x157C0A32, 0x1E1A54DA, 0xFFAE766, 0xDE8C921, 0x18058707, 0x156B56D0, 0x16957CCB, 0x1BE53D36, 0x1B2A6B88, 0x178E7514, 0x1853AD83, 0x70D9750, 0x663C4CD, 0x3F998E0, 0x0}
var CURVE_Pxabb = [...]Chunk{0x1B7FEAFE, 0xD3819E5, 0x2F0FC2, 0x171969D, 0xCA5231, 0x292BE10, 0x51A30C7, 0x16364F37, 0xE6EC143, 0x11F0E3BB, 0x862A57D, 0x1F17C198, 0x1B92A393, 0x1F2C10DB, 0x16B18BC, 0x17FD1EB3, 0x12954D4, 0x2E3C6C0, 0x973AD86, 0x17C44318, 0x0}
var CURVE_Pxbaa = [...]Chunk{0x13F8CCE5, 0x1CE1D0E2, 0x7532EDC, 0x16BEE8D9, 0x1AA80C65, 0xAFE0C44, 0x49D3EB5, 0x9255CB1, 0xC10B2EF, 0x40CCEAD, 0x6607E79, 0xA70CD3, 0x1F0E7C58, 0x15AB3AF, 0x1D742C59, 0xC600F8C, 0x4CAA9DD, 0x1D1E2CC7, 0x2CD644, 0x717238C, 0x0}
var CURVE_Pxbab = [...]Chunk{0xA3C093A, 0x10026C8A, 0x138CDC3C, 0x12C1221F, 0xF097FC7, 0xF8BBB09, 0x175D656A, 0x1738162B, 0x1EB57B40, 0x1AE944CB, 0x77D8E0, 0x6E8303, 0x58677BB, 0xBBD1E8D, 0xD773BC2, 0x111EF71E, 0x1E4ECDA0, 0x101F8988, 0x1FAC1CE1, 0x192D8EF2, 0x0}
var CURVE_Pxbba = [...]Chunk{0x750E057, 0xB03F30, 0x170CD539, 0x16B61C40, 0x2D63334, 0x1F219261, 0xCAAB472, 0xBDF9E68, 0x10FD0CAA, 0x9D89E76, 0x13BC47CA, 0x16F4893, 0x1908BA2C, 0x1C295B6D, 0x106CE744, 0x1CCC1BD4, 0x98908AE, 0x1F80CBD2, 0x118187B8, 0x1736F2A3, 0x0}
var CURVE_Pxbbb = [...]Chunk{0x1BC6AE34, 0x10CED007, 0x5F0FE13, 0x15E5F93D, 0x1FC44E56, 0x1EB575FC, 0x116151E6, 0x16FC561A, 0x164A7190, 0x1F94E7F9, 0x1E33F2A4, 0xE514FF3, 0xF741719, 0x3DA908E, 0xA77BEBD, 0x563CBAF, 0xC4F4AAA, 0x2941312, 0xBECAF7B, 0x104FAB84, 0x0}
var CURVE_Pyaaa = [...]Chunk{0xD2D7971, 0x1F6E9FF2, 0xB03FCC8, 0xA025562, 0x6D65904, 0x15FBBF75, 0x18F05666, 0xDB15CA2, 0xD90F733, 0x17D13BA4, 0x24188D6, 0x86BF556, 0x1B39EBFC, 0x12BBF379, 0x108E0166, 0x4972316, 0x16452F30, 0xFD24B90, 0x1B0DD6D7, 0x1D6A66A, 0x0}
var CURVE_Pyaab = [...]Chunk{0x16CD5665, 0xA38EDC9, 0x1FF1EC44, 0x16846A4B, 0xE2E588, 0x1D04BEBB, 0x1877484B, 0x11255649, 0x12C5C3D1, 0x121D8F8C, 0xBEC25AC, 0x65F97E7, 0x1D729647, 0xF37DD00, 0x108AE8C9, 0x1B856EB4, 0x11815FCA, 0xA26D329, 0x5E783FC, 0x509B8EB, 0x0}
var CURVE_Pyaba = [...]Chunk{0xA2A8474, 0x1995293, 0xEE3F79A, 0x18F88DF8, 0x52269CB, 0x9AEA8D3, 0x178BC307, 0x194652BC, 0x11515536, 0xE874820, 0x17DF5726, 0xE0A288E, 0x13A480D3, 0x16AD88CE, 0x1140C085, 0x13DE585F, 0x17036766, 0x1F210F7D, 0x17402148, 0x166D4403, 0x0}
var CURVE_Pyabb = [...]Chunk{0x841589D, 0x1109ED49, 0x194CDCC5, 0x7B17143, 0x5E578FB, 0x1ED281F7, 0xE84359E, 0xEE84EE1, 0xDCED281, 0x199FD20, 0xB226C89, 0x245A4E8, 0xB0E710E, 0x7711EEC, 0x1B4CD837, 0x563859B, 0x1BD47876, 0x144111FD, 0x1887B701, 0x15D84B48, 0x0}
var CURVE_Pybaa = [...]Chunk{0x2E50137, 0x3C18FCC, 0x13DE90FD, 0xAFFBBBF, 0x1137B088, 0x9ACA2E, 0x13D67D0C, 0x9CA256C, 0x8A1E2CA, 0x111C66E7, 0x16171DFE, 0x2530AFD, 0x159805F1, 0xEC9DAD4, 0x11506D0F, 0xB44AA9B, 0x1A5A8832, 0x148B281F, 0x88EA711, 0x1A413AB4, 0x0}
var CURVE_Pybab = [...]Chunk{0xF90BEE4, 0x776E2C6, 0x1B3CE965, 0xB3DB044, 0x12B679DA, 0xCC6553, 0xE78EABF, 0xF8301A2, 0x1F6824F4, 0x6138420, 0xA0D083A, 0x156EA09F, 0x182E2055, 0x1915AC4E, 0x159BAC59, 0x17208435, 0x1D5AD537, 0x1289E99C, 0x115CDADE, 0xFA1A06E, 0x0}
var CURVE_Pybba = [...]Chunk{0x1EB23986, 0xA0FD757, 0x6A98ACF, 0x110802FB, 0x13DCCC9E, 0x7D31CFA, 0x62D6ED0, 0x118E964C, 0x122C1FAB, 0x11D14327, 0x63D096B, 0x10334DBF, 0x15F14E4C, 0xD8320A, 0xD93F021, 0x1F1400DE, 0x1DFDD17A, 0x112E1682, 0x46F997A, 0x112CECF0, 0x0}
var CURVE_Pybbb = [...]Chunk{0x132718B6, 0x133FFE5B, 0x1A71575, 0x158CDD08, 0x13F748E5, 0x6C62559, 0x1505CC0, 0x7D8E324, 0x1E1AD033, 0x14E18F4B, 0xCE8FE39, 0x1D95352A, 0x149B6EF8, 0x728643A, 0x1C501AFA, 0x36BC0D1, 0x7E84F98, 0x9C9D2E0, 0x1FE240A7, 0x6BC4A49, 0x0}
//var CURVE_W=[2][21]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
//var CURVE_SB=[2][2][21]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
//var CURVE_WB=[4][21]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
//var CURVE_BB=[4][4][21]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}

835
ec/bls48581/core/AES.go Normal file
View File

@ -0,0 +1,835 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* AES Encryption */
package core
//import "fmt"
const AES_ECB int = 0
const AES_CBC int = 1
const AES_CFB1 int = 2
const AES_CFB2 int = 3
const AES_CFB4 int = 5
const AES_OFB1 int = 14
const AES_OFB2 int = 15
const AES_OFB4 int = 17
const AES_OFB8 int = 21
const AES_OFB16 int = 29
const AES_CTR1 int = 30
const AES_CTR2 int = 31
const AES_CTR4 int = 33
const AES_CTR8 int = 37
const AES_CTR16 int = 45
var aes_InCo = [...]byte{0xB, 0xD, 0x9, 0xE} /* Inverse Coefficients */
var aes_ptab = [...]byte{
1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1}
var aes_ltab = [...]byte{
0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,
125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,
101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,
150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,
102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,
126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,
175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,
44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,
127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,
204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,
151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,
83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,
103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7}
var aes_fbsub = [...]byte{
99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22}
var aes_rbsub = [...]byte{
82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,
124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,
84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,
8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,
114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,
108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,
144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,
208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,
58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,
252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,
31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,
96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,
160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125}
var aes_rco = [...]byte{1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47}
var aes_ftable = [...]uint32{
0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0xdf2f2ff, 0xbd6b6bd6,
0xb16f6fde, 0x54c5c591, 0x50303060, 0x3010102, 0xa96767ce, 0x7d2b2b56,
0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, 0x45caca8f, 0x9d82821f,
0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0xbf0f0fb,
0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,
0x5a36366c, 0x413f3f7e, 0x2f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551,
0x34e5e5d1, 0x8f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
0xc040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637,
0xf05050a, 0xb59a9a2f, 0x907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d,
0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd,
0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x0, 0x2cededc1,
0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a,
0x55333366, 0x94858511, 0xcf45458a, 0x10f9f9e9, 0x6020204, 0x817f7ffe,
0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d,
0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x4f5f5f1,
0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5,
0xef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,
0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755,
0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,
0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, 0x3be0e0db, 0x56323264,
0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0xa06060c, 0x6c242448, 0xe45c5cb8,
0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531,
0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac,
0x7f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657,
0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,
0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x5030306, 0x1f6f6f7, 0x120e0e1c,
0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199,
0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,
0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c,
0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7,
0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c}
var aes_rtable = [...]uint32{
0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f,
0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5,
0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, 0x495ab1de, 0x671bba25,
0x980eea45, 0xe1c0fe5d, 0x2752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b,
0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927,
0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, 0x184adf63, 0x82311ae5,
0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9,
0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72,
0x578f1fe3, 0x2aab5566, 0x728ebb2, 0x3c2b52f, 0x9a7bc586, 0xa50837d3,
0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a, 0x92b479a7,
0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4,
0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040,
0x69f715e, 0x51106ebd, 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d,
0xb58d5491, 0x55dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879,
0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x0, 0x83868009, 0x48ed2b32,
0xac70111e, 0x4e725a6c, 0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36,
0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0xfe75793,
0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
0xaba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0xb0d090e, 0xadc78bf2,
0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3,
0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, 0x7629438b, 0xdcc623cb,
0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684,
0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947,
0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322, 0xc74e4987, 0xc1d138d9,
0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f,
0xe49d3a2c, 0xd927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890,
0x5ef7392e, 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x97826cd, 0xf418596e,
0x1b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x8cfbc21, 0xe6e815ef,
0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, 0xafb2a431, 0x31233f2a,
0x3094a5c6, 0xc066a235, 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733,
0x4a9804f1, 0xf7daec41, 0xe50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546,
0x4ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92,
0x335610e9, 0x1347d66d, 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb,
0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255,
0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0xc25e2bc,
0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664,
0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0}
type AES struct {
Nk int
Nr int
mode int
fkey [60]uint32
rkey [60]uint32
f [16]byte
}
/* Rotates 32-bit word left by 1, 2 or 3 byte */
func aes_ROTL8(x uint32) uint32 {
return (((x) << 8) | ((x) >> 24))
}
func aes_ROTL16(x uint32) uint32 {
return (((x) << 16) | ((x) >> 16))
}
func aes_ROTL24(x uint32) uint32 {
return (((x) << 24) | ((x) >> 8))
}
func aes_pack(b [4]byte) uint32 { /* pack bytes into a 32-bit Word */
return ((uint32(b[3]) & 0xff) << 24) | ((uint32(b[2]) & 0xff) << 16) | ((uint32(b[1]) & 0xff) << 8) | (uint32(b[0]) & 0xff)
}
func aes_unpack(a uint32) [4]byte { /* unpack bytes from a word */
var b = [4]byte{byte(a & 0xff), byte((a >> 8) & 0xff), byte((a >> 16) & 0xff), byte((a >> 24) & 0xff)}
return b
}
func aes_bmul(x byte, y byte) byte { /* x.y= AntiLog(Log(x) + Log(y)) */
ix := int(x) & 0xff
iy := int(y) & 0xff
lx := int(aes_ltab[ix]) & 0xff
ly := int(aes_ltab[iy]) & 0xff
if x != 0 && y != 0 {
return aes_ptab[(lx+ly)%255]
} else {
return byte(0)
}
}
func aes_SubByte(a uint32) uint32 {
b := aes_unpack(a)
b[0] = aes_fbsub[int(b[0])]
b[1] = aes_fbsub[int(b[1])]
b[2] = aes_fbsub[int(b[2])]
b[3] = aes_fbsub[int(b[3])]
return aes_pack(b)
}
func aes_product(x uint32, y uint32) byte { /* dot product of two 4-byte arrays */
xb := aes_unpack(x)
yb := aes_unpack(y)
return (aes_bmul(xb[0], yb[0]) ^ aes_bmul(xb[1], yb[1]) ^ aes_bmul(xb[2], yb[2]) ^ aes_bmul(xb[3], yb[3]))
}
func aes_InvMixCol(x uint32) uint32 { /* matrix Multiplication */
var b [4]byte
m := aes_pack(aes_InCo)
b[3] = aes_product(m, x)
m = aes_ROTL24(m)
b[2] = aes_product(m, x)
m = aes_ROTL24(m)
b[1] = aes_product(m, x)
m = aes_ROTL24(m)
b[0] = aes_product(m, x)
var y = aes_pack(b)
return y
}
func aes_increment(f []byte) {
for i := 0; i < 16; i++ {
f[i]++
if f[i] != 0 {
break
}
}
}
/* reset cipher */
func (A *AES) Reset(m int, iv []byte) { /* reset mode, or reset iv */
A.mode = m
for i := 0; i < 16; i++ {
A.f[i] = 0
}
if (A.mode != AES_ECB) && (iv != nil) {
for i := 0; i < 16; i++ {
A.f[i] = iv[i]
}
}
}
func (A *AES) Init(m int, nk int, key []byte, iv []byte) bool {
/* Key Scheduler. Create expanded encryption key */
var CipherKey [8]uint32
var b [4]byte
nk /= 4
if nk != 4 && nk != 6 && nk != 8 {
return false
}
nr := 6 + nk
A.Nk = nk
A.Nr = nr
A.Reset(m, iv)
N := 4 * (nr + 1)
j := 0
for i := 0; i < nk; i++ {
for k := 0; k < 4; k++ {
b[k] = key[j+k]
}
CipherKey[i] = aes_pack(b)
j += 4
}
for i := 0; i < nk; i++ {
A.fkey[i] = CipherKey[i]
}
j = nk
for k := 0; j < N; k++ {
A.fkey[j] = A.fkey[j-nk] ^ aes_SubByte(aes_ROTL24(A.fkey[j-1])) ^ uint32(aes_rco[k])
if nk <= 6 {
for i := 1; i < nk && (i+j) < N; i++ {
A.fkey[i+j] = A.fkey[i+j-nk] ^ A.fkey[i+j-1]
}
} else {
i := 0
for i = 1; i < 4 && (i+j) < N; i++ {
A.fkey[i+j] = A.fkey[i+j-nk] ^ A.fkey[i+j-1]
}
if (j + 4) < N {
A.fkey[j+4] = A.fkey[j+4-nk] ^ aes_SubByte(A.fkey[j+3])
}
for i = 5; i < nk && (i+j) < N; i++ {
A.fkey[i+j] = A.fkey[i+j-nk] ^ A.fkey[i+j-1]
}
}
j += nk
}
/* now for the expanded decrypt key in reverse order */
for j := 0; j < 4; j++ {
A.rkey[j+N-4] = A.fkey[j]
}
for i := 4; i < N-4; i += 4 {
k := N - 4 - i
for j := 0; j < 4; j++ {
A.rkey[k+j] = aes_InvMixCol(A.fkey[i+j])
}
}
for j := N - 4; j < N; j++ {
A.rkey[j-N+4] = A.fkey[j]
}
return true
}
func NewAES() *AES {
var A = new(AES)
return A
}
func (A *AES) Getreg() [16]byte {
var ir [16]byte
for i := 0; i < 16; i++ {
ir[i] = A.f[i]
}
return ir
}
/* Encrypt a single block */
func (A *AES) ecb_encrypt(buff []byte) {
var b [4]byte
var p [4]uint32
var q [4]uint32
j := 0
for i := 0; i < 4; i++ {
for k := 0; k < 4; k++ {
b[k] = buff[j+k]
}
p[i] = aes_pack(b)
p[i] ^= A.fkey[i]
j += 4
}
k := 4
/* State alternates between p and q */
for i := 1; i < A.Nr; i++ {
q[0] = A.fkey[k] ^ aes_ftable[int(p[0]&0xff)] ^ aes_ROTL8(aes_ftable[int((p[1]>>8)&0xff)]) ^ aes_ROTL16(aes_ftable[int((p[2]>>16)&0xff)]) ^ aes_ROTL24(aes_ftable[int((p[3]>>24)&0xff)])
q[1] = A.fkey[k+1] ^ aes_ftable[int(p[1]&0xff)] ^ aes_ROTL8(aes_ftable[int((p[2]>>8)&0xff)]) ^ aes_ROTL16(aes_ftable[int((p[3]>>16)&0xff)]) ^ aes_ROTL24(aes_ftable[int((p[0]>>24)&0xff)])
q[2] = A.fkey[k+2] ^ aes_ftable[int(p[2]&0xff)] ^ aes_ROTL8(aes_ftable[int((p[3]>>8)&0xff)]) ^ aes_ROTL16(aes_ftable[int((p[0]>>16)&0xff)]) ^ aes_ROTL24(aes_ftable[int((p[1]>>24)&0xff)])
q[3] = A.fkey[k+3] ^ aes_ftable[int(p[3]&0xff)] ^ aes_ROTL8(aes_ftable[int((p[0]>>8)&0xff)]) ^ aes_ROTL16(aes_ftable[int((p[1]>>16)&0xff)]) ^ aes_ROTL24(aes_ftable[int((p[2]>>24)&0xff)])
k += 4
for j = 0; j < 4; j++ {
t := p[j]
p[j] = q[j]
q[j] = t
}
}
/* Last Round */
q[0] = A.fkey[k] ^ uint32(aes_fbsub[int(p[0]&0xff)]) ^ aes_ROTL8(uint32(aes_fbsub[int((p[1]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_fbsub[int((p[2]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_fbsub[int((p[3]>>24)&0xff)]))
q[1] = A.fkey[k+1] ^ uint32(aes_fbsub[int(p[1]&0xff)]) ^ aes_ROTL8(uint32(aes_fbsub[int((p[2]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_fbsub[int((p[3]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_fbsub[int((p[0]>>24)&0xff)]))
q[2] = A.fkey[k+2] ^ uint32(aes_fbsub[int(p[2]&0xff)]) ^ aes_ROTL8(uint32(aes_fbsub[int((p[3]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_fbsub[int((p[0]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_fbsub[int((p[1]>>24)&0xff)]))
q[3] = A.fkey[k+3] ^ uint32(aes_fbsub[int(p[3]&0xff)]) ^ aes_ROTL8(uint32(aes_fbsub[int((p[0]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_fbsub[int((p[1]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_fbsub[int((p[2]>>24)&0xff)]))
j = 0
for i := 0; i < 4; i++ {
b = aes_unpack(q[i])
for k = 0; k < 4; k++ {
buff[j+k] = b[k]
}
j += 4
}
}
/* Decrypt a single block */
func (A *AES) ecb_decrypt(buff []byte) {
var b [4]byte
var p [4]uint32
var q [4]uint32
j := 0
for i := 0; i < 4; i++ {
for k := 0; k < 4; k++ {
b[k] = buff[j+k]
}
p[i] = aes_pack(b)
p[i] ^= A.rkey[i]
j += 4
}
k := 4
/* State alternates between p and q */
for i := 1; i < A.Nr; i++ {
q[0] = A.rkey[k] ^ aes_rtable[int(p[0]&0xff)] ^ aes_ROTL8(aes_rtable[int((p[3]>>8)&0xff)]) ^ aes_ROTL16(aes_rtable[int((p[2]>>16)&0xff)]) ^ aes_ROTL24(aes_rtable[int((p[1]>>24)&0xff)])
q[1] = A.rkey[k+1] ^ aes_rtable[int(p[1]&0xff)] ^ aes_ROTL8(aes_rtable[int((p[0]>>8)&0xff)]) ^ aes_ROTL16(aes_rtable[int((p[3]>>16)&0xff)]) ^ aes_ROTL24(aes_rtable[int((p[2]>>24)&0xff)])
q[2] = A.rkey[k+2] ^ aes_rtable[int(p[2]&0xff)] ^ aes_ROTL8(aes_rtable[int((p[1]>>8)&0xff)]) ^ aes_ROTL16(aes_rtable[int((p[0]>>16)&0xff)]) ^ aes_ROTL24(aes_rtable[int((p[3]>>24)&0xff)])
q[3] = A.rkey[k+3] ^ aes_rtable[int(p[3]&0xff)] ^ aes_ROTL8(aes_rtable[int((p[2]>>8)&0xff)]) ^ aes_ROTL16(aes_rtable[int((p[1]>>16)&0xff)]) ^ aes_ROTL24(aes_rtable[int((p[0]>>24)&0xff)])
k += 4
for j := 0; j < 4; j++ {
t := p[j]
p[j] = q[j]
q[j] = t
}
}
/* Last Round */
q[0] = A.rkey[k] ^ uint32(aes_rbsub[int(p[0]&0xff)]) ^ aes_ROTL8(uint32(aes_rbsub[int((p[3]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_rbsub[int((p[2]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_rbsub[int((p[1]>>24)&0xff)]))
q[1] = A.rkey[k+1] ^ uint32(aes_rbsub[int(p[1]&0xff)]) ^ aes_ROTL8(uint32(aes_rbsub[int((p[0]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_rbsub[int((p[3]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_rbsub[int((p[2]>>24)&0xff)]))
q[2] = A.rkey[k+2] ^ uint32(aes_rbsub[int(p[2]&0xff)]) ^ aes_ROTL8(uint32(aes_rbsub[int((p[1]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_rbsub[int((p[0]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_rbsub[int((p[3]>>24)&0xff)]))
q[3] = A.rkey[k+3] ^ uint32(aes_rbsub[int((p[3])&0xff)]) ^ aes_ROTL8(uint32(aes_rbsub[int((p[2]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_rbsub[int((p[1]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_rbsub[int((p[0]>>24)&0xff)]))
j = 0
for i := 0; i < 4; i++ {
b = aes_unpack(q[i])
for k := 0; k < 4; k++ {
buff[j+k] = b[k]
}
j += 4
}
}
/* Encrypt using selected mode of operation */
func (A *AES) Encrypt(buff []byte) uint32 {
var st [16]byte
// Supported Modes of Operation
var fell_off uint32 = 0
switch A.mode {
case AES_ECB:
A.ecb_encrypt(buff)
return 0
case AES_CBC:
for j := 0; j < 16; j++ {
buff[j] ^= A.f[j]
}
A.ecb_encrypt(buff)
for j := 0; j < 16; j++ {
A.f[j] = buff[j]
}
return 0
case AES_CFB1:
fallthrough
case AES_CFB2:
fallthrough
case AES_CFB4:
bytes := A.mode - AES_CFB1 + 1
for j := 0; j < bytes; j++ {
fell_off = (fell_off << 8) | uint32(A.f[j])
}
for j := 0; j < 16; j++ {
st[j] = A.f[j]
}
for j := bytes; j < 16; j++ {
A.f[j-bytes] = A.f[j]
}
A.ecb_encrypt(st[:])
for j := 0; j < bytes; j++ {
buff[j] ^= st[j]
A.f[16-bytes+j] = buff[j]
}
return fell_off
case AES_OFB1:
fallthrough
case AES_OFB2:
fallthrough
case AES_OFB4:
fallthrough
case AES_OFB8:
fallthrough
case AES_OFB16:
bytes := A.mode - AES_OFB1 + 1
A.ecb_encrypt(A.f[:])
for j := 0; j < bytes; j++ {
buff[j] ^= A.f[j]
}
return 0
case AES_CTR1:
fallthrough
case AES_CTR2:
fallthrough
case AES_CTR4:
fallthrough
case AES_CTR8:
fallthrough
case AES_CTR16:
bytes := A.mode - AES_CTR1 + 1
for j := 0; j < 16; j++ {
st[j] = A.f[j]
}
A.ecb_encrypt(st[:])
for j := 0; j < bytes; j++ {
buff[j] ^= st[j]
}
aes_increment(A.f[:])
return 0
default:
return 0
}
}
/* Decrypt using selected mode of operation */
func (A *AES) Decrypt(buff []byte) uint32 {
var st [16]byte
// Supported Modes of Operation
var fell_off uint32 = 0
switch A.mode {
case AES_ECB:
A.ecb_decrypt(buff)
return 0
case AES_CBC:
for j := 0; j < 16; j++ {
st[j] = A.f[j]
A.f[j] = buff[j]
}
A.ecb_decrypt(buff)
for j := 0; j < 16; j++ {
buff[j] ^= st[j]
st[j] = 0
}
return 0
case AES_CFB1:
fallthrough
case AES_CFB2:
fallthrough
case AES_CFB4:
bytes := A.mode - AES_CFB1 + 1
for j := 0; j < bytes; j++ {
fell_off = (fell_off << 8) | uint32(A.f[j])
}
for j := 0; j < 16; j++ {
st[j] = A.f[j]
}
for j := bytes; j < 16; j++ {
A.f[j-bytes] = A.f[j]
}
A.ecb_encrypt(st[:])
for j := 0; j < bytes; j++ {
A.f[16-bytes+j] = buff[j]
buff[j] ^= st[j]
}
return fell_off
case AES_OFB1:
fallthrough
case AES_OFB2:
fallthrough
case AES_OFB4:
fallthrough
case AES_OFB8:
fallthrough
case AES_OFB16:
bytes := A.mode - AES_OFB1 + 1
A.ecb_encrypt(A.f[:])
for j := 0; j < bytes; j++ {
buff[j] ^= A.f[j]
}
return 0
case AES_CTR1:
fallthrough
case AES_CTR2:
fallthrough
case AES_CTR4:
fallthrough
case AES_CTR8:
fallthrough
case AES_CTR16:
bytes := A.mode - AES_CTR1 + 1
for j := 0; j < 16; j++ {
st[j] = A.f[j]
}
A.ecb_encrypt(st[:])
for j := 0; j < bytes; j++ {
buff[j] ^= st[j]
}
aes_increment(A.f[:])
return 0
default:
return 0
}
}
/* Clean up and delete left-overs */
func (A *AES) End() { // clean up
for i := 0; i < 4*(A.Nr+1); i++ {
A.fkey[i] = 0
A.rkey[i] = 0
}
for i := 0; i < 16; i++ {
A.f[i] = 0
}
}
/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
func AES_CBC_IV0_ENCRYPT(K []byte, M []byte) []byte { /* AES CBC encryption, with Null IV and key K */
/* Input is from an octet string M, output is to an octet string C */
/* Input is padded as necessary to make up a full final block */
a := NewAES()
fin := false
var buff [16]byte
var C []byte
a.Init(AES_CBC, len(K), K, nil)
ipt := 0 //opt:=0
var i int
for true {
for i = 0; i < 16; i++ {
if ipt < len(M) {
buff[i] = M[ipt]
ipt++
} else {
fin = true
break
}
}
if fin {
break
}
a.Encrypt(buff[:])
for i = 0; i < 16; i++ {
C = append(C, buff[i])
}
}
/* last block, filled up to i-th index */
padlen := 16 - i
for j := i; j < 16; j++ {
buff[j] = byte(padlen)
}
a.Encrypt(buff[:])
for i = 0; i < 16; i++ {
C = append(C, buff[i])
}
a.End()
return C
}
/* returns plaintext if all consistent, else returns null string */
func AES_CBC_IV0_DECRYPT(K []byte, C []byte) []byte { /* padding is removed */
a := NewAES()
var buff [16]byte
var MM []byte
var M []byte
var i int
ipt := 0
opt := 0
a.Init(AES_CBC, len(K), K, nil)
if len(C) == 0 {
return nil
}
ch := C[ipt]
ipt++
fin := false
for true {
for i = 0; i < 16; i++ {
buff[i] = ch
if ipt >= len(C) {
fin = true
break
} else {
ch = C[ipt]
ipt++
}
}
a.Decrypt(buff[:])
if fin {
break
}
for i = 0; i < 16; i++ {
MM = append(MM, buff[i])
opt++
}
}
a.End()
bad := false
padlen := int(buff[15])
if i != 15 || padlen < 1 || padlen > 16 {
bad = true
}
if padlen >= 2 && padlen <= 16 {
for i = 16 - padlen; i < 16; i++ {
if buff[i] != byte(padlen) {
bad = true
}
}
}
if !bad {
for i = 0; i < 16-padlen; i++ {
MM = append(MM, buff[i])
opt++
}
}
if bad {
return nil
}
for i = 0; i < opt; i++ {
M = append(M, MM[i])
}
return M
}
/*
func main() {
var key [32]byte
var block [16]byte
var iv [16]byte
for i:=0;i<32;i++ {key[i]=0}
key[0]=1
for i:=0;i<16;i++ {iv[i]=byte(i)}
for i:=0;i<16;i++ {block[i]=byte(i)}
a:=NewAES()
a.Init(AES_CTR16,32,key[:],iv[:])
fmt.Printf("Plain= \n")
for i:=0;i<16;i++ {fmt.Printf("%02X ", block[i]&0xff)}
fmt.Printf("\n")
a.Encrypt(block[:])
fmt.Printf("Encrypt= \n")
for i:=0;i<16;i++ {fmt.Printf("%02X ", block[i]&0xff)}
fmt.Printf("\n")
a.Reset(AES_CTR16,iv[:])
a.Decrypt(block[:])
fmt.Printf("Decrypt= \n")
for i:=0;i<16;i++ {fmt.Printf("%02X ", block[i]&0xff)}
fmt.Printf("\n")
a.End();
}
*/

File diff suppressed because it is too large Load Diff

457
ec/bls48581/core/GCM.go Normal file
View File

@ -0,0 +1,457 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/*
* Implementation of the AES-GCM Encryption/Authentication
*
* Some restrictions..
* 1. Only for use with AES
* 2. Returned tag is always 128-bits. Truncate at your own risk.
* 3. The order of function calls must follow some rules
*
* Typical sequence of calls..
* 1. call GCM_init
* 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
* 3. call GCM_add_header one last time with any length of header
* 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
* 5. call GCM_add_cipher one last time with any length of cipher/plaintext
* 6. call GCM_finish to extract the tag.
*
* See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
*/
package core
import (
// "fmt"
"strconv"
)
const gcm_NB int = 4
const GCM_ACCEPTING_HEADER int = 0
const GCM_ACCEPTING_CIPHER int = 1
const GCM_NOT_ACCEPTING_MORE int = 2
const GCM_FINISHED int = 3
const GCM_ENCRYPTING int = 0
const GCM_DECRYPTING int = 1
type GCM struct {
table [128][4]uint32 /* 2k bytes */
stateX [16]byte
Y_0 [16]byte
counter int
lenA [2]uint32
lenC [2]uint32
status int
a *AES
}
func gcm_pack(b [4]byte) uint32 { /* pack bytes into a 32-bit Word */
return ((uint32(b[0]) & 0xff) << 24) | ((uint32(b[1]) & 0xff) << 16) | ((uint32(b[2]) & 0xff) << 8) | (uint32(b[3]) & 0xff)
}
func gcm_unpack(a uint32) [4]byte { /* unpack bytes from a word */
var b = [4]byte{byte((a >> 24) & 0xff), byte((a >> 16) & 0xff), byte((a >> 8) & 0xff), byte(a & 0xff)}
return b
}
func (G *GCM) precompute(H []byte) {
var b [4]byte
j := 0
for i := 0; i < gcm_NB; i++ {
b[0] = H[j]
b[1] = H[j+1]
b[2] = H[j+2]
b[3] = H[j+3]
G.table[0][i] = gcm_pack(b)
j += 4
}
for i := 1; i < 128; i++ {
c := uint32(0)
for j := 0; j < gcm_NB; j++ {
G.table[i][j] = c | (G.table[i-1][j])>>1
c = G.table[i-1][j] << 31
}
if c != 0 {
G.table[i][0] ^= 0xE1000000
} /* irreducible polynomial */
}
}
func (G *GCM) gf2mul() { /* gf2m mul - Z=H*X mod 2^128 */
var P [4]uint32
for i := 0; i < 4; i++ {
P[i] = 0
}
j := uint(8)
m := 0
for i := 0; i < 128; i++ {
j--
c := uint32((G.stateX[m] >> j) & 1)
c = ^c + 1
for k := 0; k < gcm_NB; k++ {
P[k] ^= (G.table[i][k] & c)
}
if j == 0 {
j = 8
m++
if m == 16 {
break
}
}
}
j = 0
for i := 0; i < gcm_NB; i++ {
b := gcm_unpack(P[i])
G.stateX[j] = b[0]
G.stateX[j+1] = b[1]
G.stateX[j+2] = b[2]
G.stateX[j+3] = b[3]
j += 4
}
}
func (G *GCM) wrap() { /* Finish off GHASH */
var F [4]uint32
var L [16]byte
/* convert lengths from bytes to bits */
F[0] = (G.lenA[0] << 3) | (G.lenA[1]&0xE0000000)>>29
F[1] = G.lenA[1] << 3
F[2] = (G.lenC[0] << 3) | (G.lenC[1]&0xE0000000)>>29
F[3] = G.lenC[1] << 3
j := 0
for i := 0; i < gcm_NB; i++ {
b := gcm_unpack(F[i])
L[j] = b[0]
L[j+1] = b[1]
L[j+2] = b[2]
L[j+3] = b[3]
j += 4
}
for i := 0; i < 16; i++ {
G.stateX[i] ^= L[i]
}
G.gf2mul()
}
func (G *GCM) ghash(plain []byte, len int) bool {
if G.status == GCM_ACCEPTING_HEADER {
G.status = GCM_ACCEPTING_CIPHER
}
if G.status != GCM_ACCEPTING_CIPHER {
return false
}
j := 0
for j < len {
for i := 0; i < 16 && j < len; i++ {
G.stateX[i] ^= plain[j]
j++
G.lenC[1]++
if G.lenC[1] == 0 {
G.lenC[0]++
}
}
G.gf2mul()
}
if len%16 != 0 {
G.status = GCM_NOT_ACCEPTING_MORE
}
return true
}
/* Initialize GCM mode */
func (G *GCM) Init(nk int, key []byte, niv int, iv []byte) { /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
var H [16]byte
for i := 0; i < 16; i++ {
H[i] = 0
G.stateX[i] = 0
}
G.a = new(AES)
G.a.Init(AES_ECB, nk, key, iv)
G.a.ecb_encrypt(H[:]) /* E(K,0) */
G.precompute(H[:])
G.lenA[0] = 0
G.lenC[0] = 0
G.lenA[1] = 0
G.lenC[1] = 0
if niv == 12 {
for i := 0; i < 12; i++ {
G.a.f[i] = iv[i]
}
b := gcm_unpack(uint32(1))
G.a.f[12] = b[0]
G.a.f[13] = b[1]
G.a.f[14] = b[2]
G.a.f[15] = b[3] /* initialise IV */
for i := 0; i < 16; i++ {
G.Y_0[i] = G.a.f[i]
}
} else {
G.status = GCM_ACCEPTING_CIPHER
G.ghash(iv, niv) /* GHASH(H,0,IV) */
G.wrap()
for i := 0; i < 16; i++ {
G.a.f[i] = G.stateX[i]
G.Y_0[i] = G.a.f[i]
G.stateX[i] = 0
}
G.lenA[0] = 0
G.lenC[0] = 0
G.lenA[1] = 0
G.lenC[1] = 0
}
G.status = GCM_ACCEPTING_HEADER
}
/* Add Header data - included but not encrypted */
func (G *GCM) Add_header(header []byte, len int) bool { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
if G.status != GCM_ACCEPTING_HEADER {
return false
}
j := 0
for j < len {
for i := 0; i < 16 && j < len; i++ {
G.stateX[i] ^= header[j]
j++
G.lenA[1]++
if G.lenA[1] == 0 {
G.lenA[0]++
}
}
G.gf2mul()
}
if len%16 != 0 {
G.status = GCM_ACCEPTING_CIPHER
}
return true
}
/* Add Plaintext - included and encrypted */
func (G *GCM) Add_plain(plain []byte, len int) []byte {
var B [16]byte
var b [4]byte
cipher := make([]byte, len)
var counter uint32 = 0
if G.status == GCM_ACCEPTING_HEADER {
G.status = GCM_ACCEPTING_CIPHER
}
if G.status != GCM_ACCEPTING_CIPHER {
return nil
}
j := 0
for j < len {
b[0] = G.a.f[12]
b[1] = G.a.f[13]
b[2] = G.a.f[14]
b[3] = G.a.f[15]
counter = gcm_pack(b)
counter++
b = gcm_unpack(counter)
G.a.f[12] = b[0]
G.a.f[13] = b[1]
G.a.f[14] = b[2]
G.a.f[15] = b[3] /* increment counter */
for i := 0; i < 16; i++ {
B[i] = G.a.f[i]
}
G.a.ecb_encrypt(B[:]) /* encrypt it */
for i := 0; i < 16 && j < len; i++ {
cipher[j] = (plain[j] ^ B[i])
G.stateX[i] ^= cipher[j]
j++
G.lenC[1]++
if G.lenC[1] == 0 {
G.lenC[0]++
}
}
G.gf2mul()
}
if len%16 != 0 {
G.status = GCM_NOT_ACCEPTING_MORE
}
return cipher
}
/* Add Ciphertext - decrypts to plaintext */
func (G *GCM) Add_cipher(cipher []byte, len int) []byte {
var B [16]byte
var b [4]byte
plain := make([]byte, len)
var counter uint32 = 0
if G.status == GCM_ACCEPTING_HEADER {
G.status = GCM_ACCEPTING_CIPHER
}
if G.status != GCM_ACCEPTING_CIPHER {
return nil
}
j := 0
for j < len {
b[0] = G.a.f[12]
b[1] = G.a.f[13]
b[2] = G.a.f[14]
b[3] = G.a.f[15]
counter = gcm_pack(b)
counter++
b = gcm_unpack(counter)
G.a.f[12] = b[0]
G.a.f[13] = b[1]
G.a.f[14] = b[2]
G.a.f[15] = b[3] /* increment counter */
for i := 0; i < 16; i++ {
B[i] = G.a.f[i]
}
G.a.ecb_encrypt(B[:]) /* encrypt it */
for i := 0; i < 16 && j < len; i++ {
oc := cipher[j]
plain[j] = (cipher[j] ^ B[i])
G.stateX[i] ^= oc
j++
G.lenC[1]++
if G.lenC[1] == 0 {
G.lenC[0]++
}
}
G.gf2mul()
}
if len%16 != 0 {
G.status = GCM_NOT_ACCEPTING_MORE
}
return plain
}
/* Finish and extract Tag */
func (G *GCM) Finish(extract bool) []byte { /* Finish off GHASH and extract tag (MAC) */
var tag []byte
G.wrap()
/* extract tag */
if extract {
G.a.ecb_encrypt(G.Y_0[:]) /* E(K,Y0) */
for i := 0; i < 16; i++ {
G.Y_0[i] ^= G.stateX[i]
}
for i := 0; i < 16; i++ {
tag = append(tag, G.Y_0[i])
G.Y_0[i] = 0
G.stateX[i] = 0
}
}
G.status = GCM_FINISHED
G.a.End()
return tag
}
func hex2bytes(s string) []byte {
lgh := len(s)
data := make([]byte, lgh/2)
for i := 0; i < lgh; i += 2 {
a, _ := strconv.ParseInt(s[i:i+2], 16, 32)
data[i/2] = byte(a)
}
return data
}
func GCM_ENCRYPT(K []byte, IV []byte, H []byte, P []byte) ([]byte, []byte) {
g := new(GCM)
g.Init(len(K), K, len(IV), IV)
g.Add_header(H, len(H))
C := g.Add_plain(P, len(P))
T := g.Finish(true)
return C, T
}
func GCM_DECRYPT(K []byte, IV []byte, H []byte, C []byte) ([]byte, []byte) {
g := new(GCM)
g.Init(len(K), K, len(IV), IV)
g.Add_header(H, len(H))
P := g.Add_cipher(C, len(C))
T := g.Finish(true)
return P, T
}
/*
func main() {
KT:="feffe9928665731c6d6a8f9467308308"
MT:="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"
HT:="feedfacedeadbeeffeedfacedeadbeefabaddad2"
NT:="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
// Tag should be 619cc5aefffe0bfa462af43c1699d050
g:=new(GCM)
M:=hex2bytes(MT)
H:=hex2bytes(HT)
N:=hex2bytes(NT)
K:=hex2bytes(KT)
lenM:=len(M)
lenH:=len(H)
lenK:=len(K)
lenIV:=len(N)
fmt.Printf("Plaintext=\n");
for i:=0;i<lenM;i++ {fmt.Printf("%02x",M[i])}
fmt.Printf("\n")
g.Init(lenK,K,lenIV,N)
g.Add_header(H,lenH)
C:=g.Add_plain(M,lenM)
T:=g.Finish(true)
fmt.Printf("Ciphertext=\n")
for i:=0;i<lenM;i++ {fmt.Printf("%02x",C[i])}
fmt.Printf("\n")
fmt.Printf("Tag=\n")
for i:=0;i<16;i++ {fmt.Printf("%02x",T[i])}
fmt.Printf("\n")
g.Init(lenK,K,lenIV,N)
g.Add_header(H,lenH)
P:=g.Add_cipher(C,lenM)
T=g.Finish(true)
fmt.Printf("Plaintext=\n");
for i:=0;i<lenM;i++ {fmt.Printf("%02x",P[i])}
fmt.Printf("\n")
fmt.Printf("Tag=\n");
for i:=0;i<16;i++ {fmt.Printf("%02x",T[i])}
fmt.Printf("\n")
}
*/

233
ec/bls48581/core/HASH256.go Normal file
View File

@ -0,0 +1,233 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/*
* Implementation of the Secure Hashing Algorithm (SHA-256)
*
* Generates a 256 bit message digest. It should be impossible to come
* come up with two messages that hash to the same value ("collision free").
*
* For use with byte-oriented messages only.
*/
package core
//import "fmt"
const SHA256 int = 32
const hash256_H0 uint32 = 0x6A09E667
const hash256_H1 uint32 = 0xBB67AE85
const hash256_H2 uint32 = 0x3C6EF372
const hash256_H3 uint32 = 0xA54FF53A
const hash256_H4 uint32 = 0x510E527F
const hash256_H5 uint32 = 0x9B05688C
const hash256_H6 uint32 = 0x1F83D9AB
const hash256_H7 uint32 = 0x5BE0CD19
var hash256_K = [...]uint32{
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}
type HASH256 struct {
length [2]uint32
h [8]uint32
w [64]uint32
}
/* functions */
func hash256_S(n uint32, x uint32) uint32 {
return (((x) >> n) | ((x) << (32 - n)))
}
func hash256_R(n uint32, x uint32) uint32 {
return ((x) >> n)
}
func hash256_Ch(x, y, z uint32) uint32 {
return ((x & y) ^ (^(x) & z))
}
func hash256_Maj(x, y, z uint32) uint32 {
return ((x & y) ^ (x & z) ^ (y & z))
}
func hash256_Sig0(x uint32) uint32 {
return (hash256_S(2, x) ^ hash256_S(13, x) ^ hash256_S(22, x))
}
func hash256_Sig1(x uint32) uint32 {
return (hash256_S(6, x) ^ hash256_S(11, x) ^ hash256_S(25, x))
}
func hash256_theta0(x uint32) uint32 {
return (hash256_S(7, x) ^ hash256_S(18, x) ^ hash256_R(3, x))
}
func hash256_theta1(x uint32) uint32 {
return (hash256_S(17, x) ^ hash256_S(19, x) ^ hash256_R(10, x))
}
func (H *HASH256) transform() { /* basic transformation step */
for j := 16; j < 64; j++ {
H.w[j] = hash256_theta1(H.w[j-2]) + H.w[j-7] + hash256_theta0(H.w[j-15]) + H.w[j-16]
}
a := H.h[0]
b := H.h[1]
c := H.h[2]
d := H.h[3]
e := H.h[4]
f := H.h[5]
g := H.h[6]
hh := H.h[7]
for j := 0; j < 64; j++ { /* 64 times - mush it up */
t1 := hh + hash256_Sig1(e) + hash256_Ch(e, f, g) + hash256_K[j] + H.w[j]
t2 := hash256_Sig0(a) + hash256_Maj(a, b, c)
hh = g
g = f
f = e
e = d + t1
d = c
c = b
b = a
a = t1 + t2
}
H.h[0] += a
H.h[1] += b
H.h[2] += c
H.h[3] += d
H.h[4] += e
H.h[5] += f
H.h[6] += g
H.h[7] += hh
}
/* Initialise Hash function */
func (H *HASH256) Init() { /* initialise */
for i := 0; i < 64; i++ {
H.w[i] = 0
}
H.length[0] = 0
H.length[1] = 0
H.h[0] = hash256_H0
H.h[1] = hash256_H1
H.h[2] = hash256_H2
H.h[3] = hash256_H3
H.h[4] = hash256_H4
H.h[5] = hash256_H5
H.h[6] = hash256_H6
H.h[7] = hash256_H7
}
func NewHASH256() *HASH256 {
H := new(HASH256)
H.Init()
return H
}
func NewHASH256copy(HC *HASH256) *HASH256 {
H := new(HASH256)
for i := 0; i < 64; i++ {
H.w[i] = HC.w[i]
}
for i := 0; i < 8; i++ {
H.h[i] = HC.h[i]
}
H.length[0] = HC.length[0]
H.length[1] = HC.length[1]
return H
}
/* process a single byte */
func (H *HASH256) Process(byt byte) { /* process the next message byte */
cnt := (H.length[0] / 32) % 16
H.w[cnt] <<= 8
H.w[cnt] |= uint32(byt & 0xFF)
H.length[0] += 8
if H.length[0] == 0 {
H.length[1]++
H.length[0] = 0
}
if (H.length[0] % 512) == 0 {
H.transform()
}
}
/* process an array of bytes */
func (H *HASH256) Process_array(b []byte) {
for i := 0; i < len(b); i++ {
H.Process((b[i]))
}
}
/* process a 32-bit integer */
func (H *HASH256) Process_num(n int32) {
H.Process(byte((n >> 24) & 0xff))
H.Process(byte((n >> 16) & 0xff))
H.Process(byte((n >> 8) & 0xff))
H.Process(byte(n & 0xff))
}
/* Generate 32-byte Hash */
func (H *HASH256) Hash() []byte { /* pad message and finish - supply digest */
var digest [32]byte
len0 := H.length[0]
len1 := H.length[1]
H.Process(0x80)
for (H.length[0] % 512) != 448 {
H.Process(0)
}
H.w[14] = len1
H.w[15] = len0
H.transform()
for i := 0; i < 32; i++ { /* convert to bytes */
digest[i] = byte((H.h[i/4] >> uint(8*(3-i%4))) & 0xff)
}
H.Init()
return digest[0:32]
}
func (H *HASH256) Continuing_Hash() []byte {
sh := NewHASH256copy(H)
return sh.Hash()
}
/* test program: should produce digest */
//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
/*
func main() {
test := []byte("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
sh:=NewHASH256()
for i:=0;i<len(test);i++ {
sh.Process(test[i])
}
digest:=sh.Hash()
for i:=0;i<32;i++ {fmt.Printf("%02x",digest[i])}
} */

247
ec/bls48581/core/HASH384.go Normal file
View File

@ -0,0 +1,247 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/*
* Implementation of the Secure Hashing Algorithm (SHA-384)
*
* Generates a 384 bit message digest. It should be impossible to come
* come up with two messages that hash to the same value ("collision free").
*
* For use with byte-oriented messages only.
*/
package core
//import "fmt"
const SHA384 int = 48
const hash384_H0 uint64 = 0xcbbb9d5dc1059ed8
const hash384_H1 uint64 = 0x629a292a367cd507
const hash384_H2 uint64 = 0x9159015a3070dd17
const hash384_H3 uint64 = 0x152fecd8f70e5939
const hash384_H4 uint64 = 0x67332667ffc00b31
const hash384_H5 uint64 = 0x8eb44a8768581511
const hash384_H6 uint64 = 0xdb0c2e0d64f98fa7
const hash384_H7 uint64 = 0x47b5481dbefa4fa4
var hash384_K = [...]uint64{
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817}
type HASH384 struct {
length [2]uint64
h [8]uint64
w [80]uint64
}
/* functions */
func hash384_S(n uint64, x uint64) uint64 {
return (((x) >> n) | ((x) << (64 - n)))
}
func hash384_R(n uint64, x uint64) uint64 {
return ((x) >> n)
}
func hash384_Ch(x, y, z uint64) uint64 {
return ((x & y) ^ (^(x) & z))
}
func hash384_Maj(x, y, z uint64) uint64 {
return ((x & y) ^ (x & z) ^ (y & z))
}
func hash384_Sig0(x uint64) uint64 {
return (hash384_S(28, x) ^ hash384_S(34, x) ^ hash384_S(39, x))
}
func hash384_Sig1(x uint64) uint64 {
return (hash384_S(14, x) ^ hash384_S(18, x) ^ hash384_S(41, x))
}
func hash384_theta0(x uint64) uint64 {
return (hash384_S(1, x) ^ hash384_S(8, x) ^ hash384_R(7, x))
}
func hash384_theta1(x uint64) uint64 {
return (hash384_S(19, x) ^ hash384_S(61, x) ^ hash384_R(6, x))
}
func (H *HASH384) transform() { /* basic transformation step */
for j := 16; j < 80; j++ {
H.w[j] = hash384_theta1(H.w[j-2]) + H.w[j-7] + hash384_theta0(H.w[j-15]) + H.w[j-16]
}
a := H.h[0]
b := H.h[1]
c := H.h[2]
d := H.h[3]
e := H.h[4]
f := H.h[5]
g := H.h[6]
hh := H.h[7]
for j := 0; j < 80; j++ { /* 80 times - mush it up */
t1 := hh + hash384_Sig1(e) + hash384_Ch(e, f, g) + hash384_K[j] + H.w[j]
t2 := hash384_Sig0(a) + hash384_Maj(a, b, c)
hh = g
g = f
f = e
e = d + t1
d = c
c = b
b = a
a = t1 + t2
}
H.h[0] += a
H.h[1] += b
H.h[2] += c
H.h[3] += d
H.h[4] += e
H.h[5] += f
H.h[6] += g
H.h[7] += hh
}
/* Initialise Hash function */
func (H *HASH384) Init() { /* initialise */
for i := 0; i < 80; i++ {
H.w[i] = 0
}
H.length[0] = 0
H.length[1] = 0
H.h[0] = hash384_H0
H.h[1] = hash384_H1
H.h[2] = hash384_H2
H.h[3] = hash384_H3
H.h[4] = hash384_H4
H.h[5] = hash384_H5
H.h[6] = hash384_H6
H.h[7] = hash384_H7
}
func NewHASH384() *HASH384 {
H := new(HASH384)
H.Init()
return H
}
func NewHASH384copy(HC *HASH384) *HASH384 {
H := new(HASH384)
for i := 0; i < 80; i++ {
H.w[i] = HC.w[i]
}
for i := 0; i < 8; i++ {
H.h[i] = HC.h[i]
}
H.length[0] = HC.length[0]
H.length[1] = HC.length[1]
return H
}
/* process a single byte */
func (H *HASH384) Process(byt byte) { /* process the next message byte */
cnt := (H.length[0] / 64) % 16
H.w[cnt] <<= 8
H.w[cnt] |= uint64(byt & 0xFF)
H.length[0] += 8
if H.length[0] == 0 {
H.length[1]++
H.length[0] = 0
}
if (H.length[0] % 1024) == 0 {
H.transform()
}
}
/* process an array of bytes */
func (H *HASH384) Process_array(b []byte) {
for i := 0; i < len(b); i++ {
H.Process((b[i]))
}
}
/* process a 32-bit integer */
func (H *HASH384) Process_num(n int32) {
H.Process(byte((n >> 24) & 0xff))
H.Process(byte((n >> 16) & 0xff))
H.Process(byte((n >> 8) & 0xff))
H.Process(byte(n & 0xff))
}
/* Generate 32-byte Hash */
func (H *HASH384) Hash() []byte { /* pad message and finish - supply digest */
var digest [48]byte
len0 := H.length[0]
len1 := H.length[1]
H.Process(0x80)
for (H.length[0] % 1024) != 896 {
H.Process(0)
}
H.w[14] = len1
H.w[15] = len0
H.transform()
for i := 0; i < 48; i++ { /* convert to bytes */
digest[i] = byte((H.h[i/8] >> uint(8*(7-i%8))) & 0xff)
}
H.Init()
return digest[0:48]
}
func (H *HASH384) Continuing_Hash() []byte {
sh := NewHASH384copy(H)
return sh.Hash()
}
/* test program: should produce digest */
//09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712 fcc7c71a557e2db9 66c3e9fa91746039
/*
func main() {
test := []byte("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
sh:=NewHASH384()
for i:=0;i<len(test);i++ {
sh.Process(test[i])
}
digest:=sh.Hash()
for i:=0;i<48;i++ {fmt.Printf("%02x",digest[i])}
}
*/

247
ec/bls48581/core/HASH512.go Normal file
View File

@ -0,0 +1,247 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/*
* Implementation of the Secure Hashing Algorithm (SHA-384)
*
* Generates a 384 bit message digest. It should be impossible to come
* come up with two messages that hash to the same value ("collision free").
*
* For use with byte-oriented messages only.
*/
package core
//import "fmt"
const SHA512 int = 64
const hash512_H0 uint64 = 0x6a09e667f3bcc908
const hash512_H1 uint64 = 0xbb67ae8584caa73b
const hash512_H2 uint64 = 0x3c6ef372fe94f82b
const hash512_H3 uint64 = 0xa54ff53a5f1d36f1
const hash512_H4 uint64 = 0x510e527fade682d1
const hash512_H5 uint64 = 0x9b05688c2b3e6c1f
const hash512_H6 uint64 = 0x1f83d9abfb41bd6b
const hash512_H7 uint64 = 0x5be0cd19137e2179
var hash512_K = [...]uint64{
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817}
type HASH512 struct {
length [2]uint64
h [8]uint64
w [80]uint64
}
/* functions */
func hash512_S(n uint64, x uint64) uint64 {
return (((x) >> n) | ((x) << (64 - n)))
}
func hash512_R(n uint64, x uint64) uint64 {
return ((x) >> n)
}
func hash512_Ch(x, y, z uint64) uint64 {
return ((x & y) ^ (^(x) & z))
}
func hash512_Maj(x, y, z uint64) uint64 {
return ((x & y) ^ (x & z) ^ (y & z))
}
func hash512_Sig0(x uint64) uint64 {
return (hash512_S(28, x) ^ hash512_S(34, x) ^ hash512_S(39, x))
}
func hash512_Sig1(x uint64) uint64 {
return (hash512_S(14, x) ^ hash512_S(18, x) ^ hash512_S(41, x))
}
func hash512_theta0(x uint64) uint64 {
return (hash512_S(1, x) ^ hash512_S(8, x) ^ hash512_R(7, x))
}
func hash512_theta1(x uint64) uint64 {
return (hash512_S(19, x) ^ hash512_S(61, x) ^ hash512_R(6, x))
}
func (H *HASH512) transform() { /* basic transformation step */
for j := 16; j < 80; j++ {
H.w[j] = hash512_theta1(H.w[j-2]) + H.w[j-7] + hash512_theta0(H.w[j-15]) + H.w[j-16]
}
a := H.h[0]
b := H.h[1]
c := H.h[2]
d := H.h[3]
e := H.h[4]
f := H.h[5]
g := H.h[6]
hh := H.h[7]
for j := 0; j < 80; j++ { /* 80 times - mush it up */
t1 := hh + hash512_Sig1(e) + hash512_Ch(e, f, g) + hash512_K[j] + H.w[j]
t2 := hash512_Sig0(a) + hash512_Maj(a, b, c)
hh = g
g = f
f = e
e = d + t1
d = c
c = b
b = a
a = t1 + t2
}
H.h[0] += a
H.h[1] += b
H.h[2] += c
H.h[3] += d
H.h[4] += e
H.h[5] += f
H.h[6] += g
H.h[7] += hh
}
/* Initialise Hash function */
func (H *HASH512) Init() { /* initialise */
for i := 0; i < 80; i++ {
H.w[i] = 0
}
H.length[0] = 0
H.length[1] = 0
H.h[0] = hash512_H0
H.h[1] = hash512_H1
H.h[2] = hash512_H2
H.h[3] = hash512_H3
H.h[4] = hash512_H4
H.h[5] = hash512_H5
H.h[6] = hash512_H6
H.h[7] = hash512_H7
}
func NewHASH512() *HASH512 {
H := new(HASH512)
H.Init()
return H
}
func NewHASH512copy(HC *HASH512) *HASH512 {
H := new(HASH512)
for i := 0; i < 80; i++ {
H.w[i] = HC.w[i]
}
for i := 0; i < 8; i++ {
H.h[i] = HC.h[i]
}
H.length[0] = HC.length[0]
H.length[1] = HC.length[1]
return H
}
/* process a single byte */
func (H *HASH512) Process(byt byte) { /* process the next message byte */
cnt := (H.length[0] / 64) % 16
H.w[cnt] <<= 8
H.w[cnt] |= uint64(byt & 0xFF)
H.length[0] += 8
if H.length[0] == 0 {
H.length[1]++
H.length[0] = 0
}
if (H.length[0] % 1024) == 0 {
H.transform()
}
}
/* process an array of bytes */
func (H *HASH512) Process_array(b []byte) {
for i := 0; i < len(b); i++ {
H.Process((b[i]))
}
}
/* process a 32-bit integer */
func (H *HASH512) Process_num(n int32) {
H.Process(byte((n >> 24) & 0xff))
H.Process(byte((n >> 16) & 0xff))
H.Process(byte((n >> 8) & 0xff))
H.Process(byte(n & 0xff))
}
/* Generate 64-byte Hash */
func (H *HASH512) Hash() []byte { /* pad message and finish - supply digest */
var digest [64]byte
len0 := H.length[0]
len1 := H.length[1]
H.Process(0x80)
for (H.length[0] % 1024) != 896 {
H.Process(0)
}
H.w[14] = len1
H.w[15] = len0
H.transform()
for i := 0; i < 64; i++ { /* convert to bytes */
digest[i] = byte((H.h[i/8] >> uint(8*(7-i%8))) & 0xff)
}
H.Init()
return digest[0:64]
}
func (H *HASH512) Continuing_Hash() []byte {
sh := NewHASH512copy(H)
return sh.Hash()
}
/* test program: should produce digest */
//8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909
/*
func main() {
test := []byte("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
sh:=NewHASH512()
for i:=0;i<len(test);i++ {
sh.Process(test[i])
}
digest:=sh.Hash()
for i:=0;i<64;i++ {fmt.Printf("%02x",digest[i])}
}
*/

909
ec/bls48581/core/HMAC.go Normal file
View File

@ -0,0 +1,909 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/*
* Implementation of the Secure Hashing Algorithm (SHA-256)
*
* Generates a 256 bit message digest. It should be impossible to come
* come up with two messages that hash to the same value ("collision free").
*
* For use with byte-oriented messages only.
*/
package core
const MC_SHA2 int = 2
const MC_SHA3 int = 3
/* Convert Integer to n-byte array */
func InttoBytes(n int, len int) []byte {
var b []byte
var i int
for i = 0; i < len; i++ {
b = append(b, 0)
}
i = len
for n > 0 && i > 0 {
i--
b[i] = byte(n & 0xff)
n /= 256
}
return b
}
/* general purpose hashing of Byte array|integer|Byte array. Output of length olen, padded with leading zeros if required */
func GPhashit(hash int, hlen int, olen int, zpad int, A []byte, n int32, B []byte) []byte {
var R []byte
if hash == MC_SHA2 {
if hlen == SHA256 {
H := NewHASH256()
for i := 0; i < zpad; i++ {
H.Process(0)
}
if A != nil {
H.Process_array(A)
}
if n >= 0 {
H.Process_num(int32(n))
}
if B != nil {
H.Process_array(B)
}
R = H.Hash()
}
if hlen == SHA384 {
H := NewHASH384()
for i := 0; i < zpad; i++ {
H.Process(0)
}
if A != nil {
H.Process_array(A)
}
if n >= 0 {
H.Process_num(int32(n))
}
if B != nil {
H.Process_array(B)
}
R = H.Hash()
}
if hlen == SHA512 {
H := NewHASH512()
for i := 0; i < zpad; i++ {
H.Process(0)
}
if A != nil {
H.Process_array(A)
}
if n >= 0 {
H.Process_num(int32(n))
}
if B != nil {
H.Process_array(B)
}
R = H.Hash()
}
}
if hash == MC_SHA3 {
H := NewSHA3(hlen)
for i := 0; i < zpad; i++ {
H.Process(0)
}
if A != nil {
H.Process_array(A)
}
if n >= 0 {
H.Process_num(int32(n))
}
if B != nil {
H.Process_array(B)
}
R = H.Hash()
}
if R == nil {
return nil
}
if olen == 0 {
return R
}
var W []byte
for i := 0; i < olen; i++ {
W = append(W, 0)
}
if olen <= hlen {
for i := 0; i < olen; i++ {
W[i] = R[i]
}
} else {
for i := 0; i < hlen; i++ {
W[i+olen-hlen] = R[i]
}
for i := 0; i < olen-hlen; i++ {
W[i] = 0
}
}
return W
}
/* Simple hashing of byte array */
func SPhashit(hash int, hlen int, A []byte) []byte {
return GPhashit(hash, hlen, 0, 0, A, -1, nil)
}
/* Key Derivation Function */
/* Input octet Z */
/* Output key of length olen */
func KDF2(hash int, sha int, Z []byte, P []byte, olen int) []byte {
/* NOTE: the parameter olen is the length of the output k in bytes */
hlen := sha
var K []byte
k := 0
for i := 0; i < olen; i++ {
K = append(K, 0)
}
cthreshold := olen / hlen
if olen%hlen != 0 {
cthreshold++
}
for counter := 1; counter <= cthreshold; counter++ {
B := GPhashit(hash, sha, 0, 0, Z, int32(counter), P)
if k+hlen > olen {
for i := 0; i < olen%hlen; i++ {
K[k] = B[i]
k++
}
} else {
for i := 0; i < hlen; i++ {
K[k] = B[i]
k++
}
}
}
return K
}
/* Password based Key Derivation Function */
/* Input password p, salt s, and repeat count */
/* Output key of length olen */
func PBKDF2(hash int, sha int, Pass []byte, Salt []byte, rep int, olen int) []byte {
d := olen / sha
if olen%sha != 0 {
d++
}
var F []byte
var U []byte
var S []byte
var K []byte
for i := 0; i < sha; i++ {
F = append(F, 0)
U = append(U, 0)
}
for i := 1; i <= d; i++ {
for j := 0; j < len(Salt); j++ {
S = append(S, Salt[j])
}
N := InttoBytes(i, 4)
for j := 0; j < 4; j++ {
S = append(S, N[j])
}
HMAC(MC_SHA2, sha, F[:], sha, S, Pass)
for j := 0; j < sha; j++ {
U[j] = F[j]
}
for j := 2; j <= rep; j++ {
HMAC(MC_SHA2, sha, U[:], sha, U[:], Pass)
for k := 0; k < sha; k++ {
F[k] ^= U[k]
}
}
for j := 0; j < sha; j++ {
K = append(K, F[j])
}
}
var key []byte
for i := 0; i < olen; i++ {
key = append(key, K[i])
}
return key
}
func blksize(hash int, sha int) int {
b := 0
if hash == MC_SHA2 {
b = 64
if sha > 32 {
b = 128
}
}
if hash == MC_SHA3 {
b = 200 - 2*sha
}
return b
}
/* Calculate HMAC of m using key k. HMAC is tag of length olen (which is length of tag) */
func HMAC(hash int, sha int, tag []byte, olen int, K []byte, M []byte) int {
/* Input is from an octet m *
* olen is requested output length in bytes. k is the key *
* The output is the calculated tag */
var B []byte
b := blksize(hash, sha)
if b == 0 {
return 0
}
var K0 [200]byte
//olen := len(tag)
for i := 0; i < b; i++ {
K0[i] = 0
}
if len(K) > b {
B = SPhashit(hash, sha, K)
for i := 0; i < sha; i++ {
K0[i] = B[i]
}
} else {
for i := 0; i < len(K); i++ {
K0[i] = K[i]
}
}
for i := 0; i < b; i++ {
K0[i] ^= 0x36
}
B = GPhashit(hash, sha, 0, 0, K0[0:b], -1, M)
for i := 0; i < b; i++ {
K0[i] ^= 0x6a
}
B = GPhashit(hash, sha, olen, 0, K0[0:b], -1, B)
for i := 0; i < olen; i++ {
tag[i] = B[i]
}
return 1
}
func HKDF_Extract(hash int, hlen int, SALT []byte, IKM []byte) []byte {
var PRK []byte
for i := 0; i < hlen; i++ {
PRK = append(PRK, 0)
}
if SALT == nil {
var H []byte
for i := 0; i < hlen; i++ {
H = append(H, 0)
}
HMAC(hash, hlen, PRK, hlen, H, IKM)
} else {
HMAC(hash, hlen, PRK, hlen, SALT, IKM)
}
return PRK
}
func HKDF_Expand(hash int, hlen int, olen int, PRK []byte, INFO []byte) []byte {
n := olen / hlen
flen := olen % hlen
var OKM []byte
var T []byte
var K [64]byte
for i := 1; i <= n; i++ {
for j := 0; j < len(INFO); j++ {
T = append(T, INFO[j])
}
T = append(T, byte(i))
HMAC(hash, hlen, K[:], hlen, PRK, T)
T = nil
for j := 0; j < hlen; j++ {
OKM = append(OKM, K[j])
T = append(T, K[j])
}
}
if flen > 0 {
for j := 0; j < len(INFO); j++ {
T = append(T, INFO[j])
}
T = append(T, byte(n+1))
HMAC(hash, hlen, K[:], flen, PRK, T)
for j := 0; j < flen; j++ {
OKM = append(OKM, K[j])
}
}
return OKM
}
func ceil(a int, b int) int {
return (((a)-1)/(b) + 1)
}
func XOF_Expand(hlen int, olen int, DST []byte, MSG []byte) []byte {
var OKM = make([]byte, olen)
H := NewSHA3(hlen)
for i := 0; i < len(MSG); i++ {
H.Process(MSG[i])
}
H.Process(byte((olen >> 8) & 0xff))
H.Process(byte(olen & 0xff))
for i := 0; i < len(DST); i++ {
H.Process(DST[i])
}
H.Process(byte(len(DST) & 0xff))
H.Shake(OKM[:], olen)
return OKM
}
func xmd_Expand_Short_DST(hash int, hlen int, olen int, DST []byte, MSG []byte) []byte {
var OKM = make([]byte, olen)
var TMP = make([]byte, len(DST)+4)
ell := ceil(olen, hlen)
blk := blksize(hash, hlen)
TMP[0] = byte((olen >> 8) & 0xff)
TMP[1] = byte(olen & 0xff)
TMP[2] = byte(0)
for j := 0; j < len(DST); j++ {
TMP[3+j] = DST[j]
}
TMP[3+len(DST)] = byte(len(DST) & 0xff)
var H0 = GPhashit(hash, hlen, 0, blk, MSG, -1, TMP)
var H1 = make([]byte, hlen)
var TMP2 = make([]byte, len(DST)+2)
k := 0
for i := 1; i <= ell; i++ {
for j := 0; j < hlen; j++ {
H1[j] ^= H0[j]
}
TMP2[0] = byte(i)
for j := 0; j < len(DST); j++ {
TMP2[1+j] = DST[j]
}
TMP2[1+len(DST)] = byte(len(DST) & 0xff)
H1 = GPhashit(hash, hlen, 0, 0, H1, -1, TMP2)
for j := 0; j < hlen && k < olen; j++ {
OKM[k] = H1[j]
k++
}
}
return OKM
}
func XMD_Expand(hash int, hlen int, olen int, DST []byte, MSG []byte) []byte {
var R []byte
OS := []byte("H2C-OVERSIZE-DST-")
if len(DST)>=256 {
W := GPhashit(hash, hlen, 0, 0, OS, -1, DST)
R=xmd_Expand_Short_DST(hash,hlen,olen,W,MSG)
} else {
R=xmd_Expand_Short_DST(hash,hlen,olen,DST,MSG)
}
return R;
}
/* Mask Generation Function */
func MGF1(sha int, Z []byte, olen int, K []byte) {
hlen := sha
var k int = 0
for i := 0; i < len(K); i++ {
K[i] = 0
}
cthreshold := olen / hlen
if olen%hlen != 0 {
cthreshold++
}
for counter := 0; counter < cthreshold; counter++ {
B := GPhashit(MC_SHA2, sha, 0, 0, Z, int32(counter), nil)
//B := hashit(sha, Z, counter)
if k+hlen > olen {
for i := 0; i < olen%hlen; i++ {
K[k] = B[i]
k++
}
} else {
for i := 0; i < hlen; i++ {
K[k] = B[i]
k++
}
}
}
}
func MGF1XOR(sha int, Z []byte, olen int, K []byte) {
hlen := sha
var k int = 0
cthreshold := olen / hlen
if olen%hlen != 0 {
cthreshold++
}
for counter := 0; counter < cthreshold; counter++ {
B := GPhashit(MC_SHA2, sha, 0, 0, Z, int32(counter), nil)
//B := hashit(sha, Z, counter)
if k+hlen > olen {
for i := 0; i < olen%hlen; i++ {
K[k] ^= B[i]
k++
}
} else {
for i := 0; i < hlen; i++ {
K[k] ^= B[i]
k++
}
}
}
}
/* SHAXXX identifier strings */
var SHA256ID = [...]byte{0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}
var SHA384ID = [...]byte{0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}
var SHA512ID = [...]byte{0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}
func RSA_PKCS15(sha int, m []byte, w []byte, RFS int) bool {
olen := RFS
hlen := sha
idlen := 19
if olen < idlen+hlen+10 {
return false
}
H := SPhashit(MC_SHA2, sha, m)
//H := hashit(sha, m, -1)
for i := 0; i < len(w); i++ {
w[i] = 0
}
i := 0
w[i] = 0
i++
w[i] = 1
i++
for j := 0; j < olen-idlen-hlen-3; j++ {
w[i] = 0xff
i++
}
w[i] = 0
i++
if hlen == SHA256 {
for j := 0; j < idlen; j++ {
w[i] = SHA256ID[j]
i++
}
}
if hlen == SHA384 {
for j := 0; j < idlen; j++ {
w[i] = SHA384ID[j]
i++
}
}
if hlen == SHA512 {
for j := 0; j < idlen; j++ {
w[i] = SHA512ID[j]
i++
}
}
for j := 0; j < hlen; j++ {
w[i] = H[j]
i++
}
return true
}
/* SHAXXX identifier strings */
var SHA256IDb = [...]byte{0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x04, 0x20}
var SHA384IDb = [...]byte{0x30, 0x3f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x04, 0x30}
var SHA512IDb = [...]byte{0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x04, 0x40}
func RSA_PKCS15b(sha int, m []byte, w []byte, RFS int) bool {
olen := RFS
hlen := sha
idlen := 17
if olen < idlen+hlen+10 {
return false
}
H := SPhashit(MC_SHA2,sha,m)
//H := hashit(sha, m, -1)
for i := 0; i < len(w); i++ {
w[i] = 0
}
i := 0
w[i] = 0
i++
w[i] = 1
i++
for j := 0; j < olen-idlen-hlen-3; j++ {
w[i] = 0xff
i++
}
w[i] = 0
i++
if hlen == SHA256 {
for j := 0; j < idlen; j++ {
w[i] = SHA256IDb[j]
i++
}
}
if hlen == SHA384 {
for j := 0; j < idlen; j++ {
w[i] = SHA384IDb[j]
i++
}
}
if hlen == SHA512 {
for j := 0; j < idlen; j++ {
w[i] = SHA512IDb[j]
i++
}
}
for j := 0; j < hlen; j++ {
w[i] = H[j]
i++
}
return true
}
func RSA_PSS_ENCODE(sha int, m []byte, rng *RAND, RFS int) []byte {
emlen := RFS
embits := 8*emlen - 1
hlen := sha
SALT := make([]byte, hlen)
for i := 0; i < hlen; i++ {
SALT[i] = rng.GetByte()
}
mask := byte(0xff >> (8*emlen - embits))
H := SPhashit(MC_SHA2, sha, m)
if emlen < hlen+hlen+2 {
return nil
}
MD := make([]byte, 8+hlen+hlen)
for i := 0; i < 8; i++ {
MD[i] = 0
}
for i := 0; i < hlen; i++ {
MD[8+i] = H[i]
}
for i := 0; i < hlen; i++ {
MD[8+hlen+i] = SALT[i]
}
H = SPhashit(MC_SHA2, sha, MD)
f := make([]byte, RFS)
for i := 0; i < emlen-hlen-hlen-2; i++ {
f[i] = 0
}
f[emlen-hlen-hlen-2] = 0x1
for i := 0; i < hlen; i++ {
f[emlen+i-hlen-hlen-1] = SALT[i]
}
MGF1XOR(sha, H, emlen-hlen-1, f)
f[0] &= mask
for i := 0; i < hlen; i++ {
f[emlen+i-hlen-1] = H[i]
}
f[emlen-1] = byte(0xbc)
return f
}
func RSA_PSS_VERIFY(sha int, m []byte, f []byte) bool {
emlen := len(f)
embits := 8*emlen - 1
hlen := sha
SALT := make([]byte, hlen)
mask := byte(0xff >> (8*emlen - embits))
HMASK := SPhashit(MC_SHA2, sha, m)
if emlen < hlen+hlen+2 {
return false
}
if f[emlen-1] != byte(0xbc) {
return false
}
if (f[0] & (^mask)) != 0 {
return false
}
DB := make([]byte, emlen-hlen-1)
for i := 0; i < emlen-hlen-1; i++ {
DB[i] = f[i]
}
H := make([]byte, hlen)
for i := 0; i < hlen; i++ {
H[i] = f[emlen+i-hlen-1]
}
MGF1XOR(sha, H, emlen-hlen-1, DB)
DB[0] &= mask
k := byte(0)
for i := 0; i < emlen-hlen-hlen-2; i++ {
k |= DB[i]
}
if k != 0 {
return false
}
if DB[emlen-hlen-hlen-2] != 0x01 {
return false
}
for i := 0; i < hlen; i++ {
SALT[i] = DB[emlen+i-hlen-hlen-1]
}
MD := make([]byte, 8+hlen+hlen)
for i := 0; i < 8; i++ {
MD[i] = 0
}
for i := 0; i < hlen; i++ {
MD[8+i] = HMASK[i]
}
for i := 0; i < hlen; i++ {
MD[8+hlen+i] = SALT[i]
}
HMASK = SPhashit(MC_SHA2, sha, MD)
k = 0
for i := 0; i < hlen; i++ {
k |= (H[i] - HMASK[i])
}
if k != 0 {
return false
}
return true
}
/* OAEP Message Encoding for Encryption */
func RSA_OAEP_ENCODE(sha int, m []byte, rng *RAND, p []byte, RFS int) []byte {
olen := RFS - 1
mlen := len(m)
//var f [RFS]byte
f := make([]byte, RFS)
hlen := sha
SEED := make([]byte, hlen)
seedlen := hlen
if mlen > olen-hlen-seedlen-1 {
return nil
}
DBMASK := make([]byte, olen-seedlen)
h := SPhashit(MC_SHA2, sha, p)
//h := hashit(sha, p, -1)
for i := 0; i < hlen; i++ {
f[i] = h[i]
}
slen := olen - mlen - hlen - seedlen - 1
for i := 0; i < slen; i++ {
f[hlen+i] = 0
}
f[hlen+slen] = 1
for i := 0; i < mlen; i++ {
f[hlen+slen+1+i] = m[i]
}
for i := 0; i < seedlen; i++ {
SEED[i] = rng.GetByte()
}
MGF1(sha, SEED, olen-seedlen, DBMASK)
for i := 0; i < olen-seedlen; i++ {
DBMASK[i] ^= f[i]
}
MGF1(sha, DBMASK, seedlen, f[:])
for i := 0; i < seedlen; i++ {
f[i] ^= SEED[i]
}
for i := 0; i < olen-seedlen; i++ {
f[i+seedlen] = DBMASK[i]
}
/* pad to length RFS */
d := 1
for i := RFS - 1; i >= d; i-- {
f[i] = f[i-d]
}
for i := d - 1; i >= 0; i-- {
f[i] = 0
}
return f[:]
}
/* OAEP Message Decoding for Decryption */
func RSA_OAEP_DECODE(sha int, p []byte, f []byte, RFS int) []byte {
olen := RFS - 1
hlen := sha
SEED := make([]byte, hlen)
seedlen := hlen
CHASH := make([]byte, hlen)
if olen < seedlen+hlen+1 {
return nil
}
DBMASK := make([]byte, olen-seedlen)
for i := 0; i < olen-seedlen; i++ {
DBMASK[i] = 0
}
if len(f) < RFS {
d := RFS - len(f)
for i := RFS - 1; i >= d; i-- {
f[i] = f[i-d]
}
for i := d - 1; i >= 0; i-- {
f[i] = 0
}
}
h := SPhashit(MC_SHA2, sha, p)
//h := hashit(sha, p, -1)
for i := 0; i < hlen; i++ {
CHASH[i] = h[i]
}
x := f[0]
for i := seedlen; i < olen; i++ {
DBMASK[i-seedlen] = f[i+1]
}
MGF1(sha, DBMASK, seedlen, SEED)
for i := 0; i < seedlen; i++ {
SEED[i] ^= f[i+1]
}
MGF1(sha, SEED, olen-seedlen, f)
for i := 0; i < olen-seedlen; i++ {
DBMASK[i] ^= f[i]
}
comp := 0
for i := 0; i < hlen; i++ {
comp |= int(CHASH[i] ^ DBMASK[i])
//if CHASH[i] != DBMASK[i] {
// comp = false
//}
}
m:=olen-seedlen-hlen
for i := 0; i < m; i++ {
DBMASK[i] = DBMASK[i+hlen]
}
for i := 0; i < hlen; i++ {
SEED[i] = 0
CHASH[i] = 0
}
k:=0
t:=0
for i:=0;i<m; i++ {
if t==0 && DBMASK[i]!=0 {
k=i
t=int(DBMASK[i])
}
}
/*
var k int
for k = 0; ; k++ {
if k >= m {
return nil
}
if DBMASK[k] != 0 {
break
}
}
t := DBMASK[k] */
if comp!=0 || x != 0 || t != 0x01 {
for i := 0; i < olen-seedlen; i++ {
DBMASK[i] = 0
}
return nil
}
var r = make([]byte, m-k-1)
for i := 0; i < m-k-1; i++ {
r[i] = DBMASK[i+k+1]
}
for i := 0; i < olen-seedlen; i++ {
DBMASK[i] = 0
}
return r
}
/*
MSG := []byte("abc")
DST := []byte("P256_XMD:SHA-256_SSWU_RO_TESTGEN")
OKM := core.XOF_Expand(core.SHA3_SHAKE128,48,DST,MSG)
fmt.Printf("OKM= "); printBinary(OKM[:])
OKM = core.XMD_Expand(core.MC_SHA2,32,48,DST,MSG)
fmt.Printf("OKM= "); printBinary(OKM[:])
func main() {
var ikm []byte
var salt []byte
var info []byte
for i:=0;i<22;i++ {ikm=append(ikm,0x0b)}
for i:=0;i<13;i++ {salt=append(salt,byte(i))}
for i:=0;i<10;i++ {info=append(info,byte(0xf0+i))}
prk:=core.HKDF_Extract(core.MC_SHA2,32,salt,ikm)
fmt.Printf("PRK= ")
for i := 0; i < len(prk); i++ {
fmt.Printf("%02x", prk[i])
}
okm:=core.HKDF_Expand(core.MC_SHA2,32,42,prk,info)
fmt.Printf("\nOKM= ")
for i := 0; i < len(okm); i++ {
fmt.Printf("%02x", okm[i])
}
}
*/

796
ec/bls48581/core/KYBER.go Normal file
View File

@ -0,0 +1,796 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* Kyber API */
package core
//import "fmt"
const KY_LGN uint = 8
const KY_DEGREE int = (1 << KY_LGN);
const KY_PRIME int32 = 0xD01
const KY_ONE int32 = 0x549 // R mod Q
const KY_QINV int32 = 62209 // q^(-1) mod 2^16
const KYBER_SECRET_CPA_SIZE_512 int = (2*(KY_DEGREE*3)/2)
const KYBER_PUBLIC_SIZE_512 int = (32+2*(KY_DEGREE*3)/2)
const KYBER_CIPHERTEXT_SIZE_512 int = ((10*2+4)*KY_DEGREE/8)
const KYBER_SECRET_CCA_SIZE_512 int = (KYBER_SECRET_CPA_SIZE_512+KYBER_PUBLIC_SIZE_512+64)
const KYBER_SHARED_SECRET_512 int = 32
const KYBER_SECRET_CPA_SIZE_768 int = (3*(KY_DEGREE*3)/2)
const KYBER_PUBLIC_SIZE_768 int = (32+3*(KY_DEGREE*3)/2)
const KYBER_CIPHERTEXT_SIZE_768 int = ((10*3+4)*KY_DEGREE/8)
const KYBER_SECRET_CCA_SIZE_768 int = (KYBER_SECRET_CPA_SIZE_768+KYBER_PUBLIC_SIZE_768+64)
const KYBER_SHARED_SECRET_768 int = 32
const KYBER_SECRET_CPA_SIZE_1024 int = (4*(KY_DEGREE*3)/2)
const KYBER_PUBLIC_SIZE_1024 int = (32+4*(KY_DEGREE*3)/2)
const KYBER_CIPHERTEXT_SIZE_1024 int = ((11*4+5)*KY_DEGREE/8)
const KYBER_SECRET_CCA_SIZE_1024 int = (KYBER_SECRET_CPA_SIZE_1024+KYBER_PUBLIC_SIZE_1024+64)
const KYBER_SHARED_SECRET_1024 int = 32
const KY_MAXK = 4;
// parameters for each security level
// K,eta1,eta2,du,dv,shared secret
var PARAMS_512 = [6]int{2,3,2,10,4,32}
var PARAMS_768 = [6]int{3,2,2,10,4,32}
var PARAMS_1024 = [6]int{4,2,2,11,5,32}
/* Translated from public domain reference implementation code - taken from https://github.com/pq-crystals/kyber */
var ZETAS = [256]int16{
-1044, -758, -359, -1517, 1493, 1422, 287, 202,
-171, 622, 1577, 182, 962, -1202, -1474, 1468,
573, -1325, 264, 383, -829, 1458, -1602, -130,
-681, 1017, 732, 608, -1542, 411, -205, -1571,
1223, 652, -552, 1015, -1293, 1491, -282, -1544,
516, -8, -320, -666, -1618, -1162, 126, 1469,
-853, -90, -271, 830, 107, -1421, -247, -951,
-398, 961, -1508, -725, 448, -1065, 677, -1275,
-1103, 430, 555, 843, -1251, 871, 1550, 105,
422, 587, 177, -235, -291, -460, 1574, 1653,
-246, 778, 1159, -147, -777, 1483, -602, 1119,
-1590, 644, -872, 349, 418, 329, -156, -75,
817, 1097, 603, 610, 1322, -1285, -1465, 384,
-1215, -136, 1218, -1335, -874, 220, -1187, -1659,
-1185, -1530, -1278, 794, -1510, -854, -870, 478,
-108, -308, 996, 991, 958, -1460, 1522, 1628}
func montgomery_reduce(a int32) int16 {
t := int16(a*KY_QINV)
t = int16((a - int32(t)*KY_PRIME) >> 16)
return t
}
func barrett_reduce(a int16) int16 {
v := int16(((int32(1)<<26) + KY_PRIME/2)/KY_PRIME)
vv := int32(v)
aa := int32(a)
t := int16((vv*aa + 0x2000000) >> 26);
t *= int16(KY_PRIME)
return int16(a - t);
}
func fqmul(a int16, b int16) int16 {
return montgomery_reduce(int32(a)*int32(b));
}
func ntt(r []int16) {
var j int
k := 1
for len := 128; len >= 2; len >>= 1 {
for start := 0; start < 256; start = j + len {
zeta := ZETAS[k]; k+=1
for j = start; j < start + len; j++ {
t := fqmul(zeta, r[j + len])
r[j + len] = r[j] - t
r[j] = r[j] + t
}
}
}
}
func invntt(r []int16) {
var j int
f := int16(1441) // mont^2/128
k := 127
for len := 2; len <= 128; len <<= 1 {
for start := 0; start < 256; start = j + len {
zeta := ZETAS[k]; k-=1
for j = start; j < start + len; j++ {
t := r[j]
r[j] = barrett_reduce(t + r[j + len])
r[j + len] = (r[j + len] - t)
r[j + len] = fqmul(zeta, r[j + len])
}
}
}
for j := 0; j < 256; j++ {
r[j] = fqmul(r[j], f)
}
}
func basemul(index int,r []int16, a []int16, b []int16,zeta int16) {
i:=index
j:=index+1
r[i] = fqmul(a[j], b[j])
r[i] = fqmul(r[i], zeta)
r[i] += fqmul(a[i], b[i])
r[j] = fqmul(a[i], b[j])
r[j] += fqmul(a[j], b[i])
}
func poly_reduce(r []int16) {
for i:=0;i<KY_DEGREE;i++ {
r[i] = barrett_reduce(r[i])
}
}
func poly_ntt(r []int16) {
ntt(r)
poly_reduce(r)
}
func poly_invntt(r []int16) {
invntt(r)
}
// Note r must be distinct from a and b
func poly_mul(r []int16, a []int16, b []int16) {
for i := 0; i < KY_DEGREE/4; i++ {
basemul(4*i,r,a,b,ZETAS[64+i])
basemul(4*i+2,r,a,b,-ZETAS[64+i])
}
}
func poly_tomont(r []int16) {
f := int32(KY_ONE);
for i:=0;i<KY_DEGREE;i++ {
r[i] = montgomery_reduce(int32(r[i])*f)
}
}
/* End of public domain reference code use */
// copy polynomial
func poly_copy(p1 []int16, p2 []int16) {
for i := 0; i < KY_DEGREE; i++ {
p1[i] = p2[i]
}
}
// zero polynomial
func poly_zero(p1 []int16) {
for i := 0; i < KY_DEGREE; i++ {
p1[i] = 0
}
}
// add polynomials
func poly_add(p1 []int16, p2 []int16, p3 []int16) {
for i := 0; i < KY_DEGREE; i++ {
p1[i] = (p2[i] + p3[i])
}
}
// subtract polynomials
func poly_sub(p1 []int16, p2 []int16, p3 []int16) {
for i := 0; i < KY_DEGREE; i++ {
p1[i] = (p2[i] - p3[i])
}
}
// Generate A[i][j] from rho
func expandAij(rho []byte,Aij []int16,i int,j int) {
sh := NewSHA3(SHA3_SHAKE128)
var buff [640]byte // should be plenty (?)
for m:=0;m<32;m++ {
sh.Process(rho[m])
}
sh.Process(byte(j&0xff))
sh.Process(byte(i&0xff))
sh.Shake(buff[:],640)
i = 0
j = 0
for j<KY_DEGREE {
d1 := int16(buff[i])+256*int16(buff[i+1]&0x0F);
d2 := int16(buff[i+1])/16+16*int16(buff[i+2]);
if (d1<int16(KY_PRIME)) {
Aij[j]=d1; j+=1
}
if (d2<int16(KY_PRIME) && j<KY_DEGREE) {
Aij[j]=d2; j+=1
}
i+=3
}
}
// get n-th bit from byte array
func getbit(b []byte,n int) int {
wd:=n/8;
bt:=n%8;
return int((b[wd]>>bt)&1)
}
// centered binomial distribution
func cbd(bts []byte,eta int,f []int16) {
for i:=0;i<KY_DEGREE;i++ {
a:=0; b:=0
for j:=0;j<eta;j++ {
a+=getbit(bts,2*i*eta+j)
b+=getbit(bts,2*i*eta+eta+j)
}
f[i]=int16(a-b)
}
}
// extract ab bits into word from dense byte stream
func nextword(ab int,t []byte,position []int) int16 {
ptr:=position[0] // index in array
bts:=position[1] // bit index in byte
r:=int16(t[ptr]>>bts)
mask:=int16((1<<ab)-1)
i:=0
gotbits:=8-bts // bits left in current byte
for gotbits<ab {
i++
w:=int16(t[ptr+i])
r|=w<<gotbits
gotbits+=8
}
bts+=ab
for bts>=8{
bts-=8
ptr++
}
w:=int16(r&mask)
position[0]=ptr
position[1]=bts
return w
}
// array t has ab active bits per word
// extract bytes from array of words
// if max!=0 then -max<=t[i]<=+max
func nextbyte16(ab int,t []int16,position []int) byte {
ptr:=position[0] // index in array
bts:=position[1] // bit index in byte
left:=ab-bts // number of bits left in this word
i:=0
k:=ptr%256
w:=t[k]; w+=(w>>15)&int16(KY_PRIME)
r:=int16(w>>bts);
for left<8 {
i++
w=t[k+i]; w+=(w>>15)&int16(KY_PRIME)
r|=w<<left
left+=ab
}
bts+=8
for bts>=ab {
bts-=ab;
ptr++;
}
position[0]=ptr
position[1]=bts
return byte(r&0xff);
}
// encode polynomial vector of length len with coefficients of length L, into packed bytes
func encode(t []int16,pos []int,L int,pack []byte,pptr int) {
k:=(KY_DEGREE*L)/8 // compressed length
for n:=0;n<k;n++ {
pack[n+pptr*k]=nextbyte16(L,t,pos)
}
}
func chk_encode(t []int16,pos []int,L int,pack []byte,pptr int) byte {
k:=(KY_DEGREE*L)/8
diff:=byte(0)
for n:=0;n<k;n++ {
m:=nextbyte16(L,t,pos)
diff|=(m^pack[n+pptr*k])
}
return diff;
}
// decode packed bytes into polynomial vector, with coefficients of length L
// pos indicates current position in byte array pack
func decode(pack []byte,L int,t []int16,pos []int) {
for i:=0;i<KY_DEGREE;i++ {
t[i]=nextword(L,pack,pos)
}
}
// compress polynomial coefficents in place, for polynomial vector of length len
func compress(t []int16,d int) {
twod:=int32(1<<d)
for i:=0;i<KY_DEGREE;i++ {
t[i]+=(t[i]>>15)&int16(KY_PRIME)
t[i]= int16(((twod*int32(t[i])+KY_PRIME/2)/KY_PRIME)&(twod-1))
}
}
// decompress polynomial coefficents in place, for polynomial vector of length len
func decompress(t []int16,d int) {
twod1:=int32(1<<(d-1))
for i:=0;i<KY_DEGREE;i++ {
t[i]=int16((KY_PRIME*int32(t[i])+twod1)>>d)
}
}
// input entropy, output key pair
func cpa_keypair(params [6]int,tau []byte,sk []byte,pk []byte) {
sh := NewSHA3(SHA3_HASH512)
var rho [32]byte
var sigma [33]byte
var buff [256]byte
ck:=params[0]
var r [KY_DEGREE]int16
var w [KY_DEGREE]int16
var Aij [KY_DEGREE]int16
var s= make([][KY_DEGREE]int16, ck)
var e= make([][KY_DEGREE]int16, ck)
var p= make([][KY_DEGREE]int16, ck)
eta1:=params[1]
public_key_size:=32+ck*(KY_DEGREE*3)/2
// secret_cpa_key_size:=ck*(KY_DEGREE*3)/2
for i:=0;i<32;i++ {
sh.Process(tau[i])
}
bf := sh.Hash();
for i:=0;i<32;i++ {
rho[i]=bf[i]
sigma[i]=bf[i+32]
}
sigma[32]=0 // N
// create s
for i:=0;i<ck;i++ {
sh= NewSHA3(SHA3_SHAKE256)
for j:=0;j<33;j++{
sh.Process(sigma[j])
}
sh.Shake(buff[:],64*eta1);
cbd(buff[:],eta1,s[i][:])
sigma[32]+=1
}
// create e
for i:=0;i<ck;i++ {
sh= NewSHA3(SHA3_SHAKE256)
for j:=0;j<33;j++ {
sh.Process(sigma[j])
}
sh.Shake(buff[:],64*eta1)
cbd(buff[:],eta1,e[i][:])
sigma[32]+=1
}
for k:=0;k<ck;k++ {
poly_ntt(s[k][:])
poly_ntt(e[k][:])
}
for i:=0;i<ck;i++ {
expandAij(rho[:],Aij[:],i,0)
poly_mul(r[:],Aij[:],s[0][:])
for j:=1;j<ck;j++ {
expandAij(rho[:],Aij[:],i,j)
poly_mul(w[:],s[j][:],Aij[:])
poly_add(r[:],r[:],w[:])
}
poly_reduce(r[:])
poly_tomont(r[:])
poly_add(p[i][:],r[:],e[i][:])
poly_reduce(p[i][:])
}
var pos [2]int
pos[0]=0; pos[1]=0
for i:=0;i<ck;i++ {
encode(s[i][:],pos[:],12,sk,i)
}
pos[0]=0; pos[1]=0
for i:=0;i<ck;i++ {
encode(p[i][:],pos[:],12,pk,i)
}
for i:=0;i<32;i++ {
pk[public_key_size-32+i]=rho[i]
}
}
// input 64 random bytes, output secret and public keys
func cca_keypair(params [6]int,randbytes64 []byte,sk []byte,pk []byte) {
sh:= NewSHA3(SHA3_HASH256)
sks:=(params[0]*(KY_DEGREE*3)/2)
pks:=(32+params[0]*(KY_DEGREE*3)/2)
cpa_keypair(params,randbytes64[0:32],sk,pk)
for i:=0;i<pks;i++ {
sk[sks+i]=pk[i]
}
for i:=0;i<pks;i++ {
sh.Process(pk[i])
}
h:=sh.Hash();
for i:=0;i<32;i++ {
sk[sks+pks+i]=h[i]
}
for i:=0;i<32;i++ {
sk[sks+pks+32+i]=randbytes64[32+i]
}
}
func cpa_base_encrypt(params [6]int,coins []byte,pk []byte,ss []byte,u [][256]int16, v []int16) {
var rho [32]byte
var sigma [33]byte
var buff [256]byte
ck:=params[0]
var r [KY_DEGREE]int16
var w [KY_DEGREE]int16
var Aij [KY_DEGREE]int16
var q= make([][KY_DEGREE]int16, ck)
var p= make([][KY_DEGREE]int16, ck)
eta1:=params[1]
eta2:=params[2]
du:=params[3]
dv:=params[4]
public_key_size:=32+ck*(KY_DEGREE*3)/2
for i:=0;i<32;i++ {
sigma[i]=coins[i] //i+6 //RAND_byte(RNG);
}
sigma[32]=0
for i:=0;i<32;i++ {
rho[i]=pk[public_key_size-32+i]
}
// create q
for i:=0;i<ck;i++ {
sh := NewSHA3(SHA3_SHAKE256)
for j:=0;j<33;j++ {
sh.Process(sigma[j])
}
sh.Shake(buff[:],64*eta1)
cbd(buff[:],eta1,q[i][:])
sigma[32]+=1
}
// create e1
for i:=0;i<ck;i++ {
sh := NewSHA3(SHA3_SHAKE256)
for j:=0;j<33;j++ {
sh.Process(sigma[j])
}
sh.Shake(buff[:],64*eta2);
cbd(buff[:],eta1,u[i][:]) // e1
sigma[32]+=1
}
for i:=0;i<ck;i++ {
poly_ntt(q[i][:])
}
for i:=0;i<ck;i++ {
expandAij(rho[:],Aij[:],0,i)
poly_mul(r[:],Aij[:],q[0][:])
for j:=1;j<ck;j++ {
expandAij(rho[:],Aij[:],j,i)
poly_mul(w[:],q[j][:],Aij[:])
poly_add(r[:],r[:],w[:])
}
poly_reduce(r[:]);
poly_invntt(r[:]);
poly_add(u[i][:],u[i][:],r[:]);
poly_reduce(u[i][:]);
}
var pos [2]int
pos[0]=0; pos[1]=0
for i:=0;i<ck;i++ {
decode(pk,12,p[i][:],pos[:])
}
poly_mul(v[:],p[0][:],q[0][:])
for i:=1;i<ck;i++ {
poly_mul(r[:],p[i][:],q[i][:])
poly_add(v[:],v[:],r[:])
}
poly_invntt(v[:])
// create e2
sh := NewSHA3(SHA3_SHAKE256)
for j:=0;j<33;j++ {
sh.Process(sigma[j])
}
sh.Shake(buff[:],64*eta2)
cbd(buff[:],eta1,w[:]) // e2
poly_add(v[:],v[:],w[:])
pos[0]=0; pos[1]=0
decode(ss,1,r[:],pos[:])
decompress(r[:],1)
poly_add(v[:],v[:],r[:])
poly_reduce(v[:])
for i:=0;i<ck;i++ {
compress(u[i][:],du)
}
compress(v[:],dv)
}
// Given input of entropy, public key and shared secret is an input, outputs ciphertext
func cpa_encrypt(params [6]int,coins []byte,pk []byte,ss []byte,ct []byte) {
ck:=params[0]
var v [KY_DEGREE]int16
var u= make([][KY_DEGREE]int16, ck)
du:=params[3]
dv:=params[4]
ciphertext_size:=(du*ck+dv)*KY_DEGREE/8
cpa_base_encrypt(params,coins,pk,ss,u,v[:])
var pos [2]int
pos[0]=0; pos[1]=0
for i:=0;i<ck;i++ {
encode(u[i][:],pos[:],du,ct,i)
}
encode(v[:],pos[:],dv,ct[ciphertext_size-(dv*KY_DEGREE/8):ciphertext_size],0)
}
// Re-encrypt and check that ct is OK (if so return is zero)
func cpa_check_encrypt(params [6]int,coins []byte,pk []byte,ss []byte,ct []byte) byte {
ck:=params[0]
var v [KY_DEGREE]int16
var u= make([][KY_DEGREE]int16, ck)
du:=params[3]
dv:=params[4]
ciphertext_size:=(du*ck+dv)*KY_DEGREE/8
d1:=byte(0)
cpa_base_encrypt(params,coins,pk,ss,u,v[:]);
var pos [2]int
pos[0]=0; pos[1]=0
for i:=0;i<ck;i++ {
d1|=chk_encode(u[i][:],pos[:],du,ct,i)
}
d2:=chk_encode(v[:],pos[:],dv,ct[ciphertext_size-(dv*KY_DEGREE/8):ciphertext_size],0);
if (d1|d2)==0 {
return 0
} else {
return byte(0xff)
}
}
func cca_encrypt(params [6]int,randbytes32 []byte,pk []byte,ss []byte,ct []byte) {
var coins [32]byte
ck:=params[0]
du:=params[3]
dv:=params[4]
shared_secret_size:=params[5]
public_key_size:=32+ck*(KY_DEGREE*3)/2
ciphertext_size:=(du*ck+dv)*KY_DEGREE/8
sh := NewSHA3(SHA3_HASH256)
for i:=0;i<32;i++{
sh.Process(randbytes32[i])
}
hm := sh.Hash();
sh = NewSHA3(SHA3_HASH256)
for i:=0;i<public_key_size;i++ {
sh.Process(pk[i])
}
h := sh.Hash()
sh = NewSHA3(SHA3_HASH512);
for i:=0;i<32;i++ {
sh.Process(hm[i])
}
for i:=0;i<32;i++ {
sh.Process(h[i])
}
g:= sh.Hash()
for i:=0;i<32;i++ {
coins[i]=g[i+32]
}
cpa_encrypt(params,coins[:],pk,hm,ct)
sh = NewSHA3(SHA3_HASH256)
for i:=0;i<ciphertext_size;i++ {
sh.Process(ct[i])
}
h= sh.Hash();
sh = NewSHA3(SHA3_SHAKE256)
for i:=0;i<32;i++ {
sh.Process(g[i])
}
for i:=0;i<32;i++ {
sh.Process(h[i])
}
sh.Shake(ss[:],shared_secret_size)
}
func cpa_decrypt(params [6]int,SK []byte,CT []byte,SS []byte) {
ck:=params[0]
var w [KY_DEGREE]int16
var v [KY_DEGREE]int16
var r [KY_DEGREE]int16
var u= make([][KY_DEGREE]int16, ck)
var s= make([][KY_DEGREE]int16, ck)
du:=params[3]
dv:=params[4]
//shared_secret_size:=params[5]
var pos [2]int
pos[0]=0; pos[1]=0
for i:=0;i<ck;i++ {
decode(CT,du,u[i][:],pos[:])
}
decode(CT,dv,v[:],pos[:]);
for i:=0;i<ck;i++ {
decompress(u[i][:],du)
}
decompress(v[:],dv)
pos[0]=0; pos[1]=0
for i:=0;i<ck;i++ {
decode(SK,12,s[i][:],pos[:])
}
poly_ntt(u[0][:]);
poly_mul(w[:],u[0][:],s[0][:]);
for i:=1;i<ck;i++ {
poly_ntt(u[i][:])
poly_mul(r[:],u[i][:],s[i][:])
poly_add(w[:],w[:],r[:])
}
poly_reduce(w[:]);
poly_invntt(w[:]);
poly_sub(v[:],v[:],w[:]);
compress(v[:],1);
pos[0]=0; pos[1]=0;
encode(v[:],pos[:],1,SS,0);
}
func cca_decrypt(params [6]int,SK []byte,CT []byte,SS []byte) {
ck:=params[0]
du:=params[3]
dv:=params[4]
secret_cpa_key_size:=ck*(KY_DEGREE*3)/2
public_key_size:=32+ck*(KY_DEGREE*3)/2
shared_secret_size:=params[5]
ciphertext_size:=(du*ck+dv)*KY_DEGREE/8
var h [32]byte
var z [32]byte
var m [32]byte
var coins [32]byte
PK:=SK[secret_cpa_key_size:secret_cpa_key_size+public_key_size]
for i:=0;i<32;i++ {
h[i]=SK[secret_cpa_key_size+public_key_size+i]
}
for i:=0;i<32;i++ {
z[i]=SK[secret_cpa_key_size+public_key_size+32+i]
}
cpa_decrypt(params,SK,CT,m[:])
sh := NewSHA3(SHA3_HASH512)
for i:=0;i<32;i++ {
sh.Process(m[i])
}
for i:=0;i<32;i++ {
sh.Process(h[i])
}
g := sh.Hash()
for i:=0;i<32;i++ {
coins[i]=g[i+32]
}
mask:=cpa_check_encrypt(params,coins[:],PK,m[:],CT)
for i:=0;i<32;i++ {
g[i]^=(g[i]^z[i])&mask // substitute z for Kb on failure
}
sh = NewSHA3(SHA3_HASH256)
for i:=0;i<ciphertext_size;i++ {
sh.Process(CT[i])
}
hh:=sh.Hash()
sh = NewSHA3(SHA3_SHAKE256);
for i:=0;i<32;i++ {
sh.Process(g[i])
}
for i:=0;i<32;i++ {
sh.Process(hh[i])
}
sh.Shake(SS,shared_secret_size)
}
func KYBER_keypair512(r64 []byte,SK []byte,PK []byte) {
cca_keypair(PARAMS_512,r64,SK,PK)
}
func KYBER_encrypt512(r32 []byte,PK []byte,SS []byte,CT []byte) {
cca_encrypt(PARAMS_512,r32,PK,SS,CT)
}
func KYBER_decrypt512(SK []byte,CT []byte,SS []byte) {
cca_decrypt(PARAMS_512,SK,CT,SS)
}
func KYBER_keypair768(r64 []byte,SK []byte,PK []byte) {
cca_keypair(PARAMS_768,r64,SK,PK)
}
func KYBER_encrypt768(r32 []byte,PK []byte,SS []byte,CT []byte) {
cca_encrypt(PARAMS_768,r32,PK,SS,CT)
}
func KYBER_decrypt768(SK []byte,CT []byte,SS []byte) {
cca_decrypt(PARAMS_768,SK,CT,SS)
}
func KYBER_keypair1024(r64 []byte,SK []byte,PK []byte) {
cca_keypair(PARAMS_1024,r64,SK,PK)
}
func KYBER_encrypt1024(r32 []byte,PK []byte,SS []byte,CT []byte) {
cca_encrypt(PARAMS_1024,r32,PK,SS,CT)
}
func KYBER_decrypt1024(SK []byte,CT []byte,SS []byte) {
cca_decrypt(PARAMS_1024,SK,CT,SS)
}

178
ec/bls48581/core/RAND.go Normal file
View File

@ -0,0 +1,178 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/*
* Cryptographic strong random number generator
*
* Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
* Slow - but secure
*
* See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
*/
/* Marsaglia & Zaman Random number generator constants */
package core
//import "fmt"
const rand_NK int = 21
const rand_NJ int = 6
const rand_NV int = 8
type RAND struct {
ira [rand_NK]uint32 /* random number... */
rndptr int
borrow uint32
pool_ptr int
pool [32]byte
}
/* Terminate and clean up */
func (R *RAND) Clean() { /* kill internal state */
R.pool_ptr = 0
R.rndptr = 0
for i := 0; i < 32; i++ {
R.pool[i] = 0
}
for i := 0; i < rand_NK; i++ {
R.ira[i] = 0
}
R.borrow = 0
}
func NewRAND() *RAND {
R := new(RAND)
R.Clean()
return R
}
func (R *RAND) sbrand() uint32 { /* Marsaglia & Zaman random number generator */
R.rndptr++
if R.rndptr < rand_NK {
return R.ira[R.rndptr]
}
R.rndptr = 0
k := rand_NK - rand_NJ
for i := 0; i < rand_NK; i++ { /* calculate next NK values */
if k == rand_NK {
k = 0
}
t := R.ira[k]
pdiff := t - R.ira[i] - R.borrow
if pdiff < t {
R.borrow = 0
}
if pdiff > t {
R.borrow = 1
}
R.ira[i] = pdiff
k++
}
return R.ira[0]
}
func (R *RAND) sirand(seed uint32) {
var m uint32 = 1
R.borrow = 0
R.rndptr = 0
R.ira[0] ^= seed
for i := 1; i < rand_NK; i++ { /* fill initialisation vector */
in := (rand_NV * i) % rand_NK
R.ira[in] ^= m /* note XOR */
t := m
m = seed - m
seed = t
}
for i := 0; i < 10000; i++ {
R.sbrand()
} /* "warm-up" & stir the generator */
}
func (R *RAND) fill_pool() {
sh := NewHASH256()
for i := 0; i < 128; i++ {
sh.Process(byte(R.sbrand() & 0xff))
}
W := sh.Hash()
for i := 0; i < 32; i++ {
R.pool[i] = W[i]
}
R.pool_ptr = 0
}
func pack(b [4]byte) uint32 { /* pack 4 bytes into a 32-bit Word */
return (((uint32(b[3])) & 0xff) << 24) | ((uint32(b[2]) & 0xff) << 16) | ((uint32(b[1]) & 0xff) << 8) | (uint32(b[0]) & 0xff)
}
/* Initialize RNG with some real entropy from some external source */
func (R *RAND) Seed(rawlen int, raw []byte) { /* initialise from at least 128 byte string of raw random entropy */
var b [4]byte
sh := NewHASH256()
R.pool_ptr = 0
for i := 0; i < rand_NK; i++ {
R.ira[i] = 0
}
if rawlen > 0 {
for i := 0; i < rawlen; i++ {
sh.Process(raw[i])
}
digest := sh.Hash()
/* initialise PRNG from distilled randomness */
for i := 0; i < 8; i++ {
b[0] = digest[4*i]
b[1] = digest[4*i+1]
b[2] = digest[4*i+2]
b[3] = digest[4*i+3]
R.sirand(pack(b))
}
}
R.fill_pool()
}
/* get random byte */
func (R *RAND) GetByte() byte {
r := R.pool[R.pool_ptr]
R.pool_ptr++
if R.pool_ptr >= 32 {
R.fill_pool()
}
return byte(r & 0xff)
}
/* test main program */
/*
func main() {
var raw [100]byte
rng:=NewRAND()
rng.Clean()
for i:=0;i<100;i++ {raw[i]=byte(i)}
rng.Seed(100,raw[:])
for i:=0;i<1000;i++ {
fmt.Printf("%03d ",rng.GetByte())
}
}
*/

302
ec/bls48581/core/SHA3.go Normal file
View File

@ -0,0 +1,302 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/*
* Implementation of the Secure Hashing Algorithm (SHA-384)
*
* Generates a 384 bit message digest. It should be impossible to come
* come up with two messages that hash to the same value ("collision free").
*
* For use with byte-oriented messages only.
*/
//package main
package core
//import "fmt"
const SHA3_HASH224 int = 28
const SHA3_HASH256 int = 32
const SHA3_HASH384 int = 48
const SHA3_HASH512 int = 64
const SHA3_SHAKE128 int = 16
const SHA3_SHAKE256 int = 32
const sha3_ROUNDS int = 24
var sha3_RC = [24]uint64{
0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000,
0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003,
0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A,
0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008}
type SHA3 struct {
length uint64
rate int
len int
s [5][5]uint64
}
/* functions */
func sha3_ROTL(x uint64, n uint64) uint64 {
return (((x) << n) | ((x) >> (64 - n)))
}
func (H *SHA3) transform() { /* basic transformation step */
var c [5]uint64
var d [5]uint64
var b [5][5]uint64
for k := 0; k < sha3_ROUNDS; k++ {
c[0] = H.s[0][0] ^ H.s[0][1] ^ H.s[0][2] ^ H.s[0][3] ^ H.s[0][4]
c[1] = H.s[1][0] ^ H.s[1][1] ^ H.s[1][2] ^ H.s[1][3] ^ H.s[1][4]
c[2] = H.s[2][0] ^ H.s[2][1] ^ H.s[2][2] ^ H.s[2][3] ^ H.s[2][4]
c[3] = H.s[3][0] ^ H.s[3][1] ^ H.s[3][2] ^ H.s[3][3] ^ H.s[3][4]
c[4] = H.s[4][0] ^ H.s[4][1] ^ H.s[4][2] ^ H.s[4][3] ^ H.s[4][4]
d[0] = c[4] ^ sha3_ROTL(c[1], 1)
d[1] = c[0] ^ sha3_ROTL(c[2], 1)
d[2] = c[1] ^ sha3_ROTL(c[3], 1)
d[3] = c[2] ^ sha3_ROTL(c[4], 1)
d[4] = c[3] ^ sha3_ROTL(c[0], 1)
for i := 0; i < 5; i++ {
for j := 0; j < 5; j++ {
H.s[i][j] ^= d[i]
}
}
b[0][0] = H.s[0][0]
b[1][3] = sha3_ROTL(H.s[0][1], 36)
b[2][1] = sha3_ROTL(H.s[0][2], 3)
b[3][4] = sha3_ROTL(H.s[0][3], 41)
b[4][2] = sha3_ROTL(H.s[0][4], 18)
b[0][2] = sha3_ROTL(H.s[1][0], 1)
b[1][0] = sha3_ROTL(H.s[1][1], 44)
b[2][3] = sha3_ROTL(H.s[1][2], 10)
b[3][1] = sha3_ROTL(H.s[1][3], 45)
b[4][4] = sha3_ROTL(H.s[1][4], 2)
b[0][4] = sha3_ROTL(H.s[2][0], 62)
b[1][2] = sha3_ROTL(H.s[2][1], 6)
b[2][0] = sha3_ROTL(H.s[2][2], 43)
b[3][3] = sha3_ROTL(H.s[2][3], 15)
b[4][1] = sha3_ROTL(H.s[2][4], 61)
b[0][1] = sha3_ROTL(H.s[3][0], 28)
b[1][4] = sha3_ROTL(H.s[3][1], 55)
b[2][2] = sha3_ROTL(H.s[3][2], 25)
b[3][0] = sha3_ROTL(H.s[3][3], 21)
b[4][3] = sha3_ROTL(H.s[3][4], 56)
b[0][3] = sha3_ROTL(H.s[4][0], 27)
b[1][1] = sha3_ROTL(H.s[4][1], 20)
b[2][4] = sha3_ROTL(H.s[4][2], 39)
b[3][2] = sha3_ROTL(H.s[4][3], 8)
b[4][0] = sha3_ROTL(H.s[4][4], 14)
for i := 0; i < 5; i++ {
for j := 0; j < 5; j++ {
H.s[i][j] = b[i][j] ^ (^b[(i+1)%5][j] & b[(i+2)%5][j])
}
}
H.s[0][0] ^= sha3_RC[k]
}
}
/* Initialise Hash function */
func (H *SHA3) Init(olen int) {
for i := 0; i < 5; i++ {
for j := 0; j < 5; j++ {
H.s[i][j] = 0
}
}
H.length = 0
H.len = olen
H.rate = 200 - 2*olen
}
func NewSHA3(olen int) *SHA3 {
H := new(SHA3)
H.Init(olen)
return H
}
func NewSHA3copy(HC *SHA3) *SHA3 {
H := new(SHA3)
for i := 0; i < 5; i++ {
for j := 0; j < 5; j++ {
H.s[i][j] = HC.s[i][j]
}
}
H.length = HC.length
H.len = HC.len
H.rate = HC.rate
return H
}
/* process a single byte */
func (H *SHA3) Process(byt byte) { /* process the next message byte */
cnt := int(H.length % uint64(H.rate))
b := cnt % 8
cnt /= 8
i := cnt % 5
j := cnt / 5
H.s[i][j] ^= uint64(byt&0xff) << uint(8*b)
H.length++
if int(H.length%uint64(H.rate)) == 0 {
H.transform()
}
}
/* process an array of bytes */
func (H *SHA3) Process_array(b []byte) {
for i := 0; i < len(b); i++ {
H.Process((b[i]))
}
}
/* process a 32-bit integer */
func (H *SHA3) Process_num(n int32) {
H.Process(byte((n >> 24) & 0xff))
H.Process(byte((n >> 16) & 0xff))
H.Process(byte((n >> 8) & 0xff))
H.Process(byte(n & 0xff))
}
/* squeeze the sponge */
func (H *SHA3) Squeeze(buff []byte, olen int) {
// olen:=len(buff)
done := false
m := 0
/* extract by columns */
for {
for j := 0; j < 5; j++ {
for i := 0; i < 5; i++ {
el := H.s[i][j]
for k := 0; k < 8; k++ {
buff[m] = byte(el & 0xff)
m++
if m >= olen || (m%H.rate) == 0 {
done = true
break
}
el >>= 8
}
if done {
break
}
}
if done {
break
}
}
if m >= olen {
break
}
done = false
H.transform()
}
}
/* Generate Hash */
func (H *SHA3) Hash() []byte { /* generate a SHA3 hash of appropriate size */
var digest [64]byte
q := H.rate - int(H.length%uint64(H.rate))
if q == 1 {
H.Process(0x86)
} else {
H.Process(0x06)
for int(H.length%uint64(H.rate)) != (H.rate - 1) {
H.Process(0x00)
}
H.Process(0x80)
}
H.Squeeze(digest[:], H.len)
return digest[0:H.len]
}
func (H *SHA3) Continuing_Hash() []byte {
sh := NewSHA3copy(H)
return sh.Hash()
}
func (H *SHA3) Shake(hash []byte, olen int) { /* generate a SHA3 hash of appropriate size */
q := H.rate - int(H.length%uint64(H.rate))
if q == 1 {
H.Process(0x9f)
} else {
H.Process(0x1f)
for int(H.length%uint64(H.rate)) != H.rate-1 {
H.Process(0x00)
}
H.Process(0x80)
}
H.Squeeze(hash, olen)
}
func (H *SHA3) Continuing_Shake(hash []byte, olen int) {
sh := NewSHA3copy(H)
sh.Shake(hash, olen)
}
/* test program: should produce digest */
//916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18
//afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185
//98be04516c04cc73593fef3ed0352ea9f6443942d6950e29a372a681c3deaf4535423709b02843948684e029010badcc0acd8303fc85fdad3eabf4f78cae165635f57afd28810fc2
/*
func main() {
test := []byte("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
var digest [172]byte
sh:=NewSHA3(SHA3_HASH256)
for i:=0;i<len(test);i++ {
sh.Process(test[i])
}
sh.Hash(digest[:])
for i:=0;i<32;i++ {fmt.Printf("%02x",digest[i])}
fmt.Printf("\n");
sh=NewSHA3(SHA3_HASH512)
for i:=0;i<len(test);i++ {
sh.Process(test[i])
}
sh.Hash(digest[:])
for i:=0;i<64;i++ {fmt.Printf("%02x",digest[i])}
fmt.Printf("\n");
sh=NewSHA3(SHA3_SHAKE256)
for i:=0;i<len(test);i++ {
sh.Process(test[i])
}
sh.Shake(digest[:],72)
for i:=0;i<72;i++ {fmt.Printf("%02x",digest[i])}
fmt.Printf("\n");
} */

164
ec/bls48581/core/SHARE.go Normal file
View File

@ -0,0 +1,164 @@
/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* Shamir threshold secret sharing module */
/* Split any byte array into number of shares < 256 */
/* Specify number of shares required for recovery - nsr */
/* See TestMPIN.go for an example of use */
package core
var ptab = [...]byte{
1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1}
var ltab = [...]byte{
0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,
125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,
101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,
150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,
102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,
126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,
175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,
44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,
127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,
204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,
151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,
83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,
103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7}
type SHARE struct {
ID byte // Unique Share ID
NSR byte // Number of Shares required for recovery
B []byte // Share
}
func add(x byte, y byte) byte {
return (x ^ y)
}
func mul(x byte, y byte) byte { /* x.y= AntiLog(Log(x) + Log(y)) */
ix := int(x) & 0xff
iy := int(y) & 0xff
lx := int(ltab[ix]) & 0xff
ly := int(ltab[iy]) & 0xff
if x != 0 && y != 0 {
return ptab[(lx+ly)%255]
} else {
return byte(0)
}
}
func inv(x byte) byte {
ix := int(x) & 0xff
lx := int(ltab[ix]) & 0xff
return ptab[255-lx]
}
/* Lagrange interpolation */
func interpolate(n int, x []byte, y []byte) byte {
yp := byte(0)
for i := 0; i < n; i++ {
p := byte(1)
for j := 0; j < n; j++ {
if i != j {
p = mul(p, mul(x[j], inv(add(x[i], x[j]))))
}
}
yp = add(yp, mul(p, y[i]))
}
return yp
}
/* Return a share of M */
/* input id - Unique share ID */
/* input nsr - Number of shares required for recovery */
/* input Message M to be shared */
/* input Random seed R */
/* return share structure */
func NewSHARE(id int, nsr int, M []byte, R []byte) *SHARE {
var S = new(SHARE)
if id < 1 || id >= 256 || nsr < 2 || nsr >= 256 {
S.ID = 0
S.NSR = 0
S.B = nil
return S
}
S.ID = byte(id)
S.NSR = byte(nsr)
m := len(M)
S.B = make([]byte, m)
rng := NewRAND()
rng.Clean()
rng.Seed(len(R), R)
for j := 0; j < m; j++ {
x := byte(S.ID)
S.B[j] = M[j]
for n := 1; n < nsr; n++ {
S.B[j] = add(S.B[j], mul(rng.GetByte(), x))
x = mul(x, S.ID)
}
}
return S
}
/* recover M from shares */
func Recover(S []*SHARE) []byte {
m := len(S[0].B)
nsr := int(S[0].NSR)
if nsr != len(S) {
return nil
}
for i := 1; i < nsr; i++ {
if int(S[i].NSR) != nsr || len(S[i].B) != m {
return nil
}
}
x := make([]byte, nsr)
y := make([]byte, nsr)
M := make([]byte, m)
for j := 0; j < m; j++ {
for i := 0; i < nsr; i++ {
x[i] = S[i].ID
y[i] = S[i].B[j]
}
M[j] = interpolate(nsr, x, y)
}
return M
}

540
feldman/feldman.go Normal file
View File

@ -0,0 +1,540 @@
package feldman
import (
"bytes"
"crypto/rand"
"crypto/sha256"
"fmt"
"source.quilibrium.com/quilibrium/ceremonyclient/ec/bls48581"
)
// This will not be used in the initial ceremony, but will be used in a end of ceremony event
type FeldmanECP struct {
threshold int
total int
id int
fragsForCounterparties map[int][]byte
fragsFromCounterparties map[int]*bls48581.BIG
zkpok *bls48581.BIG
secret *bls48581.BIG
scalar *bls48581.BIG
publicKey *bls48581.ECP
point *bls48581.ECP
randomCommitmentPoint *bls48581.ECP
round FeldmanRound
zkcommitsFromCounterparties map[int][]byte
pointsFromCounterparties map[int]*bls48581.ECP
}
type FeldmanReveal struct {
Point []byte
RandomCommitmentPoint []byte
ZKPoK []byte
}
type FeldmanECP8 struct {
threshold int
total int
id int
fragsForCounterparties map[int][]byte
fragsFromCounterparties map[int]*bls48581.BIG
zkpok *bls48581.BIG
secret *bls48581.BIG
scalar *bls48581.BIG
publicKey *bls48581.ECP8
point *bls48581.ECP8
randomCommitmentPoint *bls48581.ECP8
round FeldmanRound
zkcommitsFromCounterparties map[int][]byte
pointsFromCounterparties map[int]*bls48581.ECP8
}
type FeldmanRound int
const (
FELDMAN_ROUND_UNINITIALIZED = FeldmanRound(0)
FELDMAN_ROUND_INITIALIZED = FeldmanRound(1)
FELDMAN_ROUND_COMMITTED = FeldmanRound(2)
FELDMAN_ROUND_REVEALED = FeldmanRound(3)
FELDMAN_ROUND_RECONSTRUCTED = FeldmanRound(4)
)
func NewFeldmanECP(threshold, total, id int, secret *bls48581.BIG) (*FeldmanECP, error) {
return &FeldmanECP{
threshold: threshold,
total: total,
id: id,
fragsForCounterparties: make(map[int][]byte),
fragsFromCounterparties: make(map[int]*bls48581.BIG),
zkpok: nil,
secret: secret,
scalar: nil,
publicKey: bls48581.ECP_generator(),
point: bls48581.ECP_generator(),
round: FELDMAN_ROUND_UNINITIALIZED,
zkcommitsFromCounterparties: make(map[int][]byte),
pointsFromCounterparties: make(map[int]*bls48581.ECP),
}, nil
}
func NewFeldmanECP8(threshold, total, id int, secret *bls48581.BIG) (*FeldmanECP8, error) {
return &FeldmanECP8{
threshold: threshold,
total: total,
id: id,
fragsForCounterparties: make(map[int][]byte),
fragsFromCounterparties: make(map[int]*bls48581.BIG),
zkpok: nil,
secret: secret,
scalar: nil,
publicKey: bls48581.ECP8_generator(),
point: bls48581.ECP8_generator(),
round: FELDMAN_ROUND_UNINITIALIZED,
zkcommitsFromCounterparties: make(map[int][]byte),
pointsFromCounterparties: make(map[int]*bls48581.ECP8),
}, nil
}
func (f *FeldmanECP) SamplePolynomial() {
coeffs := append([]*bls48581.BIG{}, f.secret)
for i := 0; i < f.threshold-1; i++ {
secretBytes := make([]byte, int(bls48581.MODBYTES))
rand.Read(secretBytes)
secret := bls48581.FromBytes(secretBytes)
coeffs = append(coeffs, secret)
}
for i := 1; i <= f.total; i++ {
result := coeffs[len(coeffs)-1]
for j := len(coeffs) - 2; j >= 0; j-- {
result = bls48581.Modadd(
coeffs[j],
bls48581.Modmul(
result,
bls48581.NewBIGint(i),
bls48581.NewBIGints(bls48581.CURVE_Order),
),
bls48581.NewBIGints(bls48581.CURVE_Order),
)
}
if i == f.id {
f.scalar = result
} else {
fragBytes := make([]byte, int(bls48581.MODBYTES))
result.ToBytes(fragBytes)
f.fragsForCounterparties[i] = fragBytes
}
}
f.round = FELDMAN_ROUND_INITIALIZED
}
func (f *FeldmanECP) Scalar() *bls48581.BIG {
return f.scalar
}
func (f *FeldmanECP) GetPolyFrags() map[int][]byte {
return f.fragsForCounterparties
}
func (f *FeldmanECP) SetPolyFragForParty(id int, frag []byte) []byte {
f.fragsFromCounterparties[id] = bls48581.FromBytes(frag)
if len(f.fragsFromCounterparties) == f.total-1 {
for _, v := range f.fragsFromCounterparties {
f.scalar = bls48581.Modadd(f.scalar, v, bls48581.NewBIGints(bls48581.CURVE_Order))
}
f.point = f.point.Mul(f.scalar)
randCommitmentBytes := make([]byte, int(bls48581.MODBYTES))
rand.Read(randCommitmentBytes)
randCommitment := bls48581.FromBytes(randCommitmentBytes)
f.randomCommitmentPoint = f.publicKey.Mul(randCommitment)
publicPointBytes := make([]byte, bls48581.MODBYTES+1)
randCommitmentPointBytes := make([]byte, bls48581.MODBYTES+1)
f.point.ToBytes(publicPointBytes, true)
f.randomCommitmentPoint.ToBytes(randCommitmentPointBytes, true)
challenge := sha256.Sum256(append(append([]byte{}, publicPointBytes...), randCommitmentPointBytes...))
challengeBig := bls48581.FromBytes(challenge[:])
challengeBig.Mod(bls48581.NewBIGints(bls48581.CURVE_Order))
f.zkpok = bls48581.Modadd(
bls48581.Modmul(
f.scalar,
challengeBig,
bls48581.NewBIGints(bls48581.CURVE_Order),
),
randCommitment,
bls48581.NewBIGints(bls48581.CURVE_Order),
)
zkpokBytes := make([]byte, int(bls48581.MODBYTES))
f.zkpok.ToBytes(zkpokBytes)
zkcommit := sha256.Sum256(append(append([]byte{}, randCommitmentPointBytes...), zkpokBytes...))
f.round = FELDMAN_ROUND_COMMITTED
return zkcommit[:]
}
return []byte{}
}
func (f *FeldmanECP) ReceiveCommitments(id int, zkcommit []byte) *FeldmanReveal {
f.zkcommitsFromCounterparties[id] = zkcommit
if len(f.zkcommitsFromCounterparties) == f.total-1 {
publicPointBytes := make([]byte, bls48581.MODBYTES+1)
randCommitmentPointBytes := make([]byte, bls48581.MODBYTES+1)
f.point.ToBytes(publicPointBytes, true)
f.randomCommitmentPoint.ToBytes(randCommitmentPointBytes, true)
f.round = FELDMAN_ROUND_REVEALED
zkpokBytes := make([]byte, int(bls48581.MODBYTES))
f.zkpok.ToBytes(zkpokBytes)
return &FeldmanReveal{
Point: publicPointBytes,
RandomCommitmentPoint: randCommitmentPointBytes,
ZKPoK: zkpokBytes,
}
}
return nil
}
func (f *FeldmanECP) Recombine(id int, reveal *FeldmanReveal) {
counterpartyPoint := bls48581.ECP_fromBytes(reveal.Point)
if counterpartyPoint.Equals(bls48581.ECP_generator()) {
fmt.Printf("invalid point from %d", id)
return
}
counterpartyRandomCommitmentPoint := bls48581.ECP_fromBytes(reveal.RandomCommitmentPoint)
if counterpartyRandomCommitmentPoint.Equals(bls48581.ECP_generator()) {
fmt.Printf("invalid commitment point from %d", id)
return
}
counterpartyZKPoK := bls48581.FromBytes(reveal.ZKPoK)
counterpartyZKCommit := f.zkcommitsFromCounterparties[id]
challenge := sha256.Sum256(append(append([]byte{}, reveal.Point...), reveal.RandomCommitmentPoint...))
challengeBig := bls48581.FromBytes(challenge[:])
challengeBig.Mod(bls48581.NewBIGints(bls48581.CURVE_Order))
proof := f.publicKey.Mul(counterpartyZKPoK)
counterpartyRandomCommitmentPoint.Add(counterpartyPoint.Mul(challengeBig))
if !proof.Equals(counterpartyRandomCommitmentPoint) {
fmt.Printf("invalid proof from %d", id)
return
}
verifier := sha256.Sum256(append(append([]byte{}, reveal.RandomCommitmentPoint...), reveal.ZKPoK...))
if !bytes.Equal(counterpartyZKCommit, verifier[:]) {
fmt.Printf("%d changed zkpok after commit", id)
return
}
f.pointsFromCounterparties[id] = counterpartyPoint
if len(f.pointsFromCounterparties) == f.total-1 {
f.pointsFromCounterparties[f.id] = f.point
for i := 1; i <= f.total-f.threshold; i++ {
reconstructedSum := bls48581.ECP_generator()
for j := i; j <= f.threshold+i; j++ {
coefficientNumerator := bls48581.NewBIGint(1)
coefficientDenominator := bls48581.NewBIGint(1)
for k := i; k <= f.threshold+i; k++ {
if j != k {
k := bls48581.NewBIGint(k)
coefficientNumerator = bls48581.Modmul(
coefficientNumerator,
k,
bls48581.NewBIGints(bls48581.CURVE_Order),
)
kj := bls48581.Modadd(
k,
bls48581.NewBIGints(bls48581.CURVE_Order).Minus(bls48581.NewBIGint(j)),
bls48581.NewBIGints(bls48581.CURVE_Order),
)
coefficientDenominator = bls48581.Modmul(
coefficientDenominator,
kj,
bls48581.NewBIGints(bls48581.CURVE_Order),
)
}
}
coefficientDenominator.Invmodp(bls48581.NewBIGints(bls48581.CURVE_Order))
reconstructedFragment := f.pointsFromCounterparties[j].Mul(
bls48581.Modmul(
coefficientNumerator,
coefficientDenominator,
bls48581.NewBIGints(bls48581.CURVE_Order),
),
)
if reconstructedSum.Equals(bls48581.ECP_generator()) {
reconstructedSum = reconstructedFragment
} else {
reconstructedSum.Add(reconstructedFragment)
}
}
if f.publicKey.Equals(bls48581.ECP_generator()) {
f.publicKey = reconstructedSum
} else if !f.publicKey.Equals(reconstructedSum) {
fmt.Println("key mismatch")
fmt.Println(f.publicKey.ToString())
fmt.Println(reconstructedSum.ToString())
return
}
}
f.round = FELDMAN_ROUND_RECONSTRUCTED
}
}
func (f *FeldmanECP) PublicKey() *bls48581.ECP {
key := bls48581.NewECP()
key.Copy(f.publicKey)
return key
}
func (f *FeldmanECP) PublicKeyBytes() []byte {
publicKeyBytes := make([]byte, bls48581.MODBYTES+1)
f.publicKey.ToBytes(publicKeyBytes, true)
return publicKeyBytes
}
func (f *FeldmanECP8) SamplePolynomial() {
coeffs := append([]*bls48581.BIG{}, f.secret)
for i := 0; i < f.threshold-1; i++ {
secretBytes := make([]byte, int(bls48581.MODBYTES))
rand.Read(secretBytes)
secret := bls48581.FromBytes(secretBytes)
coeffs = append(coeffs, secret)
}
for i := 1; i <= f.total; i++ {
result := coeffs[len(coeffs)-1]
for j := len(coeffs) - 2; j >= 0; j-- {
result = bls48581.Modadd(
coeffs[j],
bls48581.Modmul(
result,
bls48581.NewBIGint(i),
bls48581.NewBIGints(bls48581.CURVE_Order),
),
bls48581.NewBIGints(bls48581.CURVE_Order),
)
}
if i == f.id {
f.scalar = result
} else {
fragBytes := make([]byte, int(bls48581.MODBYTES))
result.ToBytes(fragBytes)
f.fragsForCounterparties[i] = fragBytes
}
}
f.round = FELDMAN_ROUND_INITIALIZED
}
func (f *FeldmanECP8) GetPolyFrags() map[int][]byte {
return f.fragsForCounterparties
}
func (f *FeldmanECP8) SetPolyFragForParty(id int, frag []byte) []byte {
f.fragsFromCounterparties[id] = bls48581.FromBytes(frag)
if len(f.fragsFromCounterparties) == f.total-1 {
for _, v := range f.fragsFromCounterparties {
f.scalar = bls48581.Modadd(f.scalar, v, bls48581.NewBIGints(bls48581.CURVE_Order))
}
f.point = f.point.Mul(f.scalar)
randCommitmentBytes := make([]byte, int(bls48581.MODBYTES))
rand.Read(randCommitmentBytes)
randCommitment := bls48581.FromBytes(randCommitmentBytes)
f.randomCommitmentPoint = f.publicKey.Mul(randCommitment)
publicPointBytes := make([]byte, bls48581.MODBYTES*8+1)
randCommitmentPointBytes := make([]byte, bls48581.MODBYTES*8+1)
f.point.ToBytes(publicPointBytes, true)
f.randomCommitmentPoint.ToBytes(randCommitmentPointBytes, true)
challenge := sha256.Sum256(append(append([]byte{}, publicPointBytes...), randCommitmentPointBytes...))
challengeBig := bls48581.FromBytes(challenge[:])
challengeBig.Mod(bls48581.NewBIGints(bls48581.CURVE_Order))
f.zkpok = bls48581.Modadd(
bls48581.Modmul(
f.scalar,
challengeBig,
bls48581.NewBIGints(bls48581.CURVE_Order),
),
randCommitment,
bls48581.NewBIGints(bls48581.CURVE_Order),
)
zkpokBytes := make([]byte, int(bls48581.MODBYTES))
f.zkpok.ToBytes(zkpokBytes)
zkcommit := sha256.Sum256(append(append([]byte{}, randCommitmentPointBytes...), zkpokBytes...))
f.round = FELDMAN_ROUND_COMMITTED
return zkcommit[:]
}
return []byte{}
}
func (f *FeldmanECP8) Scalar() *bls48581.BIG {
return f.scalar
}
func (f *FeldmanECP8) ReceiveCommitments(id int, zkcommit []byte) *FeldmanReveal {
f.zkcommitsFromCounterparties[id] = zkcommit
if len(f.zkcommitsFromCounterparties) == f.total-1 {
publicPointBytes := make([]byte, bls48581.MODBYTES*8+1)
randCommitmentPointBytes := make([]byte, bls48581.MODBYTES*8+1)
f.point.ToBytes(publicPointBytes, true)
f.randomCommitmentPoint.ToBytes(randCommitmentPointBytes, true)
f.round = FELDMAN_ROUND_REVEALED
zkpokBytes := make([]byte, int(bls48581.MODBYTES))
f.zkpok.ToBytes(zkpokBytes)
return &FeldmanReveal{
Point: publicPointBytes,
RandomCommitmentPoint: randCommitmentPointBytes,
ZKPoK: zkpokBytes,
}
}
return nil
}
func (f *FeldmanECP8) Recombine(id int, reveal *FeldmanReveal) {
counterpartyPoint := bls48581.ECP8_fromBytes(reveal.Point)
if counterpartyPoint.Equals(bls48581.ECP8_generator()) {
fmt.Printf("invalid point from %d", id)
return
}
counterpartyRandomCommitmentPoint := bls48581.ECP8_fromBytes(reveal.RandomCommitmentPoint)
if counterpartyRandomCommitmentPoint.Equals(bls48581.ECP8_generator()) {
fmt.Printf("invalid commitment point from %d", id)
return
}
counterpartyZKPoK := bls48581.FromBytes(reveal.ZKPoK)
counterpartyZKCommit := f.zkcommitsFromCounterparties[id]
challenge := sha256.Sum256(append(append([]byte{}, reveal.Point...), reveal.RandomCommitmentPoint...))
challengeBig := bls48581.FromBytes(challenge[:])
challengeBig.Mod(bls48581.NewBIGints(bls48581.CURVE_Order))
proof := f.publicKey.Mul(counterpartyZKPoK)
counterpartyRandomCommitmentPoint.Add(counterpartyPoint.Mul(challengeBig))
if !proof.Equals(counterpartyRandomCommitmentPoint) {
fmt.Printf("invalid proof from %d", id)
return
}
verifier := sha256.Sum256(append(append([]byte{}, reveal.RandomCommitmentPoint...), reveal.ZKPoK...))
if !bytes.Equal(counterpartyZKCommit, verifier[:]) {
fmt.Printf("%d changed zkpok after commit", id)
return
}
f.pointsFromCounterparties[id] = counterpartyPoint
if len(f.pointsFromCounterparties) == f.total-1 {
f.pointsFromCounterparties[f.id] = f.point
for i := 1; i <= f.total-f.threshold; i++ {
reconstructedSum := bls48581.ECP8_generator()
for j := i; j <= f.threshold+i; j++ {
coefficientNumerator := bls48581.NewBIGint(1)
coefficientDenominator := bls48581.NewBIGint(1)
for k := i; k <= f.threshold+i; k++ {
if j != k {
k := bls48581.NewBIGint(k)
coefficientNumerator = bls48581.Modmul(
coefficientNumerator,
k,
bls48581.NewBIGints(bls48581.CURVE_Order),
)
kj := bls48581.Modadd(
k,
bls48581.NewBIGints(bls48581.CURVE_Order).Minus(bls48581.NewBIGint(j)),
bls48581.NewBIGints(bls48581.CURVE_Order),
)
coefficientDenominator = bls48581.Modmul(
coefficientDenominator,
kj,
bls48581.NewBIGints(bls48581.CURVE_Order),
)
}
}
coefficientDenominator.Invmodp(bls48581.NewBIGints(bls48581.CURVE_Order))
reconstructedFragment := f.pointsFromCounterparties[j].Mul(
bls48581.Modmul(
coefficientNumerator,
coefficientDenominator,
bls48581.NewBIGints(bls48581.CURVE_Order),
),
)
if reconstructedSum.Equals(bls48581.ECP8_generator()) {
reconstructedSum = reconstructedFragment
} else {
reconstructedSum.Add(reconstructedFragment)
}
}
if f.publicKey.Equals(bls48581.ECP8_generator()) {
f.publicKey = reconstructedSum
} else if !f.publicKey.Equals(reconstructedSum) {
fmt.Println("key mismatch")
fmt.Println(f.publicKey.ToString())
fmt.Println(reconstructedSum.ToString())
return
}
}
f.round = FELDMAN_ROUND_RECONSTRUCTED
}
}
func (f *FeldmanECP8) PublicKey() *bls48581.ECP8 {
key := bls48581.NewECP8()
key.Copy(f.publicKey)
return key
}
func (f *FeldmanECP8) PublicKeyBytes() []byte {
publicKeyBytes := make([]byte, bls48581.MODBYTES*8+1)
f.publicKey.ToBytes(publicKeyBytes, true)
return publicKeyBytes
}

7
go.mod Normal file
View File

@ -0,0 +1,7 @@
module source.quilibrium.com/quilibrium/ceremonyclient
go 1.18
require github.com/cloudflare/circl v1.3.2
require golang.org/x/sys v0.6.0 // indirect

4
go.sum Normal file
View File

@ -0,0 +1,4 @@
github.com/cloudflare/circl v1.3.2 h1:VWp8dY3yH69fdM7lM6A1+NhhVoDu9vqK0jOgmkQHFWk=
github.com/cloudflare/circl v1.3.2/go.mod h1:+CauBF6R70Jqcyl8N2hC8pAXYbWkGIezuSbuGLtRhnw=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

71
main.go Normal file
View File

@ -0,0 +1,71 @@
package main
import (
"fmt"
"time"
)
var HOST string = "https://ceremony.quilibrium.com:8443/"
func main() {
PrintLogo()
PrintVersion()
fmt.Println("Checking sequencer...")
state := GetSequencerState()
for state != SEQUENCER_ACCEPTING {
fmt.Println("Sequencer currently not accepting new contributions, waiting...")
time.Sleep(30 * time.Second)
state = GetSequencerState()
}
JoinLobby()
batchSize := uint(32)
for batch := uint(0); batch < 65536/batchSize; batch++ {
Bootstrap(batch, batchSize)
fmt.Printf("batch: %d\n", batch)
}
fmt.Println("New Pubkey: ")
fmt.Println(bcj.PotPubKey)
ContributeAndGetVoucher()
}
func PrintLogo() {
fmt.Println(" %#########")
fmt.Println(" #############################")
fmt.Println(" ########################################&")
fmt.Println(" ###############################################")
fmt.Println(" &#####################% %######################")
fmt.Println(" ################# #################")
fmt.Println(" ############### ###############")
fmt.Println(" ############# ##############")
fmt.Println(" ############# ############&")
fmt.Println(" ############ ############")
fmt.Println(" ########### ########## &###########")
fmt.Println(" ########### ############## ###########")
fmt.Println(" ########### ############## ##########&")
fmt.Println(" ########## ############## ##########")
fmt.Println("%########## ########## ##########")
fmt.Println("##########& ##########")
fmt.Println("########## &#########")
fmt.Println("##########& ####### ####### ##########")
fmt.Println(" ########## &######################### ##########")
fmt.Println(" ########## ##############% ############## &##########")
fmt.Println(" %########## &############## ############### ##########")
fmt.Println(" ########### ############### ##############% ###########")
fmt.Println(" ###########& ########## ############### ########")
fmt.Println(" ############ ##### ##############% ####")
fmt.Println(" ############ ###############")
fmt.Println(" ############## ##############%")
fmt.Println(" ############### ###############")
fmt.Println(" #################& ##############%")
fmt.Println(" #########################&&&############# ###############")
fmt.Println(" ########################################% ############")
fmt.Println(" ####################################### ########")
fmt.Println(" ############################# ##")
}
func PrintVersion() {
fmt.Println(" ")
fmt.Println(" Quilibrium Ceremony Client - CLI - v1.0.0")
}

1
quil_voucher.hex Normal file
View File

@ -0,0 +1 @@
654990bfacd0d2702f318089f73b838c64f79b0369840bdff6e1f6b8c3aa2698585c61a0e35794afb9365a4f5ed9c841a62eb9f35d29aa50486780552dd2293cb865905d120047905b98f55bb96a8e2b1e960807a3a0f5b236b7819799a64f7c0a52f8c754dc5086373bb0ce2702ebfba900