mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-04 09:57:27 +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