mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-12-26 00:25:17 +00:00
Initial commit of CLI client
This commit is contained in:
commit
e6ef405c62
65808
basis.json
Normal file
65808
basis.json
Normal file
File diff suppressed because it is too large
Load Diff
251
bootstrap.go
Normal file
251
bootstrap.go
Normal 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
27
ec/bls48581/ARCH.go
Normal 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
1023
ec/bls48581/BIG.go
Normal file
File diff suppressed because it is too large
Load Diff
155
ec/bls48581/BLS256.go
Normal file
155
ec/bls48581/BLS256.go
Normal 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
34
ec/bls48581/CONFIG_BIG.go
Normal 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)
|
76
ec/bls48581/CONFIG_CURVE.go
Normal file
76
ec/bls48581/CONFIG_CURVE.go
Normal 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
|
47
ec/bls48581/CONFIG_FIELD.go
Normal file
47
ec/bls48581/CONFIG_FIELD.go
Normal 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
298
ec/bls48581/DBIG.go
Normal 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
381
ec/bls48581/ECDH.go
Normal 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
1850
ec/bls48581/ECP.go
Normal file
File diff suppressed because it is too large
Load Diff
1074
ec/bls48581/ECP8.go
Normal file
1074
ec/bls48581/ECP8.go
Normal file
File diff suppressed because it is too large
Load Diff
760
ec/bls48581/FP.go
Normal file
760
ec/bls48581/FP.go
Normal 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
616
ec/bls48581/FP16.go
Normal 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
505
ec/bls48581/FP2.go
Normal 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
759
ec/bls48581/FP4.go
Normal 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
1189
ec/bls48581/FP48.go
Normal file
File diff suppressed because it is too large
Load Diff
781
ec/bls48581/FP8.go
Normal file
781
ec/bls48581/FP8.go
Normal 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
327
ec/bls48581/HPKE.go
Normal 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
202
ec/bls48581/MPIN256.go
Normal 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
978
ec/bls48581/PAIR8.go
Normal 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
74
ec/bls48581/ROM.go
Normal 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
835
ec/bls48581/core/AES.go
Normal 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();
|
||||
}
|
||||
*/
|
1290
ec/bls48581/core/DILITHIUM.go
Normal file
1290
ec/bls48581/core/DILITHIUM.go
Normal file
File diff suppressed because it is too large
Load Diff
457
ec/bls48581/core/GCM.go
Normal file
457
ec/bls48581/core/GCM.go
Normal 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
233
ec/bls48581/core/HASH256.go
Normal 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
247
ec/bls48581/core/HASH384.go
Normal 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
247
ec/bls48581/core/HASH512.go
Normal 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
909
ec/bls48581/core/HMAC.go
Normal 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
796
ec/bls48581/core/KYBER.go
Normal 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
178
ec/bls48581/core/RAND.go
Normal 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
302
ec/bls48581/core/SHA3.go
Normal 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
164
ec/bls48581/core/SHARE.go
Normal 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
540
feldman/feldman.go
Normal 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
7
go.mod
Normal 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
4
go.sum
Normal 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
71
main.go
Normal 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
1
quil_voucher.hex
Normal file
@ -0,0 +1 @@
|
||||
654990bfacd0d2702f318089f73b838c64f79b0369840bdff6e1f6b8c3aa2698585c61a0e35794afb9365a4f5ed9c841a62eb9f35d29aa50486780552dd2293cb865905d120047905b98f55bb96a8e2b1e960807a3a0f5b236b7819799a64f7c0a52f8c754dc5086373bb0ce2702ebfba900
|
Loading…
Reference in New Issue
Block a user