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