mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-10-31 14:47:29 +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
	 Cassandra Heart
						Cassandra Heart